Android在应用设置里关闭权限,返回生命周期处理
问题
在处理6.0运行时权限时,很多人都忽略了这样一个问题:
在一个App应用里,如果已经允许了一个权限比如(读取通讯权限),此刻去调用相机,弹出权限申请对话框,此刻点击拒绝,然后经过处理后弹出去设置权限界面(因为权限总归是要申请),如果再在置界面里打开应用权限设置,此刻不但不打开相机权限反而将已经申请的读取通讯录权限关闭会怎样?流程图如下图片步骤:
- 原图
![](http://upload-images.jianshu.io/upload_images/2325960-527f4ddbf2dd2a44.png)
- 步骤一,打开通讯权限,并点击允许
![](http://upload-images.jianshu.io/upload_images/2325960-dfb165a066176723.png)
- 步骤二,打开相机申请权限,并点击拒绝
![](http://upload-images.jianshu.io/upload_images/2325960-dcf8ddd328833e1b.png)
- 步骤三,相机权限拒绝后弹出去设置对话框
![](http://upload-images.jianshu.io/upload_images/2325960-e604b2911ebbec6a.png)
步骤四,点击设置打开应用设置
![](http://upload-images.jianshu.io/upload_images/2325960-a771d6ad2689d7b5.png)
![](http://upload-images.jianshu.io/upload_images/2325960-192e926369dc239f.png)
![](http://upload-images.jianshu.io/upload_images/2325960-7c0297c6ca4edf2d.png)
- 步骤六,点击还回按键,回到自己的App
分析
经过以上的步骤可以发现,当权限关闭后应用会重新启动,并且会默认直接打开权限申请的那个界面,不会打开启动页,为什么呢,因为当权限关闭后,程序会被杀人,Activity是异常结束的,当返回是,app会默认修复最后打开的那个界面。
证实
上面的分析接下来一一证实,为了让权限申请界面避开自己是启动页界面,我将会在写两个界面,界面跳转步骤是
LanchActivity----》MainActivity----》PremissionActivity
- LanchActivity
![](http://upload-images.jianshu.io/upload_images/2325960-14c599ab89edafae.png)
![](http://upload-images.jianshu.io/upload_images/2325960-5a2701f3b40d1e7f.png)
- MainActivity
![](http://upload-images.jianshu.io/upload_images/2325960-6ac2a35801b92a47.png)
![](http://upload-images.jianshu.io/upload_images/2325960-fdbafc34a62eeb94.png)
PremissionActivity
![](http://upload-images.jianshu.io/upload_images/2325960-6d95fa6cc3435886.png)
![](http://upload-images.jianshu.io/upload_images/2325960-831c0e1cacf92f42.png)
- MyApplication 用于应用重启判断
![](http://upload-images.jianshu.io/upload_images/2325960-7f6584d29873fa27.png)
启动程序
启动程序,并且按照上面的步骤去关闭权限然后还回,看看打印结果
![](http://upload-images.jianshu.io/upload_images/2325960-9f156813eb616138.png)
可以看得很清楚Application再次执行,并且PremissionActivity界面也会重新被加载,并且savedInstanceState不为空!也可以知道程序此刻并不会启动启动页LanchActivity!
此时按还回键会出现什么情况?看看打印结果:
![](http://upload-images.jianshu.io/upload_images/2325960-e6ac7588f878adc6.png)
可以看到会按正常的返回回到启动页,但是启动页和主界面都是异常杀死的,所以savedInstanceState都会有数据
总结
有了以上的测试就可以知道权限被强行关闭后的生命周期,有的时候程序有很多数据,关闭权限还回后,有些数据丢失并不能恢复,就会出现空指针异常的情况!所以这里可以按照微信的设计思路就是:
强行关闭权限后,让程序重新打开启动页!
处理如下:
疑难问题,关闭程序后返回会出现一下白屏的问题!目前还不知如何解决这个问题,请告知!
PremissionActivity代码:
public class PremissionActivity extends AppCompatActivity { private static final int REQUEST_CAMERA_PERMISSION = 0x103; private static final int REQUEST_PRE_SET = 0x104; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.e("PNH", "PremissionActivity启动savedInstanceState=" + savedInstanceState); if (null != savedInstanceState) { Intent intent = new Intent(this, LanchActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); } setContentView(R.layout.activity_premission); findViewById(R.id.camera).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ContextCompat.checkSelfPermission(PremissionActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(PremissionActivity.this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); } } }); findViewById(R.id.contact).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 检查是否已经具有权限 if (ContextCompat.checkSelfPermission(PremissionActivity.this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(PremissionActivity.this, new String[]{Manifest.permission.READ_CONTACTS}, 3); } } }); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_CAMERA_PERMISSION) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { } else { //权限拒绝 openAppSetting(); } } } protected void openAppSetting() { MaterialDialog materialDialog = new MaterialDialog.Builder(this) .content("在设置-应用-GcsSloop-权限中开启相机权限,以正常使用拍照、小视频、扫一扫等功能") .positiveText("去设置") .negativeText("取消") .onNegative(new MaterialDialog.SingleButtonCallback() { @Override public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { } }) .onPositive(new MaterialDialog.SingleButtonCallback() { @Override public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { // Intent intent = new Intent("/"); // ComponentName cm = new ComponentName("com.android.settings","com.android.settings.ManageApplications"); // intent.setComponent(cm); // intent.setAction("android.intent.action.VIEW"); // startActivityForResult( intent , 0); // 打开权限设置界面 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse("package:" + getPackageName())); // 申请权限返回执行 startActivityForResult(intent, REQUEST_PRE_SET); } }).build(); materialDialog.show(); } }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
2016-07-11 【Java线程】Java线程池ExecutorService
2016-07-11 MappedByteBuffer高速缓存文件、RandomAccessFile随机访问
2016-07-11 RandomAccessFile和memory-mapped files
2016-07-11 花1K内存实现高效I/O的RandomAccessFile类
2016-07-11 java中利用RandomAccessFile读取超大文件
2016-07-11 android 多线程断点续传下载
2016-07-11 android 多线程断点续传下载 三