问题
在处理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}, 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();
}
}