转载自:http://blog.csdn.net/lin_dianwei/article/details/79025324
Android M 或以上的设备,在使用涉及隐私的安全权限时,需要动态申请,虽然不难,但写下来代码工作量也不少,而且几乎每个应用都需要用到。所以一直在探索一个要足够简单简洁优雅的处理方式,强迫症的精神指导我要拒绝一切繁琐。至于完不完美那就仁者见仁了。
一、思路:
如果在每个用到权限的地方去申请,有点繁琐,所以做法是直接在每个Activity界面显示前就把该界面所需的权限全部申请允许了,再进入正常的流程。如果有权限未被允许,开发者可以在接口中自己处理,可以直接提示并退出,或者提示权限的作用后重新发起权限申请。
二、危险权限列表:Dangerous Permissions
在Android M 或以上,以下权限需要动态申请的意思。
- group:android.permission-group.CONTACTS
- permission:android.permission.WRITE_CONTACTS
- permission:android.permission.GET_ACCOUNTS
- permission:android.permission.READ_CONTACTS
- group:android.permission-group.PHONE
- permission:android.permission.READ_CALL_LOG
- permission:android.permission.READ_PHONE_STATE
- permission:android.permission.CALL_PHONE
- permission:android.permission.WRITE_CALL_LOG
- permission:android.permission.USE_SIP
- permission:android.permission.PROCESS_OUTGOING_CALLS
- permission:com.android.voicemail.permission.ADD_VOICEMAIL
- group:android.permission-group.CALENDAR
- permission:android.permission.READ_CALENDAR
- permission:android.permission.WRITE_CALENDAR
- group:android.permission-group.CAMERA
- permission:android.permission.CAMERA
- group:android.permission-group.SENSORS
- permission:android.permission.BODY_SENSORS
- group:android.permission-group.LOCATION
- permission:android.permission.ACCESS_FINE_LOCATION
- permission:android.permission.ACCESS_COARSE_LOCATION
- group:android.permission-group.STORAGE
- permission:android.permission.READ_EXTERNAL_STORAGE
- permission:android.permission.WRITE_EXTERNAL_STORAGE
- group:android.permission-group.MICROPHONE
- permission:android.permission.RECORD_AUDIO
- group:android.permission-group.SMS
- permission:android.permission.READ_SMS
- permission:android.permission.RECEIVE_WAP_PUSH
- permission:android.permission.RECEIVE_MMS
- permission:android.permission.RECEIVE_SMS
- permission:android.permission.SEND_SMS
- permission:android.permission.READ_CELL_BROADCASTS
先从Activity的使用开始。
- public class MainActivity extends AppCompatActivity implements PermissionInterface {
- private PermissionHelper mPermissionHelper;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //初始化并发起权限申请
- mPermissionHelper = new PermissionHelper(this, this);
- mPermissionHelper.requestPermissions();
- }
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- if(mPermissionHelper.requestPermissionsResult(requestCode, permissions, grantResults)){
- //权限请求结果,并已经处理了该回调
- return;
- }
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- }
- @Override
- public int getPermissionsRequestCode() {
- //设置权限请求requestCode,只有不跟onRequestPermissionsResult方法中的其他请求码冲突即可。
- return 10000;
- }
- @Override
- public String[] getPermissions() {
- //设置该界面所需的全部权限
- return new String[]{
- Manifest.permission.WRITE_EXTERNAL_STORAGE,
- Manifest.permission.READ_PHONE_STATE
- };
- }
- @Override
- public void requestPermissionsSuccess() {
- //权限请求用户已经全部允许
- initViews();
- }
- @Override
- public void requestPermissionsFail() {
- //权限请求不被用户允许。可以提示并退出或者提示权限的用途并重新发起权限申请。
- finish();
- }
- private void initViews(){
- //已经拥有所需权限,可以放心操作任何东西了
- }
- }
1、Activity需要实现的接口PermissionInterface.java
- /**
- * 权限请求接口
- * Created by dway on 2018/1/10.
- */
- public interface PermissionInterface {
- /**
- * 可设置请求权限请求码
- */
- int getPermissionsRequestCode();
- /**
- * 设置需要请求的权限
- */
- String[] getPermissions();
- /**
- * 请求权限成功回调
- */
- void requestPermissionsSuccess();
- /**
- * 请求权限失败回调
- */
- void requestPermissionsFail();
- }
- /**
- * 动态权限工具类
- * Created by dway on 2017/1/13.
- */
- public class PermissionUtil {
- /**
- * 判断是否有某个权限
- * @param context
- * @param permission
- * @return
- */
- public static boolean hasPermission(Context context, String permission){
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- if(context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED){
- return false;
- }
- }
- return true;
- }
- /**
- * 弹出对话框请求权限
- * @param activity
- * @param permissions
- * @param requestCode
- */
- public static void requestPermissions(Activity activity, String[] permissions, int requestCode){
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- activity.requestPermissions(permissions, requestCode);
- }
- }
- /**
- * 返回缺失的权限
- * @param context
- * @param permissions
- * @return 返回缺少的权限,null 意味着没有缺少权限
- */
- public static String[] getDeniedPermissions(Context context, String[] permissions){
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- ArrayList<String> deniedPermissionList = new ArrayList<>();
- for(String permission : permissions){
- if(context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED){
- deniedPermissionList.add(permission);
- }
- }
- int size = deniedPermissionList.size();
- if(size > 0){
- return deniedPermissionList.toArray(new String[deniedPermissionList.size()]);
- }
- }
- return null;
- }
- }
- package com.dway.permission;
- import android.app.Activity;
- import android.content.pm.PackageManager;
- import android.support.annotation.NonNull;
- /**
- * 动态权限帮助类
- * Created by dway on 2018/1/10.
- */
- public class PermissionHelper {
- private Activity mActivity;
- private PermissionInterface mPermissionInterface;
- public PermissionHelper(@NonNull Activity activity, @NonNull PermissionInterface permissionInterface) {
- mActivity = activity;
- mPermissionInterface = permissionInterface;
- }
- /**
- * 开始请求权限。
- * 方法内部已经对Android M 或以上版本进行了判断,外部使用不再需要重复判断。
- * 如果设备还不是M或以上版本,则也会回调到requestPermissionsSuccess方法。
- */
- public void requestPermissions(){
- String[] deniedPermissions = PermissionUtil.getDeniedPermissions(mActivity, mPermissionInterface.getPermissions());
- if(deniedPermissions != null && deniedPermissions.length > 0){
- PermissionUtil.requestPermissions(mActivity, deniedPermissions, mPermissionInterface.getPermissionsRequestCode());
- }else{
- mPermissionInterface.requestPermissionsSuccess();
- }
- }
- /**
- * 在Activity中的onRequestPermissionsResult中调用
- * @param requestCode
- * @param permissions
- * @param grantResults
- * @return true 代表对该requestCode感兴趣,并已经处理掉了。false 对该requestCode不感兴趣,不处理。
- */
- public boolean requestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){
- if(requestCode == mPermissionInterface.getPermissionsRequestCode()){
- boolean isAllGranted = true;//是否全部权限已授权
- for(int result : grantResults){
- if(result == PackageManager.PERMISSION_DENIED){
- isAllGranted = false;
- break;
- }
- }
- if(isAllGranted){
- //已全部授权
- mPermissionInterface.requestPermissionsSuccess();
- }else{
- //权限有缺失
- mPermissionInterface.requestPermissionsFail();
- }
- return true;
- }
- return false;
- }
- }
OK,完成。哪个Activity需要权限就实现接口,其他用帮助类就全部搞定。