Android运行时权限,6.0—9.0多版本,多终端(手机,TV盒子)130行代码一劳永逸
16lz
2022-01-17
Android在API 23之后开启了危险权限动态申请的机制,具体有哪些权限这里不做赘述,只拿笔者在手机和TV端开发中用到的权限例举,示例Demo并没有依赖任何的第三方库,纯Android代码,大约130行左右。
1.新建一个用于检查权限的Activity,定义申请权限数组和请求码,在onCreate中进行权限检查,将没有授权的权限添加到待申请列表。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); ArrayList<String> needGetList = null; for (String permission : mPermissions) {// 检查是否已经授权 if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_DENIED) { if (needGetList == null){ needGetList = new ArrayList<>(); } //没有授权,添加到待申请列表 needGetList.add(permission); } } // 进行申请动作 actionPermission(needGetList, needGetList == null ? true : false); }
2.根据待申请集合和结果进行申请动作
private void actionPermission(ArrayList<String> needGetList, boolean result){ // 有需要申请的权限 if (needGetList != null && needGetList.size() > 0){ System.out.println(needGetList.toString()); String[] arrays = new String[needGetList.size()]; for (int i = 0; i < needGetList.size(); i++) { arrays[i] = needGetList.get(i); } ActivityCompat.requestPermissions(this, arrays, MY_PERMISSIONS_REQUEST_READ_CONTACTS); }else { if (result){ // 授权成功 Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(this, "授权失败,您可之后到系统应用管理页面进行手动授权", Toast.LENGTH_SHORT).show(); } startActivity(new Intent(this, HomeActivity.class)); finish(); } }
3.重写onRequestPermissionsResult方法获取申请的结果
返回的permissions是所有发起申请的权限,grantResults是对应的申请结果,下标是一一对应的。判断grantResults的结果是不是PackageManager.PERMISSION_DENIED(被拒绝),如果有被拒绝的权限弹出对话框提示,如果没有则关闭页面。
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case MY_PERMISSIONS_REQUEST_READ_CONTACTS: { ArrayList<String> denied = new ArrayList<>(); for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] == PackageManager.PERMISSION_DENIED){ denied.add(permissions[i]); } } if (denied.size() > 0 ){ // 有未申请到得权限 需要弹框提醒 showRationaleDialog(denied); }else {// 申请到所有权限 跳转页面 actionPermission(null, true); } } } }
4.弹出对话框提示用户是否继续授权
点击继续授权跳转到系统应用管理中本应用的详情页面进行开启,点击取消提示用户授权失败并关闭页面(如遇必须权限可以提示用户不授权无法使用)
注:手机端打开详情页面没有问题,但部分TV盒子将应用详情给砍掉了,会打开失败。
/** * 弹出提示语 * */ private void showRationaleDialog(final ArrayList<String> denied) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("提示"); TextView mMsg = new TextView(this); mMsg.setText("您还有权限未授权完毕,将导致应用无法正常使用,是否跳转到系统设置界面继续授权?"); mMsg.setGravity(Gravity.CENTER_HORIZONTAL); mMsg.setTextSize(18); builder.setView(mMsg); builder.setCancelable(false); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); try{// 打开系统 本应用的详情页面 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.fromParts("package", BeforeActivity.this.getPackageName(), null)); BeforeActivity.this.startActivity(intent); }catch (Exception e){ Log.e(TAG, "打开当前本应用设置界面失败: " + e.getMessage()); try{// 打开系统已安装应用页面 BeforeActivity.this.startActivity(new Intent(Settings.ACTION_APPLICATION_SETTINGS)); }catch (Exception e2){ Log.e(TAG, "打开应用设置界面失败: " + e.getMessage()); Toast.makeText(BeforeActivity.this, "打开应用设置界面失败", Toast.LENGTH_SHORT).show();// 如果都打开失败 提示用户手动之后手动开启权限 并关闭页面 actionPermission(null, false); } } toAppDetail = true; } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); actionPermission(null, false); } }); Dialog tipDialog = builder.create(); tipDialog.setCanceledOnTouchOutside(false); tipDialog.show(); }
5.从系统的应用详情页返回后
这里用的是重写onStart方法根据标志位来做的判断,页面重新可见后再次检查权限是否已经都可用,权限都可用就关闭页面,如果依然有未开启的权限则提示用户。
@Override protected void onStart() { super.onStart(); if (toAppDetail){ toAppDetail = false; for (String permission : mPermissions) {// 检查是否已经授权 if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_DENIED) { actionPermission(null, false); return; } } actionPermission(null, true); } }
整体流程就是这样,经过测试目前在华为、荣耀、小米、vivo手机上都可以实现权限的动态申请,另外TV端在小米、天猫、当贝部分盒子上也可以实现动态获取。
Demo详情地址:https://github.com/TheTangEmperor/permissiondemo.git
更多相关文章
- Android屏幕锁定实例源码详解教程一
- Android兼容android7.0、及Android8.0以上apk安装权限问题(二)
- Android(安卓)为【apk】文件签名,增加修改系统时间等权限
- Android(安卓)的提权 (root) 原理是什么?
- Android之权限管理
- Android日志打印与处理 UncaughtExceptionHandler 提交服务器
- Android利用Http下载文件
- Android开机广播和关机广播
- 申请Android(安卓)Maps API Key,以及出现的错误