动态权限那点事儿

记录自己在开发中遇到的问题,方便以后查找指导,文字一点点积累,心路一点点向前。

从一个问题开始说起

问题场景:适配动态权限时候会,对于存储权限的处理比较麻烦,因为存储功能几乎是app的必备功能之一了,而且很多的地方会用到这个权限。那如何去处理这个存储权限的问题呢?

当然,如果新写的app,可以很好的避免这个问题,在每个用到的地方去请求。但是如果需要改造一个老项目,对于这个问题,就有点不好办了?因为项目中用到的存储的地方太多了,如果每个地方加上这个权限判断几乎不现实,容易漏,如何破解呢?我看到微信的做法是当app在运行的时候,用户如果手动的把微信的存储权限关掉,再回到app,这时候微信会跳转到闪屏页面,并弹出权限请求框,授予则回到之前的运行的界面,否则退出app,再次点击,重新请求登录并到首页。这个比较好的交互方式规避了之前的问题,算是比较优雅的;如何做到的呢?

首先:我们app 界面有baseActivity, 然后在baseActiviy中去判断权限,如果没有则用ActivityListManager 管理栈工具找到当前界面,跳转到SplashActivity, 同时带上 FLAG_ACTIVITY_CLEAR_TASK , FLAG_ACTIVITY_NEW_TASK标记位,并在SplashActivity界面中onCreate检查权限,同时要注意一点是不要继承BaseActiviy,因为如果SplashActivity继承BaseActivity,会出现自己启动自己,并一直循环的情况。

代码展示:

ActivityListManager的代码:

    public void goToSplashActivity(){
        // 用了Arouter
        ARouter.getInstance().build("/app/activity/SplashActivity")
                .withFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
                .withTransition(R.anim.slide_in_right, slide_out_left)
                .navigation(getCurrentyActivity())
        ;
    }

BaseActivity的代码就是在onCreate中checkPermission;

 protected void checkStoragePermission(){

        if(ContextCompat.checkSelfPermission(this,android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityListManager.getInstance().goToSplashActivity();
        }
    }

但是,这样做会有一个小瑕疵,就是不能像微信一样在闪屏页面同意了你的权限请求回到之前的界面,怎么办呢?是不是可以用一个UI界面和闪屏页一样的界面但是里面什么都不做,仅仅是权限请求,如果同意了,则finish自己,否则,调用ActivityListManager中的的finishAllActivity的方法,是不是就能和微信一样的呢? 有没有大兄弟试一试呢?

用户动态改变权限对app的影响

场景:假如说app在运行,用户点任务键,然后设置界面把app的任一已被授予的权限关闭,这个时候回到app 会怎么样呢?

当然,当用户关闭任一权限的时候,app会被暂时杀死,当你点击app时,app会恢复之前的界面,application 也会重新走相关的逻辑:重新走application ——》 之前的最后界面;之间界面逻辑不会走,这种情况是异常结束acitvity,系统只会恢复最后展会的界面及界面中的UI组件状态和值,其他的系统变量则不予管理

所有的内存缓存和类中的类变量都会成为初始值,因为系统已经把activity的实例给回收了,所以依赖于类的变量都会为初始值,这一点对最后被恢复的界面也适用,上面提到了 “系统只会恢复最后界面及界面中的UI组件状态和值,其他的系统变量则不予管理; 这是系统的默认行为,除非我们主动调用onSaveInstates 方法存类中的变量,和重写 onRestoreInstantes方法获取之前存的变量,但这样一来,根本就不现实,一个类中如此多的类变量,没有哪个程序是用这样的办法来解决app被异常杀掉保存数据的。所以最后展示的界面也只是恢复UI组件和想应的值,但是该类变量值却成为默认值,此时就有可能出现空指针情况。

还要提示一点:虽然activity实例被销毁,但栈中还是保留相应记录,即activity栈没有被清空 ;所以我们按返回键还是可以按照之前的顺序回到主页面,而不是一下子就回到了主界面。

另外,再说一点,同样的设置,我们在改变系统的语言时候,app不会被杀死,只是会把当前的界面的生命周期再走一遍,进程还是同一个。所以,不同系统设置其影响也是不一样的,这一点也要注意的。

看到这里,要知道这是属于异常结束进程或者杀掉app界面,那我们联系到之前说的 app后台被杀掉后如何重启app恢复相关逻辑?解决方式网上大多是 新建一个类AppStatusManager ,里面弄一个变量status对应正常和app被杀两种情况,然后在闪屏页给其赋正常情况值,在BaseActivity中判断status的值是否是被杀情况的值,是的话去闪屏页,不是的话就不用管了。此方案是解决用户在app运行时到系统设置界面取消权限比较好的处理方式。

请求多个权限时提示语处理

当某个界面有多个界面需要请求,系统api提供了简单方法,

ActivityCompat.requestPermissions(this,
                    new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,WRITE_PERSSION},
                    PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);

可以一次性请求多个权限,但是我们回调的时候却只有一个code,我们还需要一些flag量去标记这些权限到底有没有被授予,没被授予则进行弹框提示,对于一些第三方权限框架,有时候也没有考虑到这个问题,所以我们有时候可以分开去请求每一个权限,然后处理结果,这样就比较好对应,同时自己在封装的时候也需要注意。

参考文章:

app运行时,系统设置界面关闭权限 :https://www.jianshu.com/p/cb68ca511776

猜你喜欢

转载自blog.csdn.net/sjh_389510506/article/details/84452385
今日推荐