1.前言
在此前的原生安卓系统中有应用通知管理功能,但更为深入的应用权限管理只能靠第三方应用实现。Android 6.0进一步强化应用权限管理,应用权限管理也成为系统级的功能,若没有加入适配的话应用很容易崩溃。先放出一篇官方的说明文档了解一下,很详细哦
Google官方也在GitHub上开源了一款的第三方库EasyPermission,帮助你管理权限
英语不过关?请点下面
2.问题
Activity需要的不止一个权限,用户也可以在手机设置中修改相应的权限,如下图:
Screenshot_2017-03-06-09-46-20-194_com.miui.securitycenter.png所以需要在每次遇到Dangerous Permission 相关的业务处理时都要添加权限判断处理。虽然代码不多,但是需要同时在onRequestPermissionsResult、onPermissionsGranted、onPermissionsDenied等多处进行代码处理。就会显得很乱,降低代码的可读性。
最理想的方式当然时只要在需要的地方加一行代码即可以处理权限。封装权限处理应运而生。
3.封装后的处理
我们先直接看封装后的权限处理代码变成了什么样。下面是一个打开摄像头的业务,调用业务前需要处理摄像头权限。
public void cameraTask() {
String[] perms = {Manifest.permission.CAMERA};
performCodeWithPermission(getString(R.string.rationale_camera), RC_CAMERA_PERM, perms, new PermissionCallback() {
@Override
public void hasPermission(List<String> allPerms) {
Toast.makeText(SimplePermActivity.this, "TODO: Camera things", Toast.LENGTH_LONG).show();
}
@Override
public void noPermission(List<String> deniedPerms, List<String> grantedPerms, Boolean hasPermanentlyDenied) {
if (hasPermanentlyDenied) {
alertAppSetPermission(getString(R.string.rationale_ask_again), RC_SETTINGS_SCREEN);
}
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SETTINGS_SCREEN) {
Toast.makeText(this, R.string.returned_from_app_settings_to_activity, Toast.LENGTH_SHORT)
.show();
}
}
注意下上面代码的alertAppSetPermission方法作用是,当权限被拒绝时,判断如果点了不再询问被拒绝的情况后弹出一个alert框,提示用户前往系统设置开启权限,这样更加人性化,不然如果用户拒绝过一次后之后的该权限将全部都会被拒绝。如下图
Screenshot_2017-03-06-10-08-23-973_com.ajmd.png再看下alertAppSetPermission方法有2个重载方法,有一个比另一个多了个requestCode参数。目的是当用户跳转系统设置返回后,有的需求可能希望返回后自动再判断用户有没有在系统设置中修改过权限从而直接继续下一步操作。这样实现onActivityResult方法,在系统页面返回时再次判断权限是否授予。
通过上面代码可以发现,封装过后只需要在需要权限处理的地方加一个performCodeWithPermission,然后再重载onActivityResult方法。如果没有页面返回后自动继续下一步的需求的话那就只需要调用performCodeWithPermission就可以了。做到了“伪一行代码”处理运行时权限。哈哈!
没有对比就没有伤害,我再把没有封装过的完整权限处理代码贴上来对比下。(使用了EasyPermission)
@AfterPermissionGranted(RC_CAMERA_PERM)
public void cameraTask() {
if (EasyPermissions.hasPermissions(this, Manifest.permission.CAMERA)) {
Toast.makeText(this, "TODO: Camera things", Toast.LENGTH_LONG).show();
} else {
EasyPermissions.requestPermissions(this, getString(R.string.rationale_camera),
RC_CAMERA_PERM, Manifest.permission.CAMERA);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
@Override
public void onPermissionsGranted(int requestCode, List<String> perms) {
Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size());
}
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
new AppSettingsDialog.Builder(this, getString(R.string.rationale_ask_again))
.setTitle(getString(R.string.title_settings_dialog))
.setPositiveButton(getString(R.string.setting))
.setNegativeButton(getString(R.string.cancel), null)
.setRequestCode(RC_SETTINGS_SCREEN)
.build()
.show();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SETTINGS_SCREEN) {
Toast.makeText(this, R.string.returned_from_app_settings_to_activity, Toast.LENGTH_SHORT)
.show();
}
}
发现比封装过的多了onRequestPermissionsResult、onPermissionsGranted、onPermissionsDenied三个回调的处理。就是说每次写权限处理需要写45个地方。而封装过的只需要写12个即可。
4.总结
在项目开发中,多处需要进行权限处理,必要的封装可以大大增加代码可读性,专注于业务代码的编写。
最后附上权限清单,android.Manifest.permission 上可以找到基础平台定义的权限列表。
网友评论