需求

现在android版本出现到了7.0,今后高版本的android肯定会占据市场的主流,所以在我们的应用中进行运行时处理,也是势在必行的了。


引用郭霖对android运行时权限的总结,一共9组24个权限,只有在android6.0 及以上的android机上使用到这些权限的时候,才需要进行运行时权限处理.

Android 6.0及运行时权限处理_第1张图片

使用场景

前提:应用运行到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

下面我将郭霖公开课的代码截屏如下:

原生方式实现

基本用法,申请单个权限

Android 6.0及运行时权限处理_第2张图片
Android 6.0及运行时权限处理_第3张图片

  • 高级用法,申请一组权限

Android 6.0及运行时权限处理_第4张图片
Android 6.0及运行时权限处理_第5张图片

封装框架

郭神提供了三种实现思路

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();

更多相关文章

  1. Android O 版本(Android 8.0) 存储空间不足时提醒
  2. Camera Flash的获得权限
  3. android中使用afinal一行代码显示网络图片
  4. 笔记 android 代码中设置Android:layout_gravity
  5. 代码中设置drawableright
  6. 最新android版本对应的API等级
  7. ANDROID常用权限记录
  8. 多点触控测试代码 PointerLocation
  9. Android NDK各版本下载

随机推荐

  1. Android入门教程(二十八)------之Service
  2. Android(安卓)UI开发第二十七篇——实现
  3. Android开发中的五大布局
  4. android studio导入第三方工具
  5. LeakCanary-帮助你检测Android所有的内存
  6. Android(安卓)使用 Material icons
  7. android 中关于SimpleAdapter构造参数的
  8. Nexus 5 Android(安卓)6.0.1刷机、Root
  9. tcping测试服务器TCP端口
  10. Android(安卓)Rxjava和retrofit