Framework基础:系统源码理解6.0的运行时权限
2018-02-08 00:00
375 查看
Android 6.0 引入了运行时权限。就是权限是在程序运行的时候赋予的,而不是安装的时候赋予的。6.0之前权限的赋予都是在安装的时候列出一堆权限,然后用户点击确定后赋予的。下面对比图,有种你敢看。
Android L.png
Android M.png
1.并不是所有权限都要运行时才申请的。有些是安装的时候自然就给你的,安装时候自动给你的都是一些小权限啦,没啥危险的。执行 adb shell pm dump com.example.rubbishdemo |find "permission" 可以看到有哪些权限是这个com.example.rubbishdemo安装的时候就被赋予的。这个可以叫做“安装时权限”,哈哈,名字是我乱起的。
Paste_Image.png
2.运行时权限的赋予是给整个权限组赋予权限,啥意思啊,是这样的,Android里面的权限都是分组的,便于管理,例如写sd卡,和读sd卡就是同一个权限组android.permission-group.STORAGE的。这些在frameworks/base/core/res/AndroidManifest.xml中定义
权限组定义.png
权限组下的两个权限.png
3.权限赋予后,会记录到设置数据库中。因而重启也不会失效。
首先是应用部分,在onCreate里面申请发送信息的权限SEND_SMS。
AndroidManifest定义要获取的权限
上节我们说到运行时权限那个弹框是有应用安装器弹出的,所在的Activity是GrantPermissionsActivity。所以,过一下这个Activity的代码。
先看一下上面的注释,大概步骤是
1.获取APK AndroidManifest中定义的所有权限,并保存在结构AppPermissions。
本例子只定义了一个权限android.permission.SEND_SMS,所以AppPermissions结构中只包含一个Permission,如果定义了多个Permission,则AppPermissions结构中包含多个Permission。
2.获取APK的权限组AppPermissionGroup ,本例子只定义了一个权限,所以权限组也只有一个。android.permission.SEND_SMS所在的权限组是android.permission-group.SMS。
3.查看要获取的权限所在的权限组是否之前已经获取到权限,如果已经获取到,不再获取。直接结束,否则会弹个框,吓吓你。
4.弹框通过GrantPermissionsDefaultViewHandler创建。
弹框吓吓你.png
下面进入GrantPermissionsDefaultViewHandler看看
可以看到,步骤也很简单
1.弹框创建了允许与拒绝的按钮,给按钮设置监听。
2.按下允许按键后,会给权限组赋予权限,最后调用PackageManagerService系统服务将结果写入设置数据库。groupState.mGroup就是权限组。
2.权限赋予的入口是应用安装器。
3.有些权限是安装时赋予的,是没啥危险的权限。危险的权限通过运行时赋予。至于危险的定义也在frameworks/base/core/res/AndroidManifest.xml中,截个图你看
危险.png
不危险.png
作者:九九叔
链接:https://www.jianshu.com/p/d31ea81f75a3
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Android L.png
Android M.png
大体说一下##
今天来说下6.0权限赋予的一个过程吧,先不上代码,先用自然语言说一下。1.并不是所有权限都要运行时才申请的。有些是安装的时候自然就给你的,安装时候自动给你的都是一些小权限啦,没啥危险的。执行 adb shell pm dump com.example.rubbishdemo |find "permission" 可以看到有哪些权限是这个com.example.rubbishdemo安装的时候就被赋予的。这个可以叫做“安装时权限”,哈哈,名字是我乱起的。
Paste_Image.png
2.运行时权限的赋予是给整个权限组赋予权限,啥意思啊,是这样的,Android里面的权限都是分组的,便于管理,例如写sd卡,和读sd卡就是同一个权限组android.permission-group.STORAGE的。这些在frameworks/base/core/res/AndroidManifest.xml中定义
权限组定义.png
权限组下的两个权限.png
3.权限赋予后,会记录到设置数据库中。因而重启也不会失效。
代码走一下##
下面就进入代码时间首先是应用部分,在onCreate里面申请发送信息的权限SEND_SMS。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.requestPermissions( new String[]{Manifest.permission.SEND_SMS}, 2); }
AndroidManifest定义要获取的权限
<uses-permission android:name="android.permission.SEND_SMS" />
上节我们说到运行时权限那个弹框是有应用安装器弹出的,所在的Activity是GrantPermissionsActivity。所以,过一下这个Activity的代码。
public void onCreate(Bundle icicle) { super.onCreate(icicle); //mRequestedPermissions是要获取的权限,这里要获取的是android.permission.SEND_SMS mRequestedPermissions = getIntent().getStringArrayExtra( PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES); if (mRequestedPermissions == null) { mRequestedPermissions = new String[0]; } final int requestedPermCount = mRequestedPermissions.length; mGrantResults = new int[requestedPermCount]; //用来保存权限获取结果 //要获取权限的应用的包名 PackageInfo callingPackageInfo = getCallingPackageInfo(); //设备管理器 DevicePolicyManager devicePolicyManager = getSystemService(DevicePolicyManager.class); //权限策略 final int permissionPolicy = devicePolicyManager.getPermissionPolicy(null); //获取应用中所有的权限,这个返回值是AndroidManifest里面定义的所有权限,本例子就是下面一个,only one /* <uses-permission android:name="android.permission.SEND_SMS" /> */ //把这些权限保存到一个数据结构AppPermissions中去 mAppPermissions = new AppPermissions(this, callingPackageInfo, null, false, new Runnable() { @Override public void run() { setResultAndFinish(); } }); for (AppPermissionGroup group : mAppPermissions.getPermissionGroups()) { //遍历应用的权限组groud boolean groupHasRequestedPermission = false; for (String requestedPermission : mRequestedPermissions) { if (group.hasPermission(requestedPermission)) { //权限组已经有权限了,就不用再次赋予权限了 groupHasRequestedPermission = true; break; } } if (!groupHasRequestedPermission) { continue; } // We allow the user to choose only non-fixed permissions. A permission // is fixed either by device policy or the user denying with prejudice. //根据权限策略赋予权限,正常这两个策略不满足 if (!group.isUserFixed() && !group.isPolicyFixed()) { switch (permissionPolicy) { case DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT: { if (!group.areRuntimePermissionsGranted()) { group.grantRuntimePermissions(false); } group.setPolicyFixed(); } break; case DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY: { if (group.areRuntimePermissionsGranted()) { group.revokeRuntimePermissions(false); } group.setPolicyFixed(); } break; default: { if (!group.areRuntimePermissionsGranted()) { //把要申请权限的权限组groud放在数据结构mRequestGrantPermissionGroups mRequestGrantPermissionGroups.put(group.getName(), new GroupState(group)); } else { group.grantRuntimePermissions(false); updateGrantResults(group); } } break; } } else { // if the permission is fixed, ensure that we return the right request result updateGrantResults(group); } } //弹出弹框 mViewHandler = new GrantPermissionsDefaultViewHandler(this).setResultListener(this); setContentView(mViewHandler.createView()); }
先看一下上面的注释,大概步骤是
1.获取APK AndroidManifest中定义的所有权限,并保存在结构AppPermissions。
本例子只定义了一个权限android.permission.SEND_SMS,所以AppPermissions结构中只包含一个Permission,如果定义了多个Permission,则AppPermissions结构中包含多个Permission。
2.获取APK的权限组AppPermissionGroup ,本例子只定义了一个权限,所以权限组也只有一个。android.permission.SEND_SMS所在的权限组是android.permission-group.SMS。
3.查看要获取的权限所在的权限组是否之前已经获取到权限,如果已经获取到,不再获取。直接结束,否则会弹个框,吓吓你。
4.弹框通过GrantPermissionsDefaultViewHandler创建。
弹框吓吓你.png
下面进入GrantPermissionsDefaultViewHandler看看
//创建了弹框,只关注同意按钮 public View createView() { mAllowButton = (Button) mRootView.findViewById(R.id.permission_allow_button); mDenyButton = (Button) mRootView.findViewById(R.id.permission_deny_button); return mRootView; } //看点击允许是怎么处理 public void onClick(View view) { switch (view.getId()) { case R.id.permission_allow_button: if (mResultListener != null) { view.clearAccessibilityFocus(); mResultListener.onPermissionGrantResult(mGroupName, true, false); //这里的mResultListener就是GrantPermissionsActivity } break; } } //GrantPermissionsActivity中 public void onPermissionGrantResult(String name, boolean granted, boolean doNotAskAgain) { GroupState groupState = mRequestGrantPermissionGroups.get(name); if (groupState.mGroup != null) { if (granted) { groupState.mGroup.grantRuntimePermissions(doNotAskAgain); //这里会往设置数据库写一个值,完成权限赋予 groupState.mState = GroupState.STATE_ALLOWED; } }
可以看到,步骤也很简单
1.弹框创建了允许与拒绝的按钮,给按钮设置监听。
2.按下允许按键后,会给权限组赋予权限,最后调用PackageManagerService系统服务将结果写入设置数据库。groupState.mGroup就是权限组。
总结##
1.6.0的权限赋予是给整个权限组赋予权限。2.权限赋予的入口是应用安装器。
3.有些权限是安装时赋予的,是没啥危险的权限。危险的权限通过运行时赋予。至于危险的定义也在frameworks/base/core/res/AndroidManifest.xml中,截个图你看
危险.png
不危险.png
作者:九九叔
链接:https://www.jianshu.com/p/d31ea81f75a3
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关文章推荐
- 谈谈Android 6.0运行时权限理解
- 终于理解你的软件 搞那么多年了 (通用权限管理系统组件源码完善了7-8年)
- 谈谈Android 6.0运行时权限理解
- 谈谈Android 6.0运行时权限理解
- 谈谈Android 6.0运行时权限理解
- 谈谈Android 6.0运行时权限理解
- 谈谈Android 6.0运行时权限理解
- 流星ASP.NET权限基础管理系统源码发布
- Android开发之深入理解Android 6.0、7.0系统权限
- 终于理解你的软件 搞那么多年了 (通用权限管理系统组件源码完善了7-8年)
- RxPermissions源码分析:使用RxJava处理Android 6.0运行时动态权限获取
- 流星ASP.NET权限基础管理系统源码发布
- 关于Android 6.0运行时权限的一些理解和权限处理的三方库的应用
- 以调用系统相机拍照为例了解Android 6.0运行时权限
- 谈谈Android 6.0运行时权限理解
- PermissionsDispatcher库的使用(简单处理Android 6.0系统中的运行时权限的开源库)
- 谈谈Android 6.0运行时权限理解
- Android学习之6.0系统运行时权限设置
- 终于理解你的软件 搞那么多年了 (通用权限管理系统组件源码完善了7-8年)
- RxPermissions源码分析:使用RxJava处理Android 6.0运行时动态权限获取