IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> [Android]从canDrawOverlays权限获取错误说起 -> 正文阅读

[移动开发][Android]从canDrawOverlays权限获取错误说起

从Settings.canDrawOverlays到Binder.getCallingPid

在调试程序的时候,发现一个奇怪的问题,在主线程调用Settings.canDrawOverlays判断是否有悬浮权限的结果和在另外一个service线程中调用Settings.canDrawOverlays的结果不一样,奇怪。

事出反常必有妖,我们去看看谁在作怪。

查看其定义

frameworks/base/core/java/android/provider/Settings.java

2225??? public static boolean canDrawOverlays(Context context) {

2226??????? return Settings.isCallingPackageAllowedToDrawOverlays(context, Process.myUid(),

2227??????????????? context.getOpPackageName(), false);

2228??? }

再调用

13247??? public static boolean isCallingPackageAllowedToDrawOverlays(Context context, int uid,
13248??????????? String callingPackage, boolean throwException) {
13249??????? return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid,
13250??????????????? callingPackage, throwException, AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
13251??????????????? PM_SYSTEM_ALERT_WINDOW, false);
13252??? }

13277??? public static boolean isCallingPackageAllowedToPerformAppOpsProtectedOperation(Context context,
13278??????????? int uid, String callingPackage, boolean throwException, int appOpsOpCode, String[]
13279??????????? permissions, boolean makeNote) {
13280??????? if (callingPackage == null) {
13281??????????? return false;
13282??????? }
13283
13284??????? AppOpsManager appOpsMgr = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
13285??????? int mode = AppOpsManager.MODE_DEFAULT;
13286??????? if (makeNote) {
13287??????????? mode = appOpsMgr.noteOpNoThrow(appOpsOpCode, uid, callingPackage);
13288??????? } else {
13289??????????? mode = appOpsMgr.checkOpNoThrow(appOpsOpCode, uid, callingPackage);
13290??????? }
13291
13292??????? switch (mode) {
13293??????????? case AppOpsManager.MODE_ALLOWED:
13294??????????????? return true;
13295
13296??????????? case AppOpsManager.MODE_DEFAULT:
13297??????????????? // this is the default operating mode after an app's installation
13298??????????????? // In this case we will check all associated static permission to see
13299??????????????? // if it is granted during install time.
13300??????????????? for (String permission : permissions) {
13301??????????????????? if (context.checkCallingOrSelfPermission(permission) == PackageManager
13302??????????????????????????? .PERMISSION_GRANTED) {
13303??????????????????????? // if either of the permissions are granted, we will allow it
13304??????????????????????? return true;
13305??????????????????? }
13306??????????????? }
13307
13308??????????? default:
13309??????????????? // this is for all other cases trickled down here...
13310???? ???????????if (!throwException) {
13311?????? ?????????????return false;
13312??????????????? }
13313??????? }

添加log,发现是context.checkCallingOrSelfPermission(permission)

的结果在不同线程里不一样,

753??? public int checkCallingOrSelfPermission(String permission) {
754??????? return mBase.checkCallingOrSelfPermission(permission);
755??? }

1786??? public int checkCallingOrSelfPermission(String permission) {
1787??????? if (permission == null) {
1788??????????? throw new IllegalArgumentException("permission is null");
1789??????? }
1790
1791??????? return checkPermission(permission, Binder.getCallingPid(),
1792??????????????? Binder.getCallingUid());
1793??? }

这里可以看到,使用了Binder.getCallingPid()Binder.getCallingUid()作为参数,在碰到的问题中,次线程是通过Binder调起的服务,所以其Binder.getCallingPid()和主线程不一样,是调用者进程的PID,就是这里的差异,导致了在同一个进程中,不同线程的调用结果不一样,

我们可以使用checkSelfPermission(“android.permission.SYSTEM_ALERT_WINDOW”)去判断权限,

或者使用Binder. clearCallingIdentity(); 把调用信息设置为当前进程后再调用Settings.canDrawOverlays方法。

回过头来看,不同线程的执行结果不一样,肯定是有线程差异在影响,我们应当对Binder的线程情况及Binder.getCallingPid有意识。对于Binder线程中权限的获取,我们都应当格外注意。

Settings.canDrawOverlays(context) 方法可以说是埋了个坑,一般不会有这个问题,如果有问题,就用上面的方法去处理。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-15 15:43:16  更:2021-08-15 15:43:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:34:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码