Android应用生死轮回的那些事儿(3) - 武器库(1)-权限管理相关API

简介: PackageManager中提供的武器,可以用“既多又杂,版本变化大”来形容。 不过,我们通过分类和排序的方法将它们组织起来,让开发者同学们可以学会使用这些强大的武器! 这一节我们将学习: * 如何查询系统中都有哪些权限组 * 每个权限组都有些什么权限 * 如何查询是否被授予某一权限

Android应用生死轮回的那些事儿(3) - 武器库(1)-权限管理相关API

PackageManager中提供的武器,可以用“既多又杂,版本变化大”来形容。
不过,我们通过分类和排序的方法将它们组织起来,让开发者同学们可以学会使用这些强大的武器!

这一节我们将学习:

  • 如何查询系统中都有哪些权限组
  • 每个权限组都有些什么权限
  • 如何查询是否被授予某一权限
  • 如何查询都有哪些应用申请了某一项权限

权限相关API及其发展史

我们先看第一个大族的API,Permission相关的API

pms_permission_gv

创始成员7个. Android 2.2版新增1个,Android 4.3新增1个,Android 6.0再增1个。共计10个。

权限相关API的创始成员

一共七个,基本上是权限的增,删,检查和查询4种操作。

  • addPermission:动态新增一个新权限
  • removePermission:删除一个权限
  • checkPermission:校验权限是否通过
  • getAllPermissionGroups:获取系统中所有的权限组
  • getPermissionGroupInfo:查询某个权限组的内容。系统中都有哪些权限组可通过getAllPermissionGroups来查询
  • queryPermissionsByGroup:查询一个权限组下面都有些什么权限
  • getPermissionInfo:根据权限名获取这个权限对象

getAllPermissionGroups

原型:

List<PermissionGroupInfo> getAllPermissionGroups (int flags);

参数:
真棒,只有一个选择:GET_META_DATA。

我们写一段例程看看效果:

   public void testGetAllPermissionGroups(){
        List<PermissionGroupInfo> list = mPm.getAllPermissionGroups(PackageManager.GET_META_DATA);
        if(list!=null){
            for(PermissionGroupInfo pgi: list){
                Log.d(TAG, "PermissionGroupInfo:" + pgi.toString());
            }
        }
    }

日志结果如下:

8-11 15:49:16.308 26087-26087/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{61443ad android.permission-group.CONTACTS flgs=0x0}
08-11 15:49:16.308 26087-26087/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{80db6e2 android.permission-group.PHONE flgs=0x0}
08-11 15:49:16.308 26087-26087/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{5bea73 android.permission-group.APPSTORE_CLOUD flgs=0x0}
08-11 15:49:16.308 26087-26087/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{840d30 android.permission-group.CALENDAR flgs=0x0}
08-11 15:49:16.308 26087-26087/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{75e6da9 android.permission-group.CAMERA flgs=0x0}
08-11 15:49:16.308 26087-26087/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{2545f2e android.permission-group.SENSORS flgs=0x0}
08-11 15:49:16.308 26087-26087/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{e80bacf android.permission-group.LOCATION flgs=0x0}
08-11 15:49:16.308 26087-26087/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{d4cc5c android.permission-group.STORAGE flgs=0x0}
08-11 15:49:16.308 26087-26087/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{c073b65 android.permission-group.MICROPHONE flgs=0x0}
08-11 15:49:16.308 26087-26087/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{84b403a android.permission-group.SMS flgs=0x0}

可见,我当前所用的Android M手机上,有下面这些PerssionGroup:

  • android.permission-group.CONTACTS:联系人相关权限组
  • android.permission-group.PHONE:电话相关权限组
  • android.permission-group.APPSTORE_CLOUD:应用商店云服务相关权限组
  • android.permission-group.CALENDAR:日历相关权限组
  • android.permission-group.CAMERA:相机相关权限组
  • android.permission-group.SENSORS:传感器相关权限组
  • android.permission-group.LOCATION:位置服务相关权限组
  • android.permission-group.STORAGE:存储相关权限组
  • android.permission-group.MICROPHONE:话筒相关权限组
  • android.permission-group.SMS:短消息相关权限组

这其中用到的PermissionGroupInfo类,用于来存储权限组的信息. 我们后面专门有相关数据结构类的详细说明。

getPermissionGroupInfo

根据字符串来查询特定的PerssionGroupInfo。

例程:

    public void testGetPermissionGroupInfo(){
        try {
            PermissionGroupInfo pgi = mPm.getPermissionGroupInfo("android.permission-group.CONTACTS", PackageManager.GET_META_DATA);
            if(pgi!=null){
                Log.d(TAG,"PermissionGroup description is:"+pgi.loadDescription(mPm));
            }
        }catch(PackageManager.NameNotFoundException e){
            Log.e(TAG,"");
        }
    }

queryPermissionsByGroup

通过上面两个方法的学习,我们已经可以获取PermissionGroup的信息了。那么,我们如何去知道一个权限组里都有哪些权限呢?
我们可以通过queryPermissionsByGroup方法来实现这个需求,请看例程:

    public void testQueryPermissionsByGroup(){
        try {
            List<PermissionInfo> list = mPm.queryPermissionsByGroup("android.permission-group.CONTACTS", PackageManager.GET_META_DATA);
            if(list!=null){
                for(PermissionInfo pi : list){
                    Log.d(TAG,"Permission info:"+pi);
                    Log.d(TAG,"Permission Description is:"+pi.loadDescription(mPm));
                }
            }
        }catch(PackageManager.NameNotFoundException e){
            Log.e(TAG,"testQueryPermissionsByGroup error",e);
        }
    }

输出的结果如下:

08-11 16:35:51.230 28164-28164/? D/TestPackageManager: Permission info:PermissionInfo{b8fe1ce android.permission.WRITE_CONTACTS}
08-11 16:35:51.231 28164-28164/? D/TestPackageManager: Permission Description is:允许该应用修改您手机上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定联系人通信的频率。此权限可让应用删除联系人数据。
08-11 16:35:51.231 28164-28164/? D/TestPackageManager: Permission info:PermissionInfo{66418ef android.permission.GET_ACCOUNTS}
08-11 16:35:51.232 28164-28164/? D/TestPackageManager: Permission Description is:允许该应用获取手机已知的帐户列表,其中可能包括由已安装的应用创建的所有帐户。
08-11 16:35:51.232 28164-28164/? D/TestPackageManager: Permission info:PermissionInfo{119ffc android.permission.READ_CONTACTS}
08-11 16:35:51.232 28164-28164/? D/TestPackageManager: Permission Description is:允许该应用读取您手机上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定个人通信的频率。此权限可让应用保存您的联系人数据,而恶意应用可能会在您不知情的情况下分享联系人数据。

从上面的Log上我们可以看到,android.permission-group.CONTACTS组里有3个成员:

  • android.permission.WRITE_CONTACTS:允许该应用修改您手机上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定联系人通信的频率。此权限可让应用删除联系人数据。
  • android.permission.GET_ACCOUNTS:允许该应用获取手机已知的帐户列表,其中可能包括由已安装的应用创建的所有帐户。
  • android.permission.READ_CONTACTS:允许该应用读取您手机上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定个人通信的频率。此权限可让应用保存您的联系人数据,而恶意应用可能会在您不知情的情况下分享联系人数据。

getPermissionInfo

根据名字查找对应的权限对象,不多说了,上例程:

    public void testGetPermissionInfo() {
        try {
            PermissionInfo pi = mPm.getPermissionInfo("android.permission.WRITE_CONTACTS", PackageManager.GET_META_DATA);
            Log.d(TAG,"Permission Description is:"+pi.loadDescription(mPm));
        } catch (PackageManager.NameNotFoundException e) {
            Log.d(TAG,"testGetPermissionInfo error",e);
        }
    }

输出如下:

08-11 16:53:58.548 28325-28325/? D/TestPackageManager: Permission Description is:允许该应用读取您手机上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定个人通信的频率。此权限可让应用保存您的联系人数据,而恶意应用可能会在您不知情的情况下分享联系人数据。
0

checkPermission

检查是否一个包是否被允许某个权限。看例程:

    public void testCheckPermission(){
        final int i = mPm.checkPermission("android.permission.WRITE_CONTACTS", "com.yunos.xulun.testcppjni2");
        if(i== PackageManager.PERMISSION_GRANTED){
            Log.d(TAG,"Permission Granted!");
        }else{
            Log.d(TAG,"Permission Denied!");
        }
    }

addPermission和removePermission两个方法暂时没见到有人用到,先略过不讲了。

API 8(Android 2.2,Froyo)新增的API

  • addPermissionAsync:异步添加新权限,可以快速返回。可以用于批量添加权限。
    这个API也没见有人用过,就不讲了。

API 18 (Android 4.3, Jelly Bean MR2)新增的API

  • getPackagesHoldingPermissions:查看当前系统里安装的应用中,哪些使用了这个权限。这个API很好玩啊,能查到哪些应用用到了危险的权限。

例程:

    public void testGetPackagesHoldingPermissions(){
        List<PackageInfo> list = mPm.getPackagesHoldingPermissions(new String[]{"android.permission.WRITE_CONTACTS"},PackageManager.GET_META_DATA | PackageManager.GET_PROVIDERS);
        if(list!=null){
            for(PackageInfo pi : list){
                Log.d(TAG,"Package that use WRITE_CONTACTS:"+pi.packageName);
            }
        }
    }

输出吓一跳,怎么这么多应用要改联系人!

08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.gba
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.ims
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.ppl
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.providers.telephony
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.schpwronoff
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.ygps
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.mms.service
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.engineermode
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.wfo.impl
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.tencent.mm
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:android
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.connectivity
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.ftprecheck
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.mms
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.stk
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.providers.settings
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.batterywarning
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.incallui
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.inputdevices
08-11 17:22:49.773 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.nlpservice
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.server.telecom
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.keychain
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.atci.service
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mediatek.thermalmanager
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.mtk.telephony
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.settings
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.vpndialogs
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.phone
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.shell
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.location.fused
08-11 17:22:49.774 28747-28747/? D/TestPackageManager: Package that use WRITE_CONTACTS:com.android.bluetooth

API 23 (Android M,6.0)新增的API

  • isPermissionRevokedByPolicy:查看权限是否符合policy的规定。如果policy不允许,就只能换policy,否则无法通过。

权限相关的数据结构类

PermissionGroupInfo

公开域:

  • public CharSequence nonLocalizedDescription:如果这个权限组的名字字符串直接定义在AndroidManifest.xml中,那么通过这个域就可以得到它的字符串名字。如果是空,那么说明是调用的字符串资源,要去查另一个属性descriptionRes。
  • public int descriptionRes:如果上面的nonLocalizedDescription是空,那么这个肯定不空。可以调用loadDescription(pm)方法获取。

其实loadDescription中早已经考虑到上面所讲的两种情况了,调用loadDescription一定能得到描述的字符串:

     public CharSequence loadDescription(PackageManager pm) {
         if (nonLocalizedDescription != null) {
             return nonLocalizedDescription;
         }
         if (descriptionRes != 0) {
             CharSequence label = pm.getText(packageName, descriptionRes, null);
             if (label != null) {
                 return label;
             }
         }
         return null;
     }

我们还是通过一个例程来学习下,可以读取到权限的本地语言,如中文的描述,还是挺好玩的哈:

    public void testGetAllPermissionGroups(){
        List<PermissionGroupInfo> list = mPm.getAllPermissionGroups(PackageManager.GET_META_DATA);
        if(list!=null){
            for(PermissionGroupInfo pgi: list){
                Log.d(TAG, "PermissionGroupInfo:" + pgi.toString());
                if(TextUtils.isEmpty(pgi.nonLocalizedDescription)){
                    Log.d(TAG,"PermissionGroup description is:"+pgi.loadDescription(mPm));
                }else{
                    Log.d(TAG,"PermissionGroup description is:"+pgi.nonLocalizedDescription);
                }
            }
        }
    }

输出的结果如下:

08-11 16:13:05.089 26875-26875/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{61443ad android.permission-group.CONTACTS flgs=0x0}
08-11 16:13:05.091 26875-26875/? D/TestPackageManager: PermissionGroup description is:使用您的通讯录
08-11 16:13:05.092 26875-26875/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{80db6e2 android.permission-group.PHONE flgs=0x0}
08-11 16:13:05.092 26875-26875/? D/TestPackageManager: PermissionGroup description is:拨打电话和管理通话
08-11 16:13:05.092 26875-26875/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{5bea73 android.permission-group.APPSTORE_CLOUD flgs=0x0}
08-11 16:13:05.092 26875-26875/? D/TestPackageManager: PermissionGroup description is:null
08-11 16:13:05.092 26875-26875/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{840d30 android.permission-group.CALENDAR flgs=0x0}
08-11 16:13:05.093 26875-26875/? D/TestPackageManager: PermissionGroup description is:访问您的日历
08-11 16:13:05.093 26875-26875/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{75e6da9 android.permission-group.CAMERA flgs=0x0}
08-11 16:13:05.094 26875-26875/? D/TestPackageManager: PermissionGroup description is:拍摄照片和录制视频
08-11 16:13:05.094 26875-26875/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{2545f2e android.permission-group.SENSORS flgs=0x0}
08-11 16:13:05.095 26875-26875/? D/TestPackageManager: PermissionGroup description is:访问与您的生命体征相关的传感器数据
08-11 16:13:05.095 26875-26875/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{e80bacf android.permission-group.LOCATION flgs=0x0}
08-11 16:13:05.096 26875-26875/? D/TestPackageManager: PermissionGroup description is:使用此设备的位置信息
08-11 16:13:05.096 26875-26875/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{d4cc5c android.permission-group.STORAGE flgs=0x0}
08-11 16:13:05.097 26875-26875/? D/TestPackageManager: PermissionGroup description is:访问您设备上的照片、媒体内容和文件
08-11 16:13:05.097 26875-26875/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{c073b65 android.permission-group.MICROPHONE flgs=0x0}
08-11 16:13:05.097 26875-26875/? D/TestPackageManager: PermissionGroup description is:录制音频
08-11 16:13:05.097 26875-26875/? D/TestPackageManager: PermissionGroupInfo:PermissionGroupInfo{84b403a android.permission-group.SMS flgs=0x0}
08-11 16:13:05.098 26875-26875/? D/TestPackageManager: PermissionGroup description is:发送和查看短信
目录
相关文章
|
18天前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
82 4
|
1天前
|
Kubernetes 安全 Devops
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
18 10
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
|
2天前
|
数据可视化 搜索推荐 API
速卖通获得aliexpress商品详情API接口的开发、应用与收益。
速卖通(AliExpress)作为阿里巴巴旗下的跨境电商平台,为全球消费者提供丰富商品。其开放平台提供的API接口支持开发者获取商品详情等信息,本文探讨了速卖通商品详情API的开发流程、应用场景及潜在收益,包括提高运营效率、降低成本、增加收入和提升竞争力等方面。
13 1
|
7天前
|
机器学习/深度学习 搜索推荐 API
淘宝/天猫按图搜索(拍立淘)API的深度解析与应用实践
在数字化时代,电商行业迅速发展,个性化、便捷性和高效性成为消费者新需求。淘宝/天猫推出的拍立淘API,利用图像识别技术,提供精准的购物搜索体验。本文深入探讨其原理、优势、应用场景及实现方法,助力电商技术和用户体验提升。
|
10天前
|
搜索推荐 算法 数据挖掘
淘口令真实URL API接口的应用与收益
淘口令作为电商推广利器,通过简短文本引导用户直达商品页,提升购物体验与销售效率。本文探讨淘口令真实URL API接口的应用,包括商品推广、数据分析、跨境电商及社交媒体营销等方面,揭示其在电商领域的巨大潜力与收益。
20 1
|
14天前
|
JSON 搜索推荐 API
LAZADA关键词搜索API接口的获取与应用
Lazada作为东南亚领先的电商平台,为满足开发者和商户需求,开放了关键词搜索API接口。本文详细介绍该接口的获取与应用,助力提升电商业务效率。接口支持关键词搜索、指定搜索范围和排序方式,提供精准、灵活且全面的数据支持,促进电商应用和服务的优化与创新。
21 3
|
13天前
|
监控 API 数据安全/隐私保护
小红书详情API接口的获取与应用
在互联网信息爆炸的时代,小红书凭借丰富的用户生成内容(UGC)和精准的推荐系统迅速崛起,成为重要的社区电商平台。为了帮助开发者高效利用平台数据,小红书开放平台提供了多种API接口,涵盖商品详情和笔记详情等。本文详细介绍了如何注册、申请权限、构建请求、处理响应及应用这些API接口,旨在为开发者提供全面的指南,助力数据驱动的决策与创新。
70 1
|
13天前
|
供应链 数据挖掘 API
获取亚马逊畅销榜API接口的获取与应用
本文详细介绍了如何获取亚马逊畅销榜API接口及其应用方法。首先,需注册并获取API凭证,了解常用API接口如Product Advertising API、Sponsored Products API等。接着,选择合适的API端点,发送请求并解析响应。最后,探讨了API在商品查询、数据分析、跨境电商及商业工具开发等方面的应用,强调了遵守服务条款的重要性。
29 0
|
14天前
|
缓存 API 持续交付
阿里巴巴热卖商品推荐API接口的获取与应用
阿里巴巴推出热卖商品推荐API接口,基于AI算法,根据用户行为推荐商品,涵盖名称、价格、描述等信息。本文介绍其获取与应用方法,帮助商家和开发者提高推荐精准度和用户满意度,优化库存管理和营销策略,提升整体销售效果。
21 0
|
17天前
|
JavaScript 前端开发 API
Vue.js 3:深入探索组合式API的实践与应用
Vue.js 3:深入探索组合式API的实践与应用