问题

在处理6.0运行时权限时,很多人都忽略了这样一个问题:
在一个App应用里,如果已经允许了一个权限比如(读取通讯权限),此刻去调用相机,弹出权限申请对话框,此刻点击拒绝,然后经过处理后弹出去设置权限界面(因为权限总归是要申请),如果再在置界面里打开应用权限设置,此刻不但不打开相机权限反而将已经申请的读取通讯录权限关闭会怎样?流程图如下图片步骤

  • 原图
      01.png
  • 步骤一,打开通讯权限,并点击允许
     02.png
  • 步骤二,打开相机申请权限,并点击拒绝
      03.png
  • 步骤三,相机权限拒绝后弹出去设置对话框
    去设置.png
    • 步骤四,点击设置打开应用设置

                   04.png
  • 步骤五,点击权限,打开权限设置,并关闭已经申请成功的读取通讯录权限
 
     05.png
 
      06.png
  • 步骤六,点击还回按键,回到自己的App

分析

经过以上的步骤可以发现,当权限关闭后应用会重新启动,并且会默认直接打开权限申请的那个界面,不会打开启动页,为什么呢,因为当权限关闭后,程序会被杀人,Activity是异常结束的,当返回是,app会默认修复最后打开的那个界面。

证实

上面的分析接下来一一证实,为了让权限申请界面避开自己是启动页界面,我将会在写两个界面,界面跳转步骤是

LanchActivity----》MainActivity----》PremissionActivity

  • LanchActivity
  LanchActivity.png
 
            1501507953(1).png
  • MainActivity
  MainActivity.png
              1501507990(1).png
    • PremissionActivity

        PremissionActivity.png
                  1501508027(1).png
  • MyApplication 用于应用重启判断
            1501507895(1).png

启动程序

启动程序,并且按照上面的步骤去关闭权限然后还回,看看打印结果

                  image.png

可以看得很清楚Application再次执行,并且PremissionActivity界面也会重新被加载,并且savedInstanceState不为空!也可以知道程序此刻并不会启动启动页LanchActivity!

此时按还回键会出现什么情况?看看打印结果:

                  image.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}, );
}
}
});
} @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 > && grantResults[] == 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(); } }

最新文章

  1. 增强学习(三)----- MDP的动态规划解法
  2. Git Merge Commit忘了选分支?数据丢失? 刚刚做的都丢失了?别急!
  3. ASP.NET输出JSON格式数据
  4. Django的Model上都有些什么
  5. 【java消息格式化】使用MessageFormat进行消息格式化
  6. 【HDU 5030】Rabbit's String (二分+后缀数组)
  7. ↗☻【编写可维护的JavaScript #BOOK#】第8章 避免“空比较”
  8. KVC vs KVO(内容为转载记录,整合大家的总结为我所用)
  9. STM32库中 __IO 修饰符(volatile修饰符)
  10. pyqt学习总结
  11. Java反射机制练习
  12. 总结Ajax验证注册功能的两种方式
  13. java实现二叉树的前中后遍历(递归和非递归)
  14. [测试题]wows
  15. 详解Java的Spring框架中的注解的用法
  16. mysql安装与配置详情
  17. unity UGUI UI跟随
  18. Python:BeautifulSoup移除某些不需要的属性
  19. 【Java算法】获得一个随机字符串
  20. 【Jmeter】Linux(Mac)上使用最新版本Jmeter(5.0)做性能测试

热门文章

  1. p4555&bzoj2565 最长双回文串
  2. webAPI路由的使用
  3. 7.29实习培训日志-Oracle题目
  4. Java数组转置
  5. jquery筛选元素函数
  6. PHP开源系统学习之fluxbb_1
  7. [CentOS7] systemd
  8. Unity3D -- shader常用函数和变量
  9. [Django笔记] django结构分析
  10. 初识XML