Android 6.0: 动态权限管理的解决方案

Android精品源码
封面图:
Android 6.0版本(Api 23)推出了很多新的特性, 大幅提升了用户体验, 同时也为程序员带来新的负担. 动态权限管理就是这样, 一方面让用户更加容易的控制自己的隐私, 一方面需要重新适配应用权限. 时代总是不断发展, 程序总是以人为本, 让我们为应用添加动态权限管理吧! 这里提供了一个非常不错的解决方案, 提供源码, 项目可以直接使用.
 

Android系统包含默认的授权提示框, 但是我们仍需要设置自己的页面. 原因是系统提供的授权框, 会有不再提示的选项. 如果用户选择, 则无法触发授权提示. 使用自定义的提示页面, 可以给予用户手动修改授权的指导.
 
如果用户点击, 不再提示, 则系统授权弹窗将不会弹出. 流程变为:
 

流程就这些, 让我们看看代码吧.

1. 权限
在AndroidManifest中, 添加两个权限, 录音修改音量.
[XML]  查看源文件  复制代码
?
1
2
3
4
5
<!--危险权限-->
  < uses-permission android:name = "android.permission.RECORD_AUDIO" />
 
  <!--一般权限-->
  < uses-permission android:name = "android.permission.MODIFY_AUDIO_SETTINGS" />
危险权限必须要授权, 一般权限不需要.
检测权限类
[Java]  查看源文件  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
  * 检查权限的工具类
  * <p/>
  * Created by wangchenlong on 16/1/26.
  */
public class PermissionsChecker {
     private final Context mContext;
 
     public PermissionsChecker(Context context) {
         mContext = context.getApplicationContext();
     }
 
     // 判断权限集合
     public boolean lacksPermissions(String... permissions) {
         for (String permission : permissions) {
             if (lacksPermission(permission)) {
                 return true ;
             }
         }
         return false ;
     }
 
     // 判断是否缺少权限
     private boolean lacksPermission(String permission) {
         return ContextCompat.checkSelfPermission(mContext, permission) ==
                 PackageManager.PERMISSION_DENIED;
     }
}
2. 首页
假设首页需要使用权限, 在页面显示前, 即onResume时, 检测权限,
如果缺少, 则进入权限获取页面; 接收返回值, 拒绝权限时, 直接关闭.
[Java]  查看源文件  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class MainActivity extends AppCompatActivity {
 
     private static final int REQUEST_CODE = 0 ; // 请求码
 
     // 所需的全部权限
     static final String[] PERMISSIONS = new String[]{
             Manifest.permission.RECORD_AUDIO,
             Manifest.permission.MODIFY_AUDIO_SETTINGS
     };
 
     @Bind (R.id.main_t_toolbar) Toolbar mTToolbar;
 
     private PermissionsChecker mPermissionsChecker; // 权限检测器
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         ButterKnife.bind( this );
 
         setSupportActionBar(mTToolbar);
 
         mPermissionsChecker = new PermissionsChecker( this );
     }
 
     @Override protected void onResume() {
         super .onResume();
 
         // 缺少权限时, 进入权限配置页面
         if (mPermissionsChecker.lacksPermissions(PERMISSIONS)) {
             startPermissionsActivity();
         }
     }
 
     private void startPermissionsActivity() {
         PermissionsActivity.startActivityForResult( this , REQUEST_CODE, PERMISSIONS);
     }
 
     @Override protected void onActivityResult( int requestCode, int resultCode, Intent data) {
         super .onActivityResult(requestCode, resultCode, data);
         // 拒绝时, 关闭页面, 缺少主要权限, 无法运行
         if (requestCode == REQUEST_CODE && resultCode == PermissionsActivity.PERMISSIONS_DENIED) {
             finish();
         }
     }
}
核心权限必须满足, 如摄像应用, 摄像头权限就是必须的, 如果用户不予授权, 则直接关闭.

3. 授权页授权页, 首先使用系统默认的授权页, 当用户拒绝时, 指导用户手动设置, 当用户再次操作失败后, 返回继续提示. 用户手动退出授权页时, 给使用页发送授权失败的通知.
[Java]  查看源文件  复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
  * 权限获取页面
  * <p/>
  * Created by wangchenlong on 16/1/26.
  */
public class PermissionsActivity extends AppCompatActivity {
 
     public static final int PERMISSIONS_GRANTED = 0 ; // 权限授权
     public static final int PERMISSIONS_DENIED = 1 ; // 权限拒绝
 
     private static final int PERMISSION_REQUEST_CODE = 0 ; // 系统权限管理页面的参数
     private static final String EXTRA_PERMISSIONS =
             "me.chunyu.clwang.permission.extra_permission" ; // 权限参数
     private static final String PACKAGE_URL_SCHEME = "package:" ; // 方案
 
     private PermissionsChecker mChecker; // 权限检测器
     private boolean isRequireCheck; // 是否需要系统权限检测
 
     // 启动当前权限页面的公开接口
     public static void startActivityForResult(Activity activity, int requestCode, String... permissions) {
         Intent intent = new Intent(activity, PermissionsActivity. class );
         intent.putExtra(EXTRA_PERMISSIONS, permissions);
         ActivityCompat.startActivityForResult(activity, intent, requestCode, null );
     }
 
     @Override protected void onCreate( @Nullable Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         if (getIntent() == null || !getIntent().hasExtra(EXTRA_PERMISSIONS)) {
             throw new RuntimeException( "PermissionsActivity需要使用静态startActivityForResult方法启动!" );
         }
         setContentView(R.layout.activity_permissions);
 
         mChecker = new PermissionsChecker( this );
         isRequireCheck = true ;
     }
 
     @Override protected void onResume() {
         super .onResume();
         if (isRequireCheck) {
             String[] permissions = getPermissions();
             if (mChecker.lacksPermissions(permissions)) {
                 requestPermissions(permissions); // 请求权限
             } else {
                 allPermissionsGranted(); // 全部权限都已获取
             }
         } else {
             isRequireCheck = true ;
         }
     }
 
     // 返回传递的权限参数
     private String[] getPermissions() {
         return getIntent().getStringArrayExtra(EXTRA_PERMISSIONS);
     }
 
     // 请求权限兼容低版本
     private void requestPermissions(String... permissions) {
         ActivityCompat.requestPermissions( this , permissions, PERMISSION_REQUEST_CODE);
     }
 
     // 全部权限均已获取
     private void allPermissionsGranted() {
         setResult(PERMISSIONS_GRANTED);
         finish();
     }
 
     /**
      * 用户权限处理,
      * 如果全部获取, 则直接过.
      * 如果权限缺失, 则提示Dialog.
      *
      * @param requestCode  请求码
      * @param permissions  权限
      * @param grantResults 结果
      */
     @Override
     public void onRequestPermissionsResult( int requestCode, @NonNull String[] permissions, @NonNull int [] grantResults) {
         if (requestCode == PERMISSION_REQUEST_CODE && hasAllPermissionsGranted(grantResults)) {
             isRequireCheck = true ;
             allPermissionsGranted();
         } else {
             isRequireCheck = false ;
             showMissingPermissionDialog();
         }
     }
 
     // 含有全部的权限
     private boolean hasAllPermissionsGranted( @NonNull int [] grantResults) {
         for ( int grantResult : grantResults) {
             if (grantResult == PackageManager.PERMISSION_DENIED) {
                 return false ;
             }
         }
         return true ;
     }
 
     // 显示缺失权限提示
     private void showMissingPermissionDialog() {
         AlertDialog.Builder builder = new AlertDialog.Builder(PermissionsActivity. this );
         builder.setTitle(R.string.help);
         builder.setMessage(R.string.string_help_text);
 
         // 拒绝, 退出应用
         builder.setNegativeButton(R.string.quit, new DialogInterface.OnClickListener() {
             @Override public void onClick(DialogInterface dialog, int which) {
                 setResult(PERMISSIONS_DENIED);
                 finish();
             }
         });
 
         builder.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() {
             @Override public void onClick(DialogInterface dialog, int which) {
                 startAppSettings();
             }
         });
 
         builder.show();
     }
 
     // 启动应用的设置
     private void startAppSettings() {
         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
         intent.setData(Uri.parse(PACKAGE_URL_SCHEME + getPackageName()));
         startActivity(intent);
     }
}
注意isRequireCheck参数的使用, 防止和系统提示框重叠.
系统授权提示: ActivityCompat.requestPermissions, ActivityCompat兼容低版本.
效果
关键部分就这些了, 动态权限授权虽然给程序员带来了一些麻烦, 但是对用户还是很有必要的, 我们也应该欢迎, 毕竟每个程序员都是半个产品经理.
危险权限列表
weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值