Reputation: 281
I am trying to open an activity from a class that extends Service. I am performing this task when the app is not in foreground/not being used. I can see in the logs that my service class triggered start activity with Intent.FLAG_ACTIVITY_NEW_TASK flag. But the activity does not open. But when the service triggers the same activity when the app is in foreground/being used, the activity opens.
After few searches I found out that I need to manually give the permission "display popup windows while running in the background android" in the other permissions section in the app settings.
The display over other apps permission SYSTEM_ALERT_WINDOW only gives access to "Display popup window".
In the image above, SYSTEM_ALERT_WINDOW will only grant you access to "Display popup window" and this works fine if the app is in foreground/being used but the permission marked in red if granted will give you access to open any activity directly from a class extending Service.
How do I check or ask the user to give "Display popup windows while running in the background" permission? or Is this permission restricted?
I see apps like Whatsapp have this checked by default.
Upvotes: 30
Views: 27548
Reputation: 1681
Since there is no official way to check the "Display pop-up windows while running in the background" permission, I used a little trick to check the permissions.
Check if the app can draw overlays like below and then if the device is xiaomi navigate the user to the specific settings screen like below.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
if ("xiaomi".equals(Build.MANUFACTURER.toLowerCase(Locale.ROOT))) {
final Intent intent =new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
intent.putExtra("extra_pkgname", getPackageName());
new AlertDialog.Builder(this)
.setTitle("Please Enable the additional permissions")
.setMessage("You will not receive notifications while the app is in background if you disable these permissions")
.setPositiveButton("Go to Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
startActivity(intent);
}
})
.setIcon(android.R.drawable.ic_dialog_info)
.setCancelable(false)
.show();
} else {
Intent overlaySettings = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
startActivityForResult(overlaySettings, OVERLAY_REQUEST_CODE);
}
}
}
Upvotes: 7
Reputation: 37061
Here is a working way to find out if it's granted (tested on MIUI 14.0.3)
public static final int OP_BACKGROUND_START_ACTIVITY = 10021;
@SuppressWarnings("JavaReflectionMemberAccess")
@TargetApi(19)
public static boolean isBackgroundStartActivityPermissionGranted(Context context) {
try {
AppOpsManager mgr = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Method m = AppOpsManager.class.getMethod("checkOpNoThrow", int.class, int.class, String.class);
int result = (int) m.invoke(mgr, OP_BACKGROUND_START_ACTIVITY, android.os.Process.myUid(), context.getPackageName());
return result == AppOpsManager.MODE_ALLOWED;
} catch (Exception e) {
Log.d("Exception", e.toString());
}
return true;
}
You can find an even more detailed code here: https://github.com/zoontek/react-native-permissions/issues/412#issuecomment-1590376224
Upvotes: 2
Reputation: 46
I manage to work around my project by following this gist https://gist.github.com/0awawa0/65bf88e43159750f596da194ed923522
@ReactMethod()
public void isMiuiCanDisplayOverlay(Promise ps){
boolean isXiaomi = XiaomiUtilities.isMIUI();
boolean isGranted = XiaomiUtilities.isPermissionGranted(reactContext,XiaomiUtilities.OP_BACKGROUND_START_ACTIVITY);
if(isXiaomi){
ps.resolve(isGranted);
}else{
ps.resolve(true);
}
}
@ReactMethod()
public void openMiuiDisplayOverlayPermission(Promise ps){
boolean isXiaomi = XiaomiUtilities.isMIUI();
try{
if(isXiaomi){
XiaomiUtilities.goToMiuiPermissionActivity_V8(reactContext);
ps.resolve(true);
}else{
ps.resolve(false);
}
}catch (Exception e){
String version = XiaomiUtilities.getMiuiVersion();
Log.d(LOG_TAG,"Cannot open Miui Display Pop-up window while running in background" + version + e.toString());
}
}
code above I created in react native to bridge to javascript
Upvotes: 2
Reputation: 1009
This is common problem in Xiaomi devices for developers,
the solution we have for the moment is to redirect users to other permissions
screen and let the users give the permission manually :
if ("xiaomi" == Build.MANUFACTURER.toLowerCase(Locale.ROOT)) {
val intent = Intent("miui.intent.action.APP_PERM_EDITOR")
intent.setClassName("com.miui.securitycenter",
"com.miui.permcenter.permissions.PermissionsEditorActivity")
intent.putExtra("extra_pkgname", getPackageName())
startActivity(intent)
}
You can use Settings.canDrawOverlays(this)
to test only if the user has given the Display pop-up windows which means the app can draw over the system ui.
The other two permissions can not be verified if the user has given them or not :
services
and broadcast
Upvotes: 11
Reputation: 760
Try the following code.
Intent rIntent = context.getPackageManager()
.getLaunchIntentForPackage(context.getPackageName() );
PendingIntent intent = PendingIntent.getActivity(
context, 0,
rIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.RTC, System.currentTimeMillis(), intent);
System.exit(2);
Upvotes: 0