1.基本常识
原来权限模型,在版本之前,权限都是一条龙服务的,只要用户安装完,AndroidManifest清单上申请的权限都会被系统默认授权,并且授权后也撤销不了。
采用新的权限模型,只有在需要权限的时候,才告知用户是否授权,是在runtime时候授权,而不是在原来安装的时候 ,同时默认情况下每次在运行时打开页面时候,需要先检查是否有所需要的权限申请。
我们可以看到整个权限里,可以分为系统权限和特殊权限授权。系统权限中,又分为normal和dangerous类型。
normal:这个权限类型并不直接威胁到用户的隐私,可以直接在manifest清单里注册,系统会帮我们默认授权的。
dangerous:这个可以直接给app访问用户一些敏感的数据,不仅需要在manifest清单里注册,同时在使用的时候,需要向系统请求授权。
需要特殊处理,后期再说:SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS,也属于dangerous权限类型;
2.基本逻辑
2.1检查并申请权限
我们需要在用到权限的地方,每次都检查是否APP已经拥有权限,
比如我们有一个下载功能,需要写SD卡的权限,
我们在写入之前检查是否有WRITE_EXTERNAL_STORAGE权限,没有则申请权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
//申请WRITE_EXTERNAL_STORAGE权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
WRITE_EXTERNAL_STORAGE_REQUEST_CODE);
}
2.2用户选择
允许或需要后,会回调onRequestPermissionsResult方法, 该方法类似于onActivityResult
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
doNext(requestCode,grantResults);
}
2.3授权结果
我们接着需要根据requestCode和grantResults(授权结果)做相应的后续处理
private void doNext(int requestCode, int[] grantResults) {
if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission Granted
} else {
// Permission Denied
}
}
}
Fragment中运行时权限的特殊处理
在Fragment中申请权限,不要使用ActivityCompat.requestPermissions, 直接使用Fragment的requestPermissions方法,否则会回调到Activity的 onRequestPermissionsResult
如果在Fragment中嵌套Fragment,在子Fragment中使用requestPermissions方 法,onRequestPermissionsResult不会回调回来,建议使用 getParentFragment().requestPermissions方法,
这个方法会回调到父Fragment中的onRequestPermissionsResult,加入以下代码可以把回调透传到子Fragment
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode,permissions,grantResults);
}
}
}
}
3.框架
鸿神,把developer.Android给翻译和封装了,根据某个框架,自己又写了一个,但是我不愿意,用鸿神的框架,自己还是引入源代码吧
鸿神博客
鸿神github框架
推荐谷歌的案例
最喜欢这个代码
/**
* Utility class that wraps access to the runtime permissions API in M and provides basic helper
* methods.
*/
public abstract class PermissionUtil {
/**
* Check that all given permissions have been granted by verifying that each entry in the
* given array is of the value {@link PackageManager#PERMISSION_GRANTED}.
*
* @see Activity#onRequestPermissionsResult(int, String[], int[])
*/
public static boolean verifyPermissions(int[] grantResults) {
// At least one result must be checked.
if(grantResults.length < 1){
return false;
}
// Verify that each required permission has been granted, otherwise return false.
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
}