I'm developing a music player application. In which, I want to display a small floating button on screen for play/pause event when app is minimized(paused). (Functionality like face book messenger chat head). It works perfectly fine on devices which has SDK < 23. But in Device with SDK >= 23, It asks for permission only 1st time when app in installed.
If permission is granted, it also perfectly displays floating button. But once the app is closed and again started, It is not showing floating button any more.
my code for opening permission dialogue box is:
public final static int REQUEST_CODE = 100;
public void checkDrawOverlayPermission() {
/** check if we already have permission to draw over other apps */
if (!Settings.canDrawOverlays(this)) {
/** if not construct intent to request permission */
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
/** request permission via start activity for result */
startActivityForResult(intent, REQUEST_CODE);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
/** check if received result code
is equal our requested code for draw permission */
if (requestCode == REQUEST_CODE) {
if (Settings.canDrawOverlays(this)) {
// continue here - permission was granted
if(isServiceRunning != true){
isServiceRunning = true;
intent12 = new Intent(this, notificationService.class);
bindService(intent12, notificationConnection, Context.BIND_AUTO_CREATE);
startService(intent12);
}
}
}
}
I'm displaying floating button when app is paused(when home button or back button is pressed to minimize the app). So I'm calling this checkDrawOverlayPermission() method in onPause() method of my apps mainActivity, like this:
#Override
protected void onPause() {
super.onPause();
if (Build.VERSION.SDK_INT >= 23) {
checkDrawOverlayPermission();
} else {
if(isServiceRunning != true){
isServiceRunning = true;
intent12 = new Intent(this, notificationService.class);
bindService(intent12, notificationConnection, Context.BIND_AUTO_CREATE);
startService(intent12);
}
}
}
But I can't understand what I'm missing here. I think code for checking permission is ok because first time it displays floating button on the screen along with asking permission in a small dialogue. Please help. Thanks!
You are not doing anything if the permission is already given in SDK > 23.
Add an else part to the checkDrawOverlayPermission method like this.
public void checkDrawOverlayPermission() {
/** check if we already have permission to draw over other apps */
if (!Settings.canDrawOverlays(this)) { // WHAT IF THIS EVALUATES TO FALSE.
/** if not construct intent to request permission */
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
/** request permission via start activity for result */
startActivityForResult(intent, REQUEST_CODE);
} else { // ADD THIS.
// Add code to bind and start the service directly.
}
}
Related
In Java, I am trying to implement a feature where only the admin (person who knows the device password) can access an information screen and when they click on a button within the app in the MainActivity, the lock screen will appear as a form of authentication and display another activity screen on success. Is this possible?
So far, I noticed that the authentication only displays when I open the app and not when I press the button in an onClickListener. Most of the solutions I've seen are doing it this way. I have the code in MainActivity within an onCreate() method.
MainActivity
ActivityResultLauncher<Intent> activityResultLaunch = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
// There are no request codes
Intent data = result.getData();
} else {
finish();
}
}
});
start_end_button_add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
authScreen(activityResultLaunch);
}
});
private void authScreen(ActivityResultLauncher<Intent> activityResultLaunch) {
KeyguardManager mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
if (!mKeyguardManager.isKeyguardSecure()) {
// Show a message that the user hasn't set up a lock screen.
} else {
Intent intent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null);
if (intent != null) {
startActivityForResult.launch(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
}
}
Intent intent = new Intent(DetectorActivity.this, SearchActivity.class);
startActivity(intent);
finish();
}
Currently, the app immediately goes to the SearchActivity class without having the lock screen displayed in between. Even if I get into the app after PIN code entered is a success, it still doesn't get into the activityResultLaunch success condition as per the new implementation referenced here by user Martin Zeitler.
Reference:
https://mobile-security.gitbook.io/mobile-security-testing-guide/android-testing-guide/0x05f-testing-local-authentication#:~:text=In%20Android%2C%20there%20are%20two,and%20the%20Biometric%20Authentication%20flow.
i want to make a swiggy type app. i have integrated gmail login in my login screen and it changes to dashboard activity on success but when i click on account tab it goes back to dashboard screen instead of account activity. pls help......
login screen
dashboard
if you want any portion of code just comment and i will update
//login screen part
//check if already signed in using google
account = GoogleSignIn.getLastSignedInAccount(this);
if(account!=null) {
finish();
Intent intent = new Intent(this, DashboardActivity.class);
startActivity(intent);
return;
}
//onclicklistener added
//method
private void googleSignin() {
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, RC_SIGN_IN);
}
onActivity result(//params provided){
if(googleLogin){
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
// The Task returned from this call is always completed, no need to attach
// a listener.
googleLogin = false; //set to false so that it can be set true again if login is actually successful
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
handleSignInResult(task);
}
}
}
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
// Signed in successfully, show authenticated UI.
sessionManager.setLogin(true);
googleLogin = true;
Intent intent = new Intent(this,DashboardActivity.class);
intent.putExtra("googleLogin", googleLogin);
startActivity(intent);
finish();
}
//Dashboard part
Intent i = new Intent(DashboardActivity.this ,MyAccountActivity.class);
i.putExtra("googleLogin", googleLogin);
startActivity(i);
//myaccount part
if(googleLogin){
GoogleSignInAccount acct = GoogleSignIn.getLastSignedInAccount(this);
if (acct != null) {
String personName = acct.getDisplayName();
//System.out.println(personName); working fine
account_name.setText(personName);
String personEmail = acct.getEmail();
//System.out.println(personEmail); fine
account_email.setText(personEmail);
account_mobile.setText("+91 1234567890");
// System.out.println(googleLogin);
// System.out.println(fbLogin);
}
}
solved this problem.
the issue was gmail was not able to provide account details for use when i tried to display them in MY ACCOUNT activity that i integrated in my app, thats why it kept on getting crashed. the code was correct thats why it wasnt giving any error i even tried logging it. there it showed correct details but still it wasnt displaying the result in text views.
so what i did was use shared preferences. everytime the user logs in using gmail, the details are stored in them and i retrieve it in MY ACCOUNT activity and yes it displayed the results correctly.
let me know if you need any more help.
I am setting device ownership for my app using dpm command (dpm set-device-admin) and in my MainActivity.java I have placed the code below :
DevicePolicyManager myDevicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
// get this app package name
ComponentName mDPM = new ComponentName(this, MyAdmin.class);
if (myDevicePolicyManager.isDeviceOwnerApp(this.getPackageName())) {
// get this app package name
String[] packages = {this.getPackageName()};
// mDPM is the admin package, and allow the specified packages to lock task
myDevicePolicyManager.setLockTaskPackages(mDPM, packages);
startLockTask();
} else {
Toast.makeText(getApplicationContext(),"Unable to auto pin - not device owner", Toast.LENGTH_LONG).show();
}
Whenever my app starts it auto pins itself, making it unable for users to leave. Without setting device ownership I am able to leave 'pinned' state by long pressing back button and providing the pin.
When I set the ownership this actions is overrided - all I see is 'App is pinned : unpinning isn't allowed on this device'. Is there any way to enable unpinning by providing pin as without device ownership? I still need it to make sure it autopins without any prompts.
Possible answer:
Override single/long key press, request pin and unpin app on success
MainActivity.java
#Override
public void onBackPressed() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
KeyguardManager km = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
Intent intent = km.createConfirmDeviceCredentialIntent(null, null);
if (intent != null) {
startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
}
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
// unpin the app
if (resultCode == RESULT_OK) {
stopLockTask();
} else {
// nope
Toast.makeText(this, "Pin is not correct", Toast.LENGTH_SHORT).show();
}
}
}
I'm trying to get permission for drawing overlays in marshmallow.
In marshmallow we must give run-time permission for drawing overlays and I have implemented. What issue I'm getting is once I have given the permission from my app next time if I check with following code, if(Settings.canDrawOverlays(getApplicationContext()) it returns false.
But in settings (Draw over other apps) my app is Checked. Here I have provided my code of lib activity.
if(Settings.canDrawOverlays(getApplicationContext())&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
Toast.makeText(getApplicationContext(), "Windows Overlay allowed" , Toast.LENGTH_SHORT).show();
startService(new Intent(this, FABService.class));
finish();
}
else{
startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION), 1);
}
and my onActivityResult is,
#TargetApi(Build.VERSION_CODES.M)
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
/** check if received result code
is equal our requested code for draw permission */
if (requestCode == 1) {
// * if so check once again if we have permission /
if (Settings.canDrawOverlays(getApplicationContext()) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// continue here - permission was granted
Toast.makeText(getApplicationContext(), "Windows Overlay allowed", Toast.LENGTH_LONG).show();
startService(new Intent(this, FABService.class));
finish();
}
}
}
These code I have implemented in lib of that application. Any 1 can help me where I have went wrong.
Put permission in Manifest
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Use this for Overlay permission
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(myIntent);
}
in my app i have some layout to edit a task and select a RingTone and save it into the database.
When i update the task, i one also to update the ringtone name. I use for that the ringtone picker, start a new Intent and get the selected ringtone uri inside the onActivityResult() method.
The problem ist, every time when i click to pick the new RingTone the page reload and i lose all the populated data in my formular, that come from the database.
How can i solve this problem. Is there a way to open the ringtone picker without reload the complete activity after selecting the ringtone?
Here is how i open picker:
protected void openRingtoneDialog() {
final Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_ALL);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, getString(R.string.ringtone_choose));
if (mAlarmTonUri != null) {
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, mAlarmTonUri);
}
else {
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, (Uri) null);
}
startActivityForResult(intent, RINGTONE_RESULT);
}
and here, how i get the selected ringtone.
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
String ringTonTitle = "";
// Get the result from RingtoneActivity
if (resultCode == RESULT_OK && requestCode == RINGTONE_RESULT) {
mAlarmTonUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
if (mAlarmTonUri != null) {
mAlarmTonValue = mAlarmTonUri.toString();
ringTonTitle = RingtoneManager.getRingtone(this, mAlarmTonUri).getTitle(this);
}
else {
ringTonTitle = "unknow";
}
mAlarmTonTextView.setText(ringTonTitle);
}
Thank you for your help!
I ran into this in my app. I had overridden onResume to reload my view in case changes were made while my app wasn't on top. Coming back from the ringtone picker was setting off my onResume. For me, it was safe to move everything from onResume to onStart. There it would run when my app came to the foreground or first started but not when the ringtone picker was dismissed.