Android 6.0 动态权限:

除了要在AndroidManifest.xml中申请外,还需使用时,请求用户允许授权。

以下是需要单独申请的权限,共分为9组,每组只要有一个权限申请成功了,就默认整组权限都可以使用了。

如果将targetSdkVersion设置为>=23,则必须按照Android谷歌的要求,动态的申请权限,如果你暂时不打算支持动态权限申请,则targetSdkVersion最大只能设置为22.

1 group:android.permission-group.CONTACTS
 2     permission:android.permission.WRITE_CONTACTS
 3     permission:android.permission.GET_ACCOUNTS    
 4     permission:android.permission.READ_CONTACTS
 5 
 6   group:android.permission-group.PHONE
 7     permission:android.permission.READ_CALL_LOG
 8     permission:android.permission.READ_PHONE_STATE 
 9     permission:android.permission.CALL_PHONE
10     permission:android.permission.WRITE_CALL_LOG
11     permission:android.permission.USE_SIP
12     permission:android.permission.PROCESS_OUTGOING_CALLS
13     permission:com.android.voicemail.permission.ADD_VOICEMAIL
14 
15   group:android.permission-group.CALENDAR
16     permission:android.permission.READ_CALENDAR
17     permission:android.permission.WRITE_CALENDAR
18 
19   group:android.permission-group.CAMERA
20     permission:android.permission.CAMERA
21 
22   group:android.permission-group.SENSORS
23     permission:android.permission.BODY_SENSORS
24 
25   group:android.permission-group.LOCATION
26     permission:android.permission.ACCESS_FINE_LOCATION
27     permission:android.permission.ACCESS_COARSE_LOCATION
28 
29   group:android.permission-group.STORAGE
30     permission:android.permission.READ_EXTERNAL_STORAGE
31     permission:android.permission.WRITE_EXTERNAL_STORAGE
32 
33   group:android.permission-group.MICROPHONE
34     permission:android.permission.RECORD_AUDIO
35 
36   group:android.permission-group.SMS
37     permission:android.permission.READ_SMS
38     permission:android.permission.RECEIVE_WAP_PUSH
39     permission:android.permission.RECEIVE_MMS
40     permission:android.permission.RECEIVE_SMS
41     permission:android.permission.SEND_SMS
42     permission:android.permission.READ_CELL_BROADCASTS

其它的权限,不用动态申请权限,在AndroidManifest.xml中申请即可。

1 public class PermissionUtils {
 2 
 3     public static final int REQUEST_LOCATION_PERMISSION = 999;
 4 
 5     public static boolean requestPermission(final Activity activity, String requestPermission) {
 6         if (Build.VERSION.SDK_INT < 23) {
 7             return true;
 8         }
 9 
10         if (activity == null) {
11             return false;
12         }
13 
14         /**
15         (1)如果是6.0以下的手机,ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED,
16         (2)如果用户关闭了你申请的权限(如在安装的时候,将一些权限关闭了) 使用ActivityCompat.checkSelfPermission()
           则可能会导致程序崩溃(java.lang.RuntimeException: Unknown exception code: 1 msg null);
17         **/
18 
19         int checkSelfPermission;
20         try {
21             // 检查是否有此权限ActivityCompat.checkSelfPermission(...),如果已经开启,则可以做此权限下的功能。
22             checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission);
23         } catch (RuntimeException e) {
24             openSettingActivity(activity, activity.getResources().getString(R.string.permission_request));
25             return false;
26         }
27 
28         if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
29             // 如果未开启,则判断是否需要向用户解释为何申请权限shouldShowRequestPermissionRationale
30             if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) {
31                 // 如果需要(返回true),则可以弹出对话框提示用户申请权限原因,用户确认后申请权限requestPermissions().
32                 showMessage(activity, REQUEST_LOCATION_PERMISSION, requestPermission);
33             } else {
34                 // 如果不需要(返回false),则直接申请权限requestPermissions()。
35                 ActivityCompat.requestPermissions(activity, new String[] {requestPermission}
36                         , REQUEST_LOCATION_PERMISSION);
37             }
38             return false;
39 
40         } else {
41             return true;
42         }
43     }
44 
45     private static void openSettingActivity(final Activity activity, String message) {
46 
47         showMessageOKCancel(activity, message, new DialogInterface.OnClickListener() {
48             @Override
49             public void onClick(DialogInterface dialog, int which) {
50                 Intent intent = new Intent();
51                 intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
52                 Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
53                 intent.setData(uri);
54                 activity.startActivity(intent);
55             }
56         });
57     }
58 
59     private static void showMessage(final Activity activity, final int requestCode, final String requestPermission) {
60         String permissionsHint = activity.getResources().getString(R.string.location_permission_tip);
61         showMessageOKCancel(activity, permissionsHint
62                 , new DialogInterface.OnClickListener() {
63             @Override
64             public void onClick(DialogInterface dialog, int which) {
65                 ActivityCompat.requestPermissions(activity,
66                         new String[]{requestPermission},
67                         requestCode);
68             }
69         });
70     }
71 
72     private static void showMessageOKCancel(final Activity context, String message, DialogInterface.OnClickListener okListener) {
73         new AlertDialog.Builder(context)
74                 .setMessage(message)
75                 .setPositiveButton(android.R.string.ok, okListener)
76                 .setNegativeButton(android.R.string.cancel, null)
77                 .create()
78                 .show();
79     }
80 }

使用:请求位置权限:

1 if (PermissionUtils.requestPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
2     // todo
3 }

第三方SDK:EasyPermissions

EasyPermissions 。和系统提供的权限管理很相似,简化权限管理。

(1) 在build.gradle文件中引入包:

1 dependencies {
2   compile 'pub.devrel:easypermissions:0.1.7'
3 }

(2) 在需要申请权限的 Activity implementsEasyPermissions.PermissionCallbacks

1 public class MainActivity extends Activity implements EasyPermissions.PermissionCallbacks {
 3     @Override
 4     public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
 5         super.onRequestPermissionsResult(requestCode, permissions, grantResults);
 6         
 7         // 调用EasyPermissions的onRequestPermissionsResult方法,参数和系统方法保持一致,然后就不要关心具体的权限申请代码了
 8         EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
 9     }
10     @Override
11     public void onPermissionsGranted(int requestCode, List<String> list) {
12         // 此处表示权限申请已经成功,可以使用该权限完成app的相应的操作了
13         // TODO
14     }
15     @Override
16     public void onPermissionsDenied(int requestCode, List<String> list) {
17         // 此处表示权限申请被用户拒绝了,此处可以通过弹框等方式展示申请该权限的原因,以使用户允许使用该权限
18         // TODO
19     }
20 }

(3) 使用:AfterPermissionGranted注解是可选的,如果有该注解的话,那么当request值对应的权限申请通过的话会自动调用该方法。

1 @AfterPermissionGranted(RC_CAMERA_PERM)
 2 public void cameraTask() {
 3     if (EasyPermissions.hasPermissions(this, Manifest.permission.CAMERA)) {
 4         // 已经有摄像头权限了,可以使用该权限完成app的相应的操作 6     } else {
 7         // app还没有使用摄像头的权限,调用该方法进行申请,同时给出了相应的说明文案,提高用户同意的可能性
 8         EasyPermissions.requestPermissions(this, getString(R.string.rationale_camera),
 9                 RC_CAMERA_PERM, Manifest.permission.CAMERA);
10     }
11 }

 

Android6.0动态权限申请步骤以及需要注意的一些坑

Android 权限最佳实践和代码实例分析

作者:晕菜一员