System_Alert_Window - How to Get This Permission Automatically on Android 6.0 and Targetsdkversion 23

SYSTEM_ALERT_WINDOW - How to get this permission automatically on Android 6.0 and targetSdkVersion 23

It is a new behaviour introduced in Marshmallow 6.0.1.

Every app that requests the SYSTEM_ALERT_WINDOW permission and that is installed through the Play Store (version 6.0.5 or higher is required), will have granted the permission automatically.

If instead the app is sideloaded, the permission is not automatically granted. You can try to download and install the Evernote APK from apkmirror.com. As you can see you need to manually grant the permission in Settings -> Apps -> Draw over other apps.

These are the commits [1] [2] that allow the Play Store to give the automatic grant of the SYSTEM_ALERT_WINDOW permission.

Runtime permission for SYSTEM_ALERT_WINDOW

there is no runtime permission/dialog for this purpose, you have to pass user to app settings

public boolean checkStartPermissionRequest() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
return false; // above will start new Activity with proper app setting
}
}
return true; // on lower OS versions granted during apk installation
}

more info HERE

Android SYSTEM_ALERT_WINDOW permission

It is a new behaviour introduced in Marshmallow 6.0.1.

Every app that requests the SYSTEM_ALERT_WINDOW permission and that is installed through the Play Store (version 6.0.5 or higher is required), will have granted the permission automatically.

If instead the app is sideloaded, the permission is not automatically granted. You can try to download and install the Evernote APK from apkmirror.com. As you can see you need to manually grant the permission in Settings -> Apps -> Draw over other apps.

[The above information is from this post.]

If you want the app to be sideloaded, you show manually show a prompt and direct the user to enable Draw over other apps permissions from the settings. Have a look at Requesting permissions

How to handle SYSTEM_ALERT_WINDOW permission not being auto-granted on some pre-Marshmallow devices

Checking if you have the drawOverlays permission is safer using this:

@SuppressLint("NewApi")
public static boolean canDrawOverlayViews(Context con){
if(Build.VERSION.SDK_INT< Build.VERSION_CODES.LOLLIPOP){return true;}
try {
return Settings.canDrawOverlays(con);
}
catch(NoSuchMethodError e){
return canDrawOverlaysUsingReflection(con);
}
}


public static boolean canDrawOverlaysUsingReflection(Context context) {

try {

AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Class clazz = AppOpsManager.class;
Method dispatchMethod = clazz.getMethod("checkOp", new Class[] { int.class, int.class, String.class });
//AppOpsManager.OP_SYSTEM_ALERT_WINDOW = 24
int mode = (Integer) dispatchMethod.invoke(manager, new Object[] { 24, Binder.getCallingUid(), context.getApplicationContext().getPackageName() });

return AppOpsManager.MODE_ALLOWED == mode;

} catch (Exception e) { return false; }

}

Custom ROMs can have altered the OS so that that Settings.canDrawOverlays() is not available. This happened to me with Xiaomi devices and the app crashed.

Requesting the permission:

@SuppressLint("InlinedApi")
public static void requestOverlayDrawPermission(Activity act, int requestCode){
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + act.getPackageName()));
act.startActivityForResult(intent, requestCode);

}

Return to app after requesting SYSTEM_ALERT_WINDOW permission

It appears that there is no way to observe this setting, so there is really no elegant solution for this.

What you can do is just check the setting once per second using a Handler after you send the user to the Settings screen.

You can't truly "go back" programmatically from the Settings screen, so the only option is to re-launch the Activity and clear the previous ones (otherwise it will go back to the Settings screen on back press afterwards).

With the example below, within one second of enabling the setting, it will re-launch MainActivity.

First define the Runnable:

Handler handler = new Handler();
Runnable checkOverlaySetting = new Runnable() {
@Override
@TargetApi(23)
public void run() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return;
}
if (Settings.canDrawOverlays(MainActivity.this)) {
//You have the permission, re-launch MainActivity
Intent i = new Intent(MainActivity.this, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
return;
}
handler.postDelayed(this, 1000);
}
};

Then start the Runnable when you send the user to the Settings screen:

Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
//Add this here:
handler.postDelayed(checkOverlaySetting, 1000);

Note that you should set a timeout or max tries so that it doesn't go on forever if the user does not enable the overlay setting.



Related Topics



Leave a reply



Submit