问题描述
我正在为父母开发MDM应用,以控制孩子们的设备,如果执行了禁止的操作,它会使用权限SYSTEM_ALERT_WINDOW
在设备上显示警告.在安装期间使用SDK 23+(Android 6.0)的设备上,应用会使用以下方法检查权限:
I'm developing the MDM app for parents to control children's devices and it uses permission SYSTEM_ALERT_WINDOW
to display warnings on device if forbidden action has performed.On devices with SDK 23+ (Android 6.0) during installation the app checks the permission using this method:
Settings.canDrawOverlays(getApplicationContext())
,如果此方法返回false
,则应用会打开系统对话框,用户可以在其中授予权限:
and if this method returns false
the app opens system dialog where user can grant the permission:
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE);
但是在具有SDK 26(Android 8.0)的设备上,当用户成功授予权限并通过按后退按钮返回到应用程序时,方法canDrawOverlays()
仍会返回false
,直到用户没有关闭应用程序并启动再次选择它,或者只是在最近的应用程序对话框中选择它.我没有在Android Studio中使用 Android 8 在最新版本的虚拟设备上对其进行测试.
But on device with SDK 26 (Android 8.0), when user has successfully granted permission and returned to the app by pressing back button, method canDrawOverlays()
still returns false
, until user doesn't close the app and starts it again or just chooses it in the recent apps dialog. I tested it on latest version of virtual device with Android 8 in Android Studio because I didn't have real device.
我做了一些研究,并另外通过AppOpsManager检查权限:
I've done a little research and additionally check the permission with AppOpsManager:
AppOpsManager appOpsMgr = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
int mode = appOpsMgr.checkOpNoThrow("android:system_alert_window", android.os.Process.myUid(), getPackageName());
Log.d(TAG, "android:system_alert_window: mode=" + mode);
等等:
- 当应用程序没有此权限时,模式为"2"(MODE_ERRORED)(
canDrawOverlays()
返回false
)当用户 - 已授予许可并返回到应用程序,模式为"1"(MODE_IGNORED)(
canDrawOverlays()
返回false
) - 如果现在重新启动应用程序,则模式为"0"(MODE_ALLOWED)(
canDrawOverlays()
返回true
)
- when the application does not have this permission, the mode is "2"(MODE_ERRORED) (
canDrawOverlays()
returnsfalse
) when the user - granted permission and returned to the application, the mode is "1"(MODE_IGNORED) (
canDrawOverlays()
returnsfalse
) - and if you now restart the app, the mode is "0" (MODE_ALLOWED) (
canDrawOverlays()
returnstrue
)
请,有人可以向我解释这种行为吗?我可以依靠操作"android:system_alert_window"
的mode == 1
并假设用户已授予权限吗?
Please, can anyone explain this behavior to me? Can I rely on mode == 1
of operation "android:system_alert_window"
and assume that the user has granted permission?
推荐答案
我也发现了checkOp的问题.就我而言,我的流程仅允许在未设置权限的情况下重定向到设置.而且只有在重定向到设置时才设置AppOps.
I've found this problems with checkOp too. In my case I have the flow which allows to redirect to settings only when the permission is not set. And the AppOps is set only when redirecting to settings.
假定仅当更改某些内容并且只有一个开关可以更改时才调用AppOps回调.这意味着,如果调用了回调,则用户必须授予权限.
Assuming that AppOps callback is called only when something is changed and there is only one switch, which can be changed. That means, if callback is called, user has to grant the permission.
if (VERSION.SDK_INT >= VERSION_CODES.O &&
(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW.equals(op) &&
packageName.equals(mContext.getPackageName()))) {
// proceed to back to your app
}
还原应用程序后,开始对canDrawOverlays()
进行检查对我而言有效.当然,我会重新启动该应用程序,并检查是否通过标准方式授予了权限.
After the app is restored, checking with canDrawOverlays()
starts worked for me. For sure I restart the app and check if permission is granted via standard way.
这绝对不是一个完美的解决方案,但是它应该可以工作,直到我们从Google了解到更多信息为止.
It's definitely not a perfect solution, but it should work, till we know more about this from Google.
我问谷歌: https://issuetracker.google.com/issues/66072795
Google对此进行了修复.但似乎Android O版本仍会受到影响.
EDIT 2:Google fixes this. But it seem that the Android O version will be affected still.
这篇关于为什么在Android 8方法中Settings.canDrawOverlays()返回"false"?当用户授予绘制覆盖图的权限并返回到我的应用程序时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!