Android 6.0及运行时权限处理
需求
现在android版本出现到了7.0,今后高版本的android肯定会占据市场的主流,所以在我们的应用中进行运行时处理,也是势在必行的了。
引用郭霖对android运行时权限的总结,一共9组24个权限,只有在android6.0 及以上的android机上使用到这些权限的时候,才需要进行运行时权限处理.
使用场景
前提:应用运行到android 6.0 及以上的android机上(低版本的android机不用进行运行时权限处理);
1.项目的targetSdkVersion < 23 , 即应用没有兼容android6.0及以上
此时应用运行到android6.0 及以上的android机上是不需要进行运行时权限处理的。系统会按照默认的权限加载方式加载。
2.targetSdkVersion >=23,但是是从小于23的版本升级上来的
及应用以前不兼容android6.0及以上版本,但是现在升级后兼容了android6.0及以上版本。
实际场景:手机之前安装了低版本(不兼容android6.0)的应用,不卸载直接升级新版本(兼容了android6.0)的。这种情况
android会默认将应用申请的权限全部授权
但是,如果你是先卸载之前低版本的应用,再安装高版本的应用,那就需要进行运行时权限处理了。
3.targetSdkVersion >=23,应用兼容android6.0及以上
此时就需要进行运行时权限处理了,需要提一下,即使是在代码中处理的运行时权限,也是需要在manifest中注册的
郭霖CSDN运行时权限公开课地址:http://edu.csdn.net/course/detail/3539
郭霖运行时权限微信推荐文章:http://chuansong.me/n/1017834351332
下面我将郭霖公开课的代码截屏如下:
原生方式实现
基本用法,申请单个权限
- 高级用法,申请一组权限
封装框架
郭神提供了三种实现思路
1.新建一个PermissionActivity,设置成透明的,所有的权限操作都在这个activity中进行,授权后在finish掉,回到原来的activity。
2.参考第三方开源运行时权限处理框架RxPermission
github地址:注意它是要结合RxJava一起使用的,但是RxJava有RxJava1和RxJava2两个库
所以RxPermission也有对应的两个库
RxPermission1:https://github.com/tbruyelle/RxPermissions
RxPermission2https://github.com/sirencode/RxPermissions2
这种的处理方法是,新建一个RxPermissionFragment 去集成 Fragment,因为Fragment里面也有运行时权限处理的方法,就是上面讲到的原生实现中涉及到的方法,并且这个RxPermissionFragment 利用了Fragment的特性,它是没有界面没有大小的,只用来处理运行时权限。
3.利用BaseActivity自己封装运行时权限
android源码中用0和-1来表示授权是否成功,0表示获取授权成功,-1表示获取授权失败。
PackageManager.PERMISSION_GRANTED = 0 ;
PackageManager.PERMISSION_DENIED= -1 ;
封装实战
实现思路
代码很简单,重点是学习这种封装的思路
1.项目中所有的Activity都继承BaseActivity
为了项目的可扩展性,一般的项目都是这样的。如果你的项目不是这样写的,自己赶紧改过来吧。2.将运行时权限检测写到BaseActivity中
3.提供授权成功和授权失败的回调接口
4.为了能够在非Activity中使用,使用Activity管理器提供栈顶Activity
实现代码
说一句,郭神在视频中说,不提供源码,是因为编程是个需要动手的过程,只看和复制别人的代码是很难提高的
- 1.BaseActivity,运行时权限处理
public class BaseActivity extends AppCompatActivity { private static final String TAG = "BaseActivity"; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityCollector.addActivity(this); } @Override protected void onDestroy() { super.onDestroy(); ActivityCollector.removeActivity(this); } private static PermissionListener mListener; /** * 请求运行时权限 * * @param permissions * @param listener */ public static void requestRuntimePermission(String[] permissions, PermissionListener listener) { try { Activity topActivity = ActivityCollector.getTopActivity(); if (topActivity == null) { return; } mListener = listener; List permissionList = new ArrayList<>(); for (String permission : permissions) { if (ContextCompat.checkSelfPermission(topActivity, permission) != PackageManager.PERMISSION_GRANTED) { permissionList.add(permission); } } if (!permissionList.isEmpty()) { ActivityCompat.requestPermissions(topActivity, permissionList.toArray(new String[permissionList.size()]), 1); } else { //授权成功 mListener.onGranted(); } } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "requestRuntimePermission: "+e.getMessage()); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case 1: //有权限被拒绝 if (grantResults.length > 0) { List deniedPermissions = new ArrayList<>(); for (int i = 0; i < grantResults.length; i++) { int grantResult = grantResults[i]; String permission = permissions[i]; if (grantResult != PackageManager.PERMISSION_GRANTED) { deniedPermissions.add(permission); } } //全部授权成功 if (deniedPermissions.isEmpty()) { mListener.onGranted(); } else { mListener.onDenied(deniedPermissions); } } break; default: break; } }}
- 2.授权回调接口
public interface PermissionListener { //授权,同意 void onGranted(); //拒绝 void onDenied(List deniedPermission);}
- 3.Activity控制器
public class ActivityCollector { private static List activityList = new ArrayList<>(); public static void addActivity(Activity activity){ activityList.add(activity); } public static void removeActivity(Activity activity){ activityList.remove(activity); } //获取当前栈顶activity public static Activity getTopActivity(){ if (activityList.isEmpty()){ return null; }else { return activityList.get(activityList.size()-1); } } public static void finishAll(){ for (Activity activity : activityList) { if (!activity.isFinishing()){ activity.finish(); } } }}
- 注意
在非Activity中使用requestRuntimePermission()方法时需要在前面加上类名,如下:
BaseActivity.requestRuntimePermission(...);
requestRuntimePermission()方法里面的try–catch,加不加都可以。
课程中提到的一些小知识点
1.访问应用包名下的目录,可以不用申请权限
/data/data/包名
2.访问应用的缓存目录,getExternalCacheDir();
3.访问应用的重要文件存储目录,getExternalFilesDir(str);
str=”“,表files的根目录;
str=”adc”,表示files下的abc目录,没有就创建。
4.访问应用的包名目录,getDataDirectory();
更多相关文章
- Android O 版本(Android 8.0) 存储空间不足时提醒
- Camera Flash的获得权限
- android中使用afinal一行代码显示网络图片
- 笔记 android 代码中设置Android:layout_gravity
- 代码中设置drawableright
- 最新android版本对应的API等级
- ANDROID常用权限记录
- 多点触控测试代码 PointerLocation
- Android NDK各版本下载