How to Handle System_Alert_Window Permission Not Being Auto-Granted on Some Pre-Marshmallow Devices

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);

}

How to check permission SYSTEM_ALERT_WINDOW is granted on Android Lollipop?

in MIUI use

public static boolean isMiuiFloatWindowOpAllowed(@NonNull Context context) {
final int version = Build.VERSION.SDK_INT;

if (version >= 19) {
return checkOp(context, OP_SYSTEM_ALERT_WINDOW); //See AppOpsManager.OP_SYSTEM_ALERT_WINDOW=24 /*@hide/
} else {
return (context.getApplicationInfo().flags & 1<<27) == 1;
}
}

public static boolean checkOp(Context context, int op, String packageName, int uid) {
final int version = Build.VERSION.SDK_INT;

if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
return (AppOpsManager.MODE_ALLOWED == (Integer) ReflectUtils.invokeMethod(manager, "checkOp", op, uid, packageName));
} catch (Exception e) {
e.printStackTrace();
}
} else {
Flog.e("Below API 19 cannot invoke!");
}
return false;
}

ReflectUtils.java

public static Object invokeMethod(@NonNull Object receiver, String methodName, Object... methodArgs) throws Exception {
Class<?>[] argsClass = null;
if (methodArgs != null && methodArgs.length != 0) {
int length = methodArgs.length;
argsClass = new Class[length];
for (int i=0; i<length; i++) {
argsClass[i] = getBaseTypeClass(methodArgs[i].getClass());
}
}

Method method = receiver.getClass().getMethod(methodName, argsClass);
return method.invoke(receiver, methodArgs);
}

Android drawing on top of other apps 23 API

Not a direct solution to the problem, but a workaround - set android:targetSdkVersion to 22.

This will still work fine with Android 6 but you will lose a few features that came with API23.

Is it possible to automatically grant dangerous permissions to pre-installed OS apps?

Yes it is possible. Check this documentation on privileged permission whitelisting.

IIRC, the user can still revoke these permissions so your app must be prepared to work without this permission. All it guarantees is that the permission is granted to the app out of the box.



Related Topics



Leave a reply



Submit