Android6.0权限管理之开源项目Grant

本文在CSDN博客首发
转载请注明出处 
http://blog.csdn.net/u011071427/article/details/52062947
本文出自Allen李的博客


Android开发者应该都知道在Android6.0后添加了权限的动态管理,我以前也写过一片博客关于怎么处理权限的动态申请。传送门

今天主要介绍Github上的开源项目Grant是如何处理权限管理的。

先来一个Github的传送门:Grant

然后直接上代码

Grant里面一共有三个类,分别是:

(1)Permissions

  1. package com.anthonycr.grant;  
  2.   
  3. /** 
  4.  * Enum class to handle the different states 
  5.  * of permissions since the PackageManager only 
  6.  * has a granted and denied state. 
  7.  */  
  8. enum Permissions {  
  9.     GRANTED,  
  10.     DENIED,  
  11.     NOT_FOUND  
  12. }  
package com.anthonycr.grant;

/**
 * Enum class to handle the different states
 * of permissions since the PackageManager only
 * has a granted and denied state.
 */
enum Permissions {
    GRANTED,
    DENIED,
    NOT_FOUND
}

这是一个枚举类,用来对应三种状态:已授权,授权失败,未发现的权限


(2) PermissionsManager

  1. package com.anthonycr.grant;  
  2.   
  3. import android.Manifest;  
  4. import android.app.Activity;  
  5. import android.content.Context;  
  6. import android.content.pm.PackageInfo;  
  7. import android.content.pm.PackageManager;  
  8. import android.os.Build;  
  9. import android.support.annotation.NonNull;  
  10. import android.support.annotation.Nullable;  
  11. import android.support.v4.app.ActivityCompat;  
  12. import android.support.v4.app.Fragment;  
  13. import android.util.Log;  
  14.   
  15. import java.lang.ref.WeakReference;  
  16. import java.lang.reflect.Field;  
  17. import java.util.ArrayList;  
  18. import java.util.HashSet;  
  19. import java.util.Iterator;  
  20. import java.util.List;  
  21. import java.util.Set;  
  22.   
  23. /** 
  24.  * A class to help you manage your permissions simply. 
  25.  */  
  26. public class PermissionsManager {  
  27.   
  28.     private static final String TAG = PermissionsManager.class.getSimpleName();  
  29.   
  30.     private final Set<String> mPendingRequests = new HashSet<>(1);  
  31.     private final Set<String> mPermissions = new HashSet<>(1);  
  32.     private final List<WeakReference<PermissionsResultAction>> mPendingActions = new ArrayList<>(1);  
  33.   
  34.     private static PermissionsManager mInstance = null;  
  35.   
  36.     public static PermissionsManager getInstance() {  
  37.         if (mInstance == null) {  
  38.             mInstance = new PermissionsManager();  
  39.         }  
  40.         return mInstance;  
  41.     }  
  42.   
  43.     private PermissionsManager() {  
  44.         initializePermissionsMap();  
  45.     }  
  46.   
  47.     /** 
  48.      * This method uses reflection to read all the permissions in the Manifest class. 
  49.      * This is necessary because some permissions do not exist on older versions of Android, 
  50.      * since they do not exist, they will be denied when you check whether you have permission 
  51.      * which is problematic since a new permission is often added where there was no previous 
  52.      * permission required. We initialize a Set of available permissions and check the set 
  53.      * when checking if we have permission since we want to know when we are denied a permission 
  54.      * because it doesn’t exist yet. 
  55.      */  
  56.     private synchronized void initializePermissionsMap() {  
  57.         Field[] fields = Manifest.permission.class.getFields();  
  58.         for (Field field : fields) {  
  59.             String name = null;  
  60.             try {  
  61.                 name = (String) field.get(”“);  
  62.             } catch (IllegalAccessException e) {  
  63.                 Log.e(TAG, ”Could not access field”, e);  
  64.             }  
  65.             mPermissions.add(name);  
  66.         }  
  67.     }  
  68.   
  69.     /** 
  70.      * This method retrieves all the permissions declared in the application’s manifest. 
  71.      * It returns a non null array of permisions that can be declared. 
  72.      * 
  73.      * @param activity the Activity necessary to check what permissions we have. 
  74.      * @return a non null array of permissions that are declared in the application manifest. 
  75.      */  
  76.     @NonNull  
  77.     private synchronized String[] getManifestPermissions(@NonNull final Activity activity) {  
  78.         PackageInfo packageInfo = null;  
  79.         List<String> list = new ArrayList<>(1);  
  80.         try {  
  81.             Log.d(TAG, activity.getPackageName());  
  82.             packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);  
  83.         } catch (PackageManager.NameNotFoundException e) {  
  84.             Log.e(TAG, ”A problem occurred when retrieving permissions”, e);  
  85.         }  
  86.         if (packageInfo != null) {  
  87.             String[] permissions = packageInfo.requestedPermissions;  
  88.             if (permissions != null) {  
  89.                 for (String perm : permissions) {  
  90.                     Log.d(TAG, ”Manifest contained permission: ” + perm);  
  91.                     list.add(perm);  
  92.                 }  
  93.             }  
  94.         }  
  95.         return list.toArray(new String[list.size()]);  
  96.     }  
  97.   
  98.     /** 
  99.      * This method adds the {@link PermissionsResultAction} to the current list 
  100.      * of pending actions that will be completed when the permissions are 
  101.      * received. The list of permissions passed to this method are registered 
  102.      * in the PermissionsResultAction object so that it will be notified of changes 
  103.      * made to these permissions. 
  104.      * 
  105.      * @param permissions the required permissions for the action to be executed. 
  106.      * @param action      the action to add to the current list of pending actions. 
  107.      */  
  108.     private synchronized void addPendingAction(@NonNull String[] permissions,  
  109.                                                @Nullable PermissionsResultAction action) {  
  110.         if (action == null) {  
  111.             return;  
  112.         }  
  113.         action.registerPermissions(permissions);  
  114.         mPendingActions.add(new WeakReference<>(action));  
  115.     }  
  116.   
  117.     /** 
  118.      * This method removes a pending action from the list of pending actions. 
  119.      * It is used for cases where the permission has already been granted, so 
  120.      * you immediately wish to remove the pending action from the queue and 
  121.      * execute the action. 
  122.      * 
  123.      * @param action the action to remove 
  124.      */  
  125.     private synchronized void removePendingAction(@Nullable PermissionsResultAction action) {  
  126.         for (Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();  
  127.              iterator.hasNext(); ) {  
  128.             WeakReference<PermissionsResultAction> weakRef = iterator.next();  
  129.             if (weakRef.get() == action || weakRef.get() == null) {  
  130.                 iterator.remove();  
  131.             }  
  132.         }  
  133.     }  
  134.   
  135.     /** 
  136.      * This static method can be used to check whether or not you have a specific permission. 
  137.      * It is basically a less verbose method of using {@link ActivityCompat#checkSelfPermission(Context, String)} 
  138.      * and will simply return a boolean whether or not you have the permission. If you pass 
  139.      * in a null Context object, it will return false as otherwise it cannot check the permission. 
  140.      * However, the Activity parameter is nullable so that you can pass in a reference that you 
  141.      * are not always sure will be valid or not (e.g. getActivity() from Fragment). 
  142.      * 
  143.      * @param context    the Context necessary to check the permission 
  144.      * @param permission the permission to check 
  145.      * @return true if you have been granted the permission, false otherwise 
  146.      */  
  147.     @SuppressWarnings(“unused”)  
  148.     public synchronized boolean hasPermission(@Nullable Context context, @NonNull String permission) {  
  149.         return context != null && (ActivityCompat.checkSelfPermission(context, permission)  
  150.                 == PackageManager.PERMISSION_GRANTED || !mPermissions.contains(permission));  
  151.     }  
  152.   
  153.     /** 
  154.      * This static method can be used to check whether or not you have several specific permissions. 
  155.      * It is simpler than checking using {@link ActivityCompat#checkSelfPermission(Context, String)} 
  156.      * for each permission and will simply return a boolean whether or not you have all the permissions. 
  157.      * If you pass in a null Context object, it will return false as otherwise it cannot check the 
  158.      * permission. However, the Activity parameter is nullable so that you can pass in a reference 
  159.      * that you are not always sure will be valid or not (e.g. getActivity() from Fragment). 
  160.      * 
  161.      * @param context     the Context necessary to check the permission 
  162.      * @param permissions the permissions to check 
  163.      * @return true if you have been granted all the permissions, false otherwise 
  164.      */  
  165.     @SuppressWarnings(“unused”)  
  166.     public synchronized boolean hasAllPermissions(@Nullable Context context, @NonNull String[] permissions) {  
  167.         if (context == null) {  
  168.             return false;  
  169.         }  
  170.         boolean hasAllPermissions = true;  
  171.         for (String perm : permissions) {  
  172.             hasAllPermissions &= hasPermission(context, perm);  
  173.         }  
  174.         return hasAllPermissions;  
  175.     }  
  176.   
  177.     /** 
  178.      * This method will request all the permissions declared in your application manifest 
  179.      * for the specified {@link PermissionsResultAction}. The purpose of this method is to enable 
  180.      * all permissions to be requested at one shot. The PermissionsResultAction is used to notify 
  181.      * you of the user allowing or denying each permission. The Activity and PermissionsResultAction 
  182.      * parameters are both annotated Nullable, but this method will not work if the Activity 
  183.      * is null. It is only annotated Nullable as a courtesy to prevent crashes in the case 
  184.      * that you call this from a Fragment where {@link Fragment#getActivity()} could yield 
  185.      * null. Additionally, you will not receive any notification of permissions being granted 
  186.      * if you provide a null PermissionsResultAction. 
  187.      * 
  188.      * @param activity the Activity necessary to request and check permissions. 
  189.      * @param action   the PermissionsResultAction used to notify you of permissions being accepted. 
  190.      */  
  191.     @SuppressWarnings(“unused”)  
  192.     public synchronized void requestAllManifestPermissionsIfNecessary(final @Nullable Activity activity,  
  193.                                                                       final @Nullable PermissionsResultAction action) {  
  194.         if (activity == null) {  
  195.             return;  
  196.         }  
  197.         String[] perms = getManifestPermissions(activity);  
  198.         requestPermissionsIfNecessaryForResult(activity, perms, action);  
  199.     }  
  200.   
  201.     /** 
  202.      * This method should be used to execute a {@link PermissionsResultAction} for the array 
  203.      * of permissions passed to this method. This method will request the permissions if 
  204.      * they need to be requested (i.e. we don’t have permission yet) and will add the 
  205.      * PermissionsResultAction to the queue to be notified of permissions being granted or 
  206.      * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately. 
  207.      * The Activity variable is nullable, but if it is null, the method will fail to execute. 
  208.      * This is only nullable as a courtesy for Fragments where getActivity() may yeild null 
  209.      * if the Fragment is not currently added to its parent Activity. 
  210.      * 
  211.      * @param activity    the activity necessary to request the permissions. 
  212.      * @param permissions the list of permissions to request for the {@link PermissionsResultAction}. 
  213.      * @param action      the PermissionsResultAction to notify when the permissions are granted or denied. 
  214.      */  
  215.     @SuppressWarnings(“unused”)  
  216.     public synchronized void requestPermissionsIfNecessaryForResult(@Nullable Activity activity,  
  217.                                                                     @NonNull String[] permissions,  
  218.                                                                     @Nullable PermissionsResultAction action) {  
  219.         if (activity == null) {  
  220.             return;  
  221.         }  
  222.         addPendingAction(permissions, action);  
  223.         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {  
  224.             doPermissionWorkBeforeAndroidM(activity, permissions, action);  
  225.         } else {  
  226.             List<String> permList = getPermissionsListToRequest(activity, permissions, action);  
  227.             if (permList.isEmpty()) {  
  228.                 //if there is no permission to request, there is no reason to keep the action int the list  
  229.                 removePendingAction(action);  
  230.             } else {  
  231.                 String[] permsToRequest = permList.toArray(new String[permList.size()]);  
  232.                 mPendingRequests.addAll(permList);  
  233.                 ActivityCompat.requestPermissions(activity, permsToRequest, 1);  
  234.             }  
  235.         }  
  236.     }  
  237.   
  238.     /** 
  239.      * This method should be used to execute a {@link PermissionsResultAction} for the array 
  240.      * of permissions passed to this method. This method will request the permissions if 
  241.      * they need to be requested (i.e. we don’t have permission yet) and will add the 
  242.      * PermissionsResultAction to the queue to be notified of permissions being granted or 
  243.      * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately. 
  244.      * The Fragment variable is used, but if {@link Fragment#getActivity()} returns null, this method 
  245.      * will fail to work as the activity reference is necessary to check for permissions. 
  246.      * 
  247.      * @param fragment    the fragment necessary to request the permissions. 
  248.      * @param permissions the list of permissions to request for the {@link PermissionsResultAction}. 
  249.      * @param action      the PermissionsResultAction to notify when the permissions are granted or denied. 
  250.      */  
  251.     @SuppressWarnings(“unused”)  
  252.     public synchronized void requestPermissionsIfNecessaryForResult(@NonNull Fragment fragment,  
  253.                                                                     @NonNull String[] permissions,  
  254.                                                                     @Nullable PermissionsResultAction action) {  
  255.         Activity activity = fragment.getActivity();  
  256.         if (activity == null) {  
  257.             return;  
  258.         }  
  259.         addPendingAction(permissions, action);  
  260.         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {  
  261.             doPermissionWorkBeforeAndroidM(activity, permissions, action);  
  262.         } else {  
  263.             List<String> permList = getPermissionsListToRequest(activity, permissions, action);  
  264.             if (permList.isEmpty()) {  
  265.                 //if there is no permission to request, there is no reason to keep the action int the list  
  266.                 removePendingAction(action);  
  267.             } else {  
  268.                 String[] permsToRequest = permList.toArray(new String[permList.size()]);  
  269.                 mPendingRequests.addAll(permList);  
  270.                 fragment.requestPermissions(permsToRequest, 1);  
  271.             }  
  272.         }  
  273.     }  
  274.   
  275.     /** 
  276.      * This method notifies the PermissionsManager that the permissions have change. If you are making 
  277.      * the permissions requests using an Activity, then this method should be called from the 
  278.      * Activity callback onRequestPermissionsResult() with the variables passed to that method. If 
  279.      * you are passing a Fragment to make the permissions request, then you should call this in 
  280.      * the {@link Fragment#onRequestPermissionsResult(int, String[], int[])} method. 
  281.      * It will notify all the pending PermissionsResultAction objects currently 
  282.      * in the queue, and will remove the permissions request from the list of pending requests. 
  283.      * 
  284.      * @param permissions the permissions that have changed. 
  285.      * @param results     the values for each permission. 
  286.      */  
  287.     @SuppressWarnings(“unused”)  
  288.     public synchronized void notifyPermissionsChange(@NonNull String[] permissions, @NonNull int[] results) {  
  289.         int size = permissions.length;  
  290.         if (results.length < size) {  
  291.             size = results.length;  
  292.         }  
  293.         Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();  
  294.         while (iterator.hasNext()) {  
  295.             PermissionsResultAction action = iterator.next().get();  
  296.             for (int n = 0; n < size; n++) {  
  297.                 if (action == null || action.onResult(permissions[n], results[n])) {  
  298.                     iterator.remove();  
  299.                     break;  
  300.                 }  
  301.             }  
  302.         }  
  303.         for (int n = 0; n < size; n++) {  
  304.             mPendingRequests.remove(permissions[n]);  
  305.         }  
  306.     }  
  307.   
  308.     /** 
  309.      * When request permissions on devices before Android M (Android 6.0, API Level 23) 
  310.      * Do the granted or denied work directly according to the permission status 
  311.      * 
  312.      * @param activity    the activity to check permissions 
  313.      * @param permissions the permissions names 
  314.      * @param action      the callback work object, containing what we what to do after 
  315.      *                    permission check 
  316.      */  
  317.     private void doPermissionWorkBeforeAndroidM(@NonNull Activity activity,  
  318.                                                 @NonNull String[] permissions,  
  319.                                                 @Nullable PermissionsResultAction action) {  
  320.         for (String perm : permissions) {  
  321.             if (action != null) {  
  322.                 if (!mPermissions.contains(perm)) {  
  323.                     action.onResult(perm, Permissions.NOT_FOUND);  
  324.                 } else if (ActivityCompat.checkSelfPermission(activity, perm)  
  325.                         != PackageManager.PERMISSION_GRANTED) {  
  326.                     action.onResult(perm, Permissions.DENIED);  
  327.                 } else {  
  328.                     action.onResult(perm, Permissions.GRANTED);  
  329.                 }  
  330.             }  
  331.         }  
  332.     }  
  333.   
  334.     /** 
  335.      * Filter the permissions list: 
  336.      * If a permission is not granted, add it to the result list 
  337.      * if a permission is granted, do the granted work, do not add it to the result list 
  338.      * 
  339.      * @param activity    the activity to check permissions 
  340.      * @param permissions all the permissions names 
  341.      * @param action      the callback work object, containing what we what to do after 
  342.      *                    permission check 
  343.      * @return a list of permissions names that are not granted yet 
  344.      */  
  345.     @NonNull  
  346.     private List<String> getPermissionsListToRequest(@NonNull Activity activity,  
  347.                                                      @NonNull String[] permissions,  
  348.                                                      @Nullable PermissionsResultAction action) {  
  349.         List<String> permList = new ArrayList<>(permissions.length);  
  350.         for (String perm : permissions) {  
  351.             if (!mPermissions.contains(perm)) {  
  352.                 if (action != null) {  
  353.                     action.onResult(perm, Permissions.NOT_FOUND);  
  354.                 }  
  355.             } else if (ActivityCompat.checkSelfPermission(activity, perm) != PackageManager.PERMISSION_GRANTED) {  
  356.                 if (!mPendingRequests.contains(perm)) {  
  357.                     permList.add(perm);  
  358.                 }  
  359.             } else {  
  360.                 if (action != null) {  
  361.                     action.onResult(perm, Permissions.GRANTED);  
  362.                 }  
  363.             }  
  364.         }  
  365.         return permList;  
  366.     }  
  367.   
  368. }  
package com.anthonycr.grant;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.util.Log;

import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * A class to help you manage your permissions simply.
 */
public class PermissionsManager {

    private static final String TAG = PermissionsManager.class.getSimpleName();

    private final Set<String> mPendingRequests = new HashSet<>(1);
    private final Set<String> mPermissions = new HashSet<>(1);
    private final List<WeakReference<PermissionsResultAction>> mPendingActions = new ArrayList<>(1);

    private static PermissionsManager mInstance = null;

    public static PermissionsManager getInstance() {
        if (mInstance == null) {
            mInstance = new PermissionsManager();
        }
        return mInstance;
    }

    private PermissionsManager() {
        initializePermissionsMap();
    }

    /**
     * This method uses reflection to read all the permissions in the Manifest class.
     * This is necessary because some permissions do not exist on older versions of Android,
     * since they do not exist, they will be denied when you check whether you have permission
     * which is problematic since a new permission is often added where there was no previous
     * permission required. We initialize a Set of available permissions and check the set
     * when checking if we have permission since we want to know when we are denied a permission
     * because it doesn't exist yet.
     */
    private synchronized void initializePermissionsMap() {
        Field[] fields = Manifest.permission.class.getFields();
        for (Field field : fields) {
            String name = null;
            try {
                name = (String) field.get("");
            } catch (IllegalAccessException e) {
                Log.e(TAG, "Could not access field", e);
            }
            mPermissions.add(name);
        }
    }

    /**
     * This method retrieves all the permissions declared in the application's manifest.
     * It returns a non null array of permisions that can be declared.
     *
     * @param activity the Activity necessary to check what permissions we have.
     * @return a non null array of permissions that are declared in the application manifest.
     */
    @NonNull
    private synchronized String[] getManifestPermissions(@NonNull final Activity activity) {
        PackageInfo packageInfo = null;
        List<String> list = new ArrayList<>(1);
        try {
            Log.d(TAG, activity.getPackageName());
            packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "A problem occurred when retrieving permissions", e);
        }
        if (packageInfo != null) {
            String[] permissions = packageInfo.requestedPermissions;
            if (permissions != null) {
                for (String perm : permissions) {
                    Log.d(TAG, "Manifest contained permission: " + perm);
                    list.add(perm);
                }
            }
        }
        return list.toArray(new String[list.size()]);
    }

    /**
     * This method adds the {@link PermissionsResultAction} to the current list
     * of pending actions that will be completed when the permissions are
     * received. The list of permissions passed to this method are registered
     * in the PermissionsResultAction object so that it will be notified of changes
     * made to these permissions.
     *
     * @param permissions the required permissions for the action to be executed.
     * @param action      the action to add to the current list of pending actions.
     */
    private synchronized void addPendingAction(@NonNull String[] permissions,
                                               @Nullable PermissionsResultAction action) {
        if (action == null) {
            return;
        }
        action.registerPermissions(permissions);
        mPendingActions.add(new WeakReference<>(action));
    }

    /**
     * This method removes a pending action from the list of pending actions.
     * It is used for cases where the permission has already been granted, so
     * you immediately wish to remove the pending action from the queue and
     * execute the action.
     *
     * @param action the action to remove
     */
    private synchronized void removePendingAction(@Nullable PermissionsResultAction action) {
        for (Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();
             iterator.hasNext(); ) {
            WeakReference<PermissionsResultAction> weakRef = iterator.next();
            if (weakRef.get() == action || weakRef.get() == null) {
                iterator.remove();
            }
        }
    }

    /**
     * This static method can be used to check whether or not you have a specific permission.
     * It is basically a less verbose method of using {@link ActivityCompat#checkSelfPermission(Context, String)}
     * and will simply return a boolean whether or not you have the permission. If you pass
     * in a null Context object, it will return false as otherwise it cannot check the permission.
     * However, the Activity parameter is nullable so that you can pass in a reference that you
     * are not always sure will be valid or not (e.g. getActivity() from Fragment).
     *
     * @param context    the Context necessary to check the permission
     * @param permission the permission to check
     * @return true if you have been granted the permission, false otherwise
     */
    @SuppressWarnings("unused")
    public synchronized boolean hasPermission(@Nullable Context context, @NonNull String permission) {
        return context != null && (ActivityCompat.checkSelfPermission(context, permission)
                == PackageManager.PERMISSION_GRANTED || !mPermissions.contains(permission));
    }

    /**
     * This static method can be used to check whether or not you have several specific permissions.
     * It is simpler than checking using {@link ActivityCompat#checkSelfPermission(Context, String)}
     * for each permission and will simply return a boolean whether or not you have all the permissions.
     * If you pass in a null Context object, it will return false as otherwise it cannot check the
     * permission. However, the Activity parameter is nullable so that you can pass in a reference
     * that you are not always sure will be valid or not (e.g. getActivity() from Fragment).
     *
     * @param context     the Context necessary to check the permission
     * @param permissions the permissions to check
     * @return true if you have been granted all the permissions, false otherwise
     */
    @SuppressWarnings("unused")
    public synchronized boolean hasAllPermissions(@Nullable Context context, @NonNull String[] permissions) {
        if (context == null) {
            return false;
        }
        boolean hasAllPermissions = true;
        for (String perm : permissions) {
            hasAllPermissions &= hasPermission(context, perm);
        }
        return hasAllPermissions;
    }

    /**
     * This method will request all the permissions declared in your application manifest
     * for the specified {@link PermissionsResultAction}. The purpose of this method is to enable
     * all permissions to be requested at one shot. The PermissionsResultAction is used to notify
     * you of the user allowing or denying each permission. The Activity and PermissionsResultAction
     * parameters are both annotated Nullable, but this method will not work if the Activity
     * is null. It is only annotated Nullable as a courtesy to prevent crashes in the case
     * that you call this from a Fragment where {@link Fragment#getActivity()} could yield
     * null. Additionally, you will not receive any notification of permissions being granted
     * if you provide a null PermissionsResultAction.
     *
     * @param activity the Activity necessary to request and check permissions.
     * @param action   the PermissionsResultAction used to notify you of permissions being accepted.
     */
    @SuppressWarnings("unused")
    public synchronized void requestAllManifestPermissionsIfNecessary(final @Nullable Activity activity,
                                                                      final @Nullable PermissionsResultAction action) {
        if (activity == null) {
            return;
        }
        String[] perms = getManifestPermissions(activity);
        requestPermissionsIfNecessaryForResult(activity, perms, action);
    }

    /**
     * This method should be used to execute a {@link PermissionsResultAction} for the array
     * of permissions passed to this method. This method will request the permissions if
     * they need to be requested (i.e. we don't have permission yet) and will add the
     * PermissionsResultAction to the queue to be notified of permissions being granted or
     * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
     * The Activity variable is nullable, but if it is null, the method will fail to execute.
     * This is only nullable as a courtesy for Fragments where getActivity() may yeild null
     * if the Fragment is not currently added to its parent Activity.
     *
     * @param activity    the activity necessary to request the permissions.
     * @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
     * @param action      the PermissionsResultAction to notify when the permissions are granted or denied.
     */
    @SuppressWarnings("unused")
    public synchronized void requestPermissionsIfNecessaryForResult(@Nullable Activity activity,
                                                                    @NonNull String[] permissions,
                                                                    @Nullable PermissionsResultAction action) {
        if (activity == null) {
            return;
        }
        addPendingAction(permissions, action);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            doPermissionWorkBeforeAndroidM(activity, permissions, action);
        } else {
            List<String> permList = getPermissionsListToRequest(activity, permissions, action);
            if (permList.isEmpty()) {
                //if there is no permission to request, there is no reason to keep the action int the list
                removePendingAction(action);
            } else {
                String[] permsToRequest = permList.toArray(new String[permList.size()]);
                mPendingRequests.addAll(permList);
                ActivityCompat.requestPermissions(activity, permsToRequest, 1);
            }
        }
    }

    /**
     * This method should be used to execute a {@link PermissionsResultAction} for the array
     * of permissions passed to this method. This method will request the permissions if
     * they need to be requested (i.e. we don't have permission yet) and will add the
     * PermissionsResultAction to the queue to be notified of permissions being granted or
     * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
     * The Fragment variable is used, but if {@link Fragment#getActivity()} returns null, this method
     * will fail to work as the activity reference is necessary to check for permissions.
     *
     * @param fragment    the fragment necessary to request the permissions.
     * @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
     * @param action      the PermissionsResultAction to notify when the permissions are granted or denied.
     */
    @SuppressWarnings("unused")
    public synchronized void requestPermissionsIfNecessaryForResult(@NonNull Fragment fragment,
                                                                    @NonNull String[] permissions,
                                                                    @Nullable PermissionsResultAction action) {
        Activity activity = fragment.getActivity();
        if (activity == null) {
            return;
        }
        addPendingAction(permissions, action);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            doPermissionWorkBeforeAndroidM(activity, permissions, action);
        } else {
            List<String> permList = getPermissionsListToRequest(activity, permissions, action);
            if (permList.isEmpty()) {
                //if there is no permission to request, there is no reason to keep the action int the list
                removePendingAction(action);
            } else {
                String[] permsToRequest = permList.toArray(new String[permList.size()]);
                mPendingRequests.addAll(permList);
                fragment.requestPermissions(permsToRequest, 1);
            }
        }
    }

    /**
     * This method notifies the PermissionsManager that the permissions have change. If you are making
     * the permissions requests using an Activity, then this method should be called from the
     * Activity callback onRequestPermissionsResult() with the variables passed to that method. If
     * you are passing a Fragment to make the permissions request, then you should call this in
     * the {@link Fragment#onRequestPermissionsResult(int, String[], int[])} method.
     * It will notify all the pending PermissionsResultAction objects currently
     * in the queue, and will remove the permissions request from the list of pending requests.
     *
     * @param permissions the permissions that have changed.
     * @param results     the values for each permission.
     */
    @SuppressWarnings("unused")
    public synchronized void notifyPermissionsChange(@NonNull String[] permissions, @NonNull int[] results) {
        int size = permissions.length;
        if (results.length < size) {
            size = results.length;
        }
        Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();
        while (iterator.hasNext()) {
            PermissionsResultAction action = iterator.next().get();
            for (int n = 0; n < size; n++) {
                if (action == null || action.onResult(permissions[n], results[n])) {
                    iterator.remove();
                    break;
                }
            }
        }
        for (int n = 0; n < size; n++) {
            mPendingRequests.remove(permissions[n]);
        }
    }

    /**
     * When request permissions on devices before Android M (Android 6.0, API Level 23)
     * Do the granted or denied work directly according to the permission status
     *
     * @param activity    the activity to check permissions
     * @param permissions the permissions names
     * @param action      the callback work object, containing what we what to do after
     *                    permission check
     */
    private void doPermissionWorkBeforeAndroidM(@NonNull Activity activity,
                                                @NonNull String[] permissions,
                                                @Nullable PermissionsResultAction action) {
        for (String perm : permissions) {
            if (action != null) {
                if (!mPermissions.contains(perm)) {
                    action.onResult(perm, Permissions.NOT_FOUND);
                } else if (ActivityCompat.checkSelfPermission(activity, perm)
                        != PackageManager.PERMISSION_GRANTED) {
                    action.onResult(perm, Permissions.DENIED);
                } else {
                    action.onResult(perm, Permissions.GRANTED);
                }
            }
        }
    }

    /**
     * Filter the permissions list:
     * If a permission is not granted, add it to the result list
     * if a permission is granted, do the granted work, do not add it to the result list
     *
     * @param activity    the activity to check permissions
     * @param permissions all the permissions names
     * @param action      the callback work object, containing what we what to do after
     *                    permission check
     * @return a list of permissions names that are not granted yet
     */
    @NonNull
    private List<String> getPermissionsListToRequest(@NonNull Activity activity,
                                                     @NonNull String[] permissions,
                                                     @Nullable PermissionsResultAction action) {
        List<String> permList = new ArrayList<>(permissions.length);
        for (String perm : permissions) {
            if (!mPermissions.contains(perm)) {
                if (action != null) {
                    action.onResult(perm, Permissions.NOT_FOUND);
                }
            } else if (ActivityCompat.checkSelfPermission(activity, perm) != PackageManager.PERMISSION_GRANTED) {
                if (!mPendingRequests.contains(perm)) {
                    permList.add(perm);
                }
            } else {
                if (action != null) {
                    action.onResult(perm, Permissions.GRANTED);
                }
            }
        }
        return permList;
    }

}
这个类主要是获取单例下的权限管理类,然后通过内部方法进行权限管理
(3) PermissionsResultAction

  1. package com.anthonycr.grant;  
  2.   
  3. import android.content.pm.PackageManager;  
  4. import android.os.Handler;  
  5. import android.os.Looper;  
  6. import android.support.annotation.CallSuper;  
  7. import android.support.annotation.NonNull;  
  8. import android.util.Log;  
  9.   
  10. import java.util.Collections;  
  11. import java.util.HashSet;  
  12. import java.util.Set;  
  13.   
  14. /** 
  15.  * This abstract class should be used to create an if/else action that the PermissionsManager 
  16.  * can execute when the permissions you request are granted or denied. Simple use involves 
  17.  * creating an anonymous instance of it and passing that instance to the 
  18.  * requestPermissionsIfNecessaryForResult method. The result will be sent back to you as 
  19.  * either onGranted (all permissions have been granted), or onDenied (a required permission 
  20.  * has been denied). Ideally you put your functionality in the onGranted method and notify 
  21.  * the user what won’t work in the onDenied method. 
  22.  */  
  23. public abstract class PermissionsResultAction {  
  24.   
  25.     private static final String TAG = PermissionsResultAction.class.getSimpleName();  
  26.     private final Set<String> mPermissions = new HashSet<>(1);  
  27.     private Looper mLooper = Looper.getMainLooper();  
  28.   
  29.     /** 
  30.      * Default Constructor 
  31.      */  
  32.     public PermissionsResultAction() {}  
  33.   
  34.     /** 
  35.      * Alternate Constructor. Pass the looper you wish the PermissionsResultAction 
  36.      * callbacks to be executed on if it is not the current Looper. For instance, 
  37.      * if you are making a permissions request from a background thread but wish the 
  38.      * callback to be on the UI thread, use this constructor to specify the UI Looper. 
  39.      * 
  40.      * @param looper the looper that the callbacks will be called using. 
  41.      */  
  42.     @SuppressWarnings(“unused”)  
  43.     public PermissionsResultAction(@NonNull Looper looper) {mLooper = looper;}  
  44.   
  45.     /** 
  46.      * This method is called when ALL permissions that have been 
  47.      * requested have been granted by the user. In this method 
  48.      * you should put all your permissions sensitive code that can 
  49.      * only be executed with the required permissions. 
  50.      */  
  51.     public abstract void onGranted();  
  52.   
  53.     /** 
  54.      * This method is called when a permission has been denied by 
  55.      * the user. It provides you with the permission that was denied 
  56.      * and will be executed on the Looper you pass to the constructor 
  57.      * of this class, or the Looper that this object was created on. 
  58.      * 
  59.      * @param permission the permission that was denied. 
  60.      */  
  61.     public abstract void onDenied(String permission);  
  62.   
  63.     /** 
  64.      * This method is used to determine if a permission not 
  65.      * being present on the current Android platform should 
  66.      * affect whether the PermissionsResultAction should continue 
  67.      * listening for events. By default, it returns true and will 
  68.      * simply ignore the permission that did not exist. Usually this will 
  69.      * work fine since most new permissions are introduced to 
  70.      * restrict what was previously allowed without permission. 
  71.      * If that is not the case for your particular permission you 
  72.      * request, override this method and return false to result in the 
  73.      * Action being denied. 
  74.      * 
  75.      * @param permission the permission that doesn’t exist on this 
  76.      *                   Android version 
  77.      * @return return true if the PermissionsResultAction should 
  78.      * ignore the lack of the permission and proceed with exection 
  79.      * or false if the PermissionsResultAction should treat the 
  80.      * absence of the permission on the API level as a denial. 
  81.      */  
  82.     @SuppressWarnings({“WeakerAccess”“SameReturnValue”})  
  83.     public synchronized boolean shouldIgnorePermissionNotFound(String permission) {  
  84.         Log.d(TAG, ”Permission not found: ” + permission);  
  85.         return true;  
  86.     }  
  87.   
  88.     @SuppressWarnings(“WeakerAccess”)  
  89.     @CallSuper  
  90.     protected synchronized final boolean onResult(final @NonNull String permission, int result) {  
  91.         if (result == PackageManager.PERMISSION_GRANTED) {  
  92.             return onResult(permission, Permissions.GRANTED);  
  93.         } else {  
  94.             return onResult(permission, Permissions.DENIED);  
  95.         }  
  96.   
  97.     }  
  98.   
  99.     /** 
  100.      * This method is called when a particular permission has changed. 
  101.      * This method will be called for all permissions, so this method determines 
  102.      * if the permission affects the state or not and whether it can proceed with 
  103.      * calling onGranted or if onDenied should be called. 
  104.      * 
  105.      * @param permission the permission that changed. 
  106.      * @param result     the result for that permission. 
  107.      * @return this method returns true if its primary action has been completed 
  108.      * and it should be removed from the data structure holding a reference to it. 
  109.      */  
  110.     @SuppressWarnings(“WeakerAccess”)  
  111.     @CallSuper  
  112.     protected synchronized final boolean onResult(final @NonNull String permission, Permissions result) {  
  113.         mPermissions.remove(permission);  
  114.         if (result == Permissions.GRANTED) {  
  115.             if (mPermissions.isEmpty()) {  
  116.                 new Handler(mLooper).post(new Runnable() {  
  117.                     @Override  
  118.                     public void run() {  
  119.                         onGranted();  
  120.                     }  
  121.                 });  
  122.                 return true;  
  123.             }  
  124.         } else if (result == Permissions.DENIED) {  
  125.             new Handler(mLooper).post(new Runnable() {  
  126.                 @Override  
  127.                 public void run() {  
  128.                     onDenied(permission);  
  129.                 }  
  130.             });  
  131.             return true;  
  132.         } else if (result == Permissions.NOT_FOUND) {  
  133.             if (shouldIgnorePermissionNotFound(permission)) {  
  134.                 if (mPermissions.isEmpty()) {  
  135.                     new Handler(mLooper).post(new Runnable() {  
  136.                         @Override  
  137.                         public void run() {  
  138.                             onGranted();  
  139.                         }  
  140.                     });  
  141.                     return true;  
  142.                 }  
  143.             } else {  
  144.                 new Handler(mLooper).post(new Runnable() {  
  145.                     @Override  
  146.                     public void run() {  
  147.                         onDenied(permission);  
  148.                     }  
  149.                 });  
  150.                 return true;  
  151.             }  
  152.         }  
  153.         return false;  
  154.     }  
  155.   
  156.     /** 
  157.      * This method registers the PermissionsResultAction object for the specified permissions 
  158.      * so that it will know which permissions to look for changes to. The PermissionsResultAction 
  159.      * will then know to look out for changes to these permissions. 
  160.      * 
  161.      * @param perms the permissions to listen for 
  162.      */  
  163.     @SuppressWarnings(“WeakerAccess”)  
  164.     @CallSuper  
  165.     protected synchronized final void registerPermissions(@NonNull String[] perms) {  
  166.         Collections.addAll(mPermissions, perms);  
  167.     }  
  168. }  
package com.anthonycr.grant;

import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.util.Log;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * This abstract class should be used to create an if/else action that the PermissionsManager
 * can execute when the permissions you request are granted or denied. Simple use involves
 * creating an anonymous instance of it and passing that instance to the
 * requestPermissionsIfNecessaryForResult method. The result will be sent back to you as
 * either onGranted (all permissions have been granted), or onDenied (a required permission
 * has been denied). Ideally you put your functionality in the onGranted method and notify
 * the user what won't work in the onDenied method.
 */
public abstract class PermissionsResultAction {

    private static final String TAG = PermissionsResultAction.class.getSimpleName();
    private final Set<String> mPermissions = new HashSet<>(1);
    private Looper mLooper = Looper.getMainLooper();

    /**
     * Default Constructor
     */
    public PermissionsResultAction() {}

    /**
     * Alternate Constructor. Pass the looper you wish the PermissionsResultAction
     * callbacks to be executed on if it is not the current Looper. For instance,
     * if you are making a permissions request from a background thread but wish the
     * callback to be on the UI thread, use this constructor to specify the UI Looper.
     *
     * @param looper the looper that the callbacks will be called using.
     */
    @SuppressWarnings("unused")
    public PermissionsResultAction(@NonNull Looper looper) {mLooper = looper;}

    /**
     * This method is called when ALL permissions that have been
     * requested have been granted by the user. In this method
     * you should put all your permissions sensitive code that can
     * only be executed with the required permissions.
     */
    public abstract void onGranted();

    /**
     * This method is called when a permission has been denied by
     * the user. It provides you with the permission that was denied
     * and will be executed on the Looper you pass to the constructor
     * of this class, or the Looper that this object was created on.
     *
     * @param permission the permission that was denied.
     */
    public abstract void onDenied(String permission);

    /**
     * This method is used to determine if a permission not
     * being present on the current Android platform should
     * affect whether the PermissionsResultAction should continue
     * listening for events. By default, it returns true and will
     * simply ignore the permission that did not exist. Usually this will
     * work fine since most new permissions are introduced to
     * restrict what was previously allowed without permission.
     * If that is not the case for your particular permission you
     * request, override this method and return false to result in the
     * Action being denied.
     *
     * @param permission the permission that doesn't exist on this
     *                   Android version
     * @return return true if the PermissionsResultAction should
     * ignore the lack of the permission and proceed with exection
     * or false if the PermissionsResultAction should treat the
     * absence of the permission on the API level as a denial.
     */
    @SuppressWarnings({"WeakerAccess", "SameReturnValue"})
    public synchronized boolean shouldIgnorePermissionNotFound(String permission) {
        Log.d(TAG, "Permission not found: " + permission);
        return true;
    }

    @SuppressWarnings("WeakerAccess")
    @CallSuper
    protected synchronized final boolean onResult(final @NonNull String permission, int result) {
        if (result == PackageManager.PERMISSION_GRANTED) {
            return onResult(permission, Permissions.GRANTED);
        } else {
            return onResult(permission, Permissions.DENIED);
        }

    }

    /**
     * This method is called when a particular permission has changed.
     * This method will be called for all permissions, so this method determines
     * if the permission affects the state or not and whether it can proceed with
     * calling onGranted or if onDenied should be called.
     *
     * @param permission the permission that changed.
     * @param result     the result for that permission.
     * @return this method returns true if its primary action has been completed
     * and it should be removed from the data structure holding a reference to it.
     */
    @SuppressWarnings("WeakerAccess")
    @CallSuper
    protected synchronized final boolean onResult(final @NonNull String permission, Permissions result) {
        mPermissions.remove(permission);
        if (result == Permissions.GRANTED) {
            if (mPermissions.isEmpty()) {
                new Handler(mLooper).post(new Runnable() {
                    @Override
                    public void run() {
                        onGranted();
                    }
                });
                return true;
            }
        } else if (result == Permissions.DENIED) {
            new Handler(mLooper).post(new Runnable() {
                @Override
                public void run() {
                    onDenied(permission);
                }
            });
            return true;
        } else if (result == Permissions.NOT_FOUND) {
            if (shouldIgnorePermissionNotFound(permission)) {
                if (mPermissions.isEmpty()) {
                    new Handler(mLooper).post(new Runnable() {
                        @Override
                        public void run() {
                            onGranted();
                        }
                    });
                    return true;
                }
            } else {
                new Handler(mLooper).post(new Runnable() {
                    @Override
                    public void run() {
                        onDenied(permission);
                    }
                });
                return true;
            }
        }
        return false;
    }

    /**
     * This method registers the PermissionsResultAction object for the specified permissions
     * so that it will know which permissions to look for changes to. The PermissionsResultAction
     * will then know to look out for changes to these permissions.
     *
     * @param perms the permissions to listen for
     */
    @SuppressWarnings("WeakerAccess")
    @CallSuper
    protected synchronized final void registerPermissions(@NonNull String[] perms) {
        Collections.addAll(mPermissions, perms);
    }
}
这个类是用来做回调使用的,方便在调用过以后进行回调。


没有做翻译,如果看不懂,用翻译软件一点一点看把。

下面写一个例子,来进行示范:

  1. public class SplashActivity extends Activity {  
  2.   
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6. //        requestWindowFeature(Window.FEATURE_NO_TITLE); //设置无标题  
  7. //        getWindow().setFlags(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);  //设置全屏  
  8.         setContentView(R.layout.activity_splash);  
  9.         requestAllPermission();//请求获取全部权限  
  10.     }  
  11.   
  12.     /** 
  13.      * 请求获取全部权限,调用权限管理类,然后放进去需要申请的权限,通过接口回调的方法获得权限获取结果 
  14.      */  
  15.     private void requestAllPermission() {  
  16.         PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(SplashActivity.this, ConstantString.permissions, new PermissionsResultAction() {  
  17.             @Override  
  18.             public void onGranted() {  
  19.                 L.i(”onGranted”);  
  20.                 myHandler.sendEmptyMessage(GETPERMISSION_SUCCESS);  
  21.             }  
  22.   
  23.             @Override  
  24.             public void onDenied(String permission) {  
  25.                 L.i(”onDenied”);  
  26.                 myHandler.sendEmptyMessage(GETPERMISSION_FAILER);  
  27.             }  
  28.         });  
  29.     }  
  30.   
  31.   
  32.   
  33.     private static final int GETPERMISSION_SUCCESS = 1;//获取权限成功  
  34.     private static final int GETPERMISSION_FAILER = 2;//获取权限失败  
  35.     private MyHandler myHandler = new MyHandler();  
  36.   
  37.     private class MyHandler extends Handler {  
  38.         @Override  
  39.         public void handleMessage(Message msg) {  
  40.             super.handleMessage(msg);  
  41.             switch (msg.what) {  
  42.                 case GETPERMISSION_SUCCESS:  
  43. <span style=”white-space:pre”>        </span>    startActivity(new Intent(SplashActivity.this,MainActivity.class));  
  44.                     break;  
  45.                 case GETPERMISSION_FAILER:  
  46.                     T.showShort(SplashActivity.this“应用没有获取权限,请重新打开应用,或者到设置页面添加权限以后再从新打开。”);  
  47.                     break;  
  48.             }  
  49.         }  
  50.     }  
  51.   
  52.     //因为权限管理类无法监听系统,所以需要重写onRequestPermissionResult方法,更新权限管理类,并回调结果。这个是必须要有的。  
  53.     @Override  
  54.     public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {  
  55.         PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);  
  56.     }  
  57. }  
public class SplashActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        requestWindowFeature(Window.FEATURE_NO_TITLE); //设置无标题
//        getWindow().setFlags(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);  //设置全屏
        setContentView(R.layout.activity_splash);
        requestAllPermission();//请求获取全部权限
    }

    /**
     * 请求获取全部权限,调用权限管理类,然后放进去需要申请的权限,通过接口回调的方法获得权限获取结果
     */
    private void requestAllPermission() {
        PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(SplashActivity.this, ConstantString.permissions, new PermissionsResultAction() {
            @Override
            public void onGranted() {
                L.i("onGranted");
                myHandler.sendEmptyMessage(GETPERMISSION_SUCCESS);
            }

            @Override
            public void onDenied(String permission) {
                L.i("onDenied");
                myHandler.sendEmptyMessage(GETPERMISSION_FAILER);
            }
        });
    }



    private static final int GETPERMISSION_SUCCESS = 1;//获取权限成功
    private static final int GETPERMISSION_FAILER = 2;//获取权限失败
    private MyHandler myHandler = new MyHandler();

    private class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case GETPERMISSION_SUCCESS:
<span style="white-space:pre">        </span>    startActivity(new Intent(SplashActivity.this,MainActivity.class));
                    break;
                case GETPERMISSION_FAILER:
                    T.showShort(SplashActivity.this, "应用没有获取权限,请重新打开应用,或者到设置页面添加权限以后再从新打开。");
                    break;
            }
        }
    }

    //因为权限管理类无法监听系统,所以需要重写onRequestPermissionResult方法,更新权限管理类,并回调结果。这个是必须要有的。
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);
    }
}

看过上面的代码以后是不是觉得6.0的权限管理变的简单了,但是还有更见的一个方法 requestAllManifestPermissionIfNecessary() 这个方法会自动查询清单文件当中申请的权限,然后自动调取系统的权限获取方法,一次解决所有问题。

上述方式用来解决权限管理对于大家的代码结构会有很大的提升,同时减少大家的代码量,期望给大家更多的问题解决方案。



转自:https://blog.csdn.net/u011071427/article/details/52062947

本文在CSDN博客首发
转载请注明出处 
http://blog.csdn.net/u011071427/article/details/52062947
本文出自Allen李的博客


Android开发者应该都知道在Android6.0后添加了权限的动态管理,我以前也写过一片博客关于怎么处理权限的动态申请。传送门

今天主要介绍Github上的开源项目Grant是如何处理权限管理的。

先来一个Github的传送门:Grant

然后直接上代码

Grant里面一共有三个类,分别是:

(1)Permissions

  1. package com.anthonycr.grant;  
  2.   
  3. /** 
  4.  * Enum class to handle the different states 
  5.  * of permissions since the PackageManager only 
  6.  * has a granted and denied state. 
  7.  */  
  8. enum Permissions {  
  9.     GRANTED,  
  10.     DENIED,  
  11.     NOT_FOUND  
  12. }  
package com.anthonycr.grant;

/**
 * Enum class to handle the different states
 * of permissions since the PackageManager only
 * has a granted and denied state.
 */
enum Permissions {
    GRANTED,
    DENIED,
    NOT_FOUND
}

这是一个枚举类,用来对应三种状态:已授权,授权失败,未发现的权限


(2) PermissionsManager

  1. package com.anthonycr.grant;  
  2.   
  3. import android.Manifest;  
  4. import android.app.Activity;  
  5. import android.content.Context;  
  6. import android.content.pm.PackageInfo;  
  7. import android.content.pm.PackageManager;  
  8. import android.os.Build;  
  9. import android.support.annotation.NonNull;  
  10. import android.support.annotation.Nullable;  
  11. import android.support.v4.app.ActivityCompat;  
  12. import android.support.v4.app.Fragment;  
  13. import android.util.Log;  
  14.   
  15. import java.lang.ref.WeakReference;  
  16. import java.lang.reflect.Field;  
  17. import java.util.ArrayList;  
  18. import java.util.HashSet;  
  19. import java.util.Iterator;  
  20. import java.util.List;  
  21. import java.util.Set;  
  22.   
  23. /** 
  24.  * A class to help you manage your permissions simply. 
  25.  */  
  26. public class PermissionsManager {  
  27.   
  28.     private static final String TAG = PermissionsManager.class.getSimpleName();  
  29.   
  30.     private final Set<String> mPendingRequests = new HashSet<>(1);  
  31.     private final Set<String> mPermissions = new HashSet<>(1);  
  32.     private final List<WeakReference<PermissionsResultAction>> mPendingActions = new ArrayList<>(1);  
  33.   
  34.     private static PermissionsManager mInstance = null;  
  35.   
  36.     public static PermissionsManager getInstance() {  
  37.         if (mInstance == null) {  
  38.             mInstance = new PermissionsManager();  
  39.         }  
  40.         return mInstance;  
  41.     }  
  42.   
  43.     private PermissionsManager() {  
  44.         initializePermissionsMap();  
  45.     }  
  46.   
  47.     /** 
  48.      * This method uses reflection to read all the permissions in the Manifest class. 
  49.      * This is necessary because some permissions do not exist on older versions of Android, 
  50.      * since they do not exist, they will be denied when you check whether you have permission 
  51.      * which is problematic since a new permission is often added where there was no previous 
  52.      * permission required. We initialize a Set of available permissions and check the set 
  53.      * when checking if we have permission since we want to know when we are denied a permission 
  54.      * because it doesn’t exist yet. 
  55.      */  
  56.     private synchronized void initializePermissionsMap() {  
  57.         Field[] fields = Manifest.permission.class.getFields();  
  58.         for (Field field : fields) {  
  59.             String name = null;  
  60.             try {  
  61.                 name = (String) field.get(”“);  
  62.             } catch (IllegalAccessException e) {  
  63.                 Log.e(TAG, ”Could not access field”, e);  
  64.             }  
  65.             mPermissions.add(name);  
  66.         }  
  67.     }  
  68.   
  69.     /** 
  70.      * This method retrieves all the permissions declared in the application’s manifest. 
  71.      * It returns a non null array of permisions that can be declared. 
  72.      * 
  73.      * @param activity the Activity necessary to check what permissions we have. 
  74.      * @return a non null array of permissions that are declared in the application manifest. 
  75.      */  
  76.     @NonNull  
  77.     private synchronized String[] getManifestPermissions(@NonNull final Activity activity) {  
  78.         PackageInfo packageInfo = null;  
  79.         List<String> list = new ArrayList<>(1);  
  80.         try {  
  81.             Log.d(TAG, activity.getPackageName());  
  82.             packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);  
  83.         } catch (PackageManager.NameNotFoundException e) {  
  84.             Log.e(TAG, ”A problem occurred when retrieving permissions”, e);  
  85.         }  
  86.         if (packageInfo != null) {  
  87.             String[] permissions = packageInfo.requestedPermissions;  
  88.             if (permissions != null) {  
  89.                 for (String perm : permissions) {  
  90.                     Log.d(TAG, ”Manifest contained permission: ” + perm);  
  91.                     list.add(perm);  
  92.                 }  
  93.             }  
  94.         }  
  95.         return list.toArray(new String[list.size()]);  
  96.     }  
  97.   
  98.     /** 
  99.      * This method adds the {@link PermissionsResultAction} to the current list 
  100.      * of pending actions that will be completed when the permissions are 
  101.      * received. The list of permissions passed to this method are registered 
  102.      * in the PermissionsResultAction object so that it will be notified of changes 
  103.      * made to these permissions. 
  104.      * 
  105.      * @param permissions the required permissions for the action to be executed. 
  106.      * @param action      the action to add to the current list of pending actions. 
  107.      */  
  108.     private synchronized void addPendingAction(@NonNull String[] permissions,  
  109.                                                @Nullable PermissionsResultAction action) {  
  110.         if (action == null) {  
  111.             return;  
  112.         }  
  113.         action.registerPermissions(permissions);  
  114.         mPendingActions.add(new WeakReference<>(action));  
  115.     }  
  116.   
  117.     /** 
  118.      * This method removes a pending action from the list of pending actions. 
  119.      * It is used for cases where the permission has already been granted, so 
  120.      * you immediately wish to remove the pending action from the queue and 
  121.      * execute the action. 
  122.      * 
  123.      * @param action the action to remove 
  124.      */  
  125.     private synchronized void removePendingAction(@Nullable PermissionsResultAction action) {  
  126.         for (Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();  
  127.              iterator.hasNext(); ) {  
  128.             WeakReference<PermissionsResultAction> weakRef = iterator.next();  
  129.             if (weakRef.get() == action || weakRef.get() == null) {  
  130.                 iterator.remove();  
  131.             }  
  132.         }  
  133.     }  
  134.   
  135.     /** 
  136.      * This static method can be used to check whether or not you have a specific permission. 
  137.      * It is basically a less verbose method of using {@link ActivityCompat#checkSelfPermission(Context, String)} 
  138.      * and will simply return a boolean whether or not you have the permission. If you pass 
  139.      * in a null Context object, it will return false as otherwise it cannot check the permission. 
  140.      * However, the Activity parameter is nullable so that you can pass in a reference that you 
  141.      * are not always sure will be valid or not (e.g. getActivity() from Fragment). 
  142.      * 
  143.      * @param context    the Context necessary to check the permission 
  144.      * @param permission the permission to check 
  145.      * @return true if you have been granted the permission, false otherwise 
  146.      */  
  147.     @SuppressWarnings(“unused”)  
  148.     public synchronized boolean hasPermission(@Nullable Context context, @NonNull String permission) {  
  149.         return context != null && (ActivityCompat.checkSelfPermission(context, permission)  
  150.                 == PackageManager.PERMISSION_GRANTED || !mPermissions.contains(permission));  
  151.     }  
  152.   
  153.     /** 
  154.      * This static method can be used to check whether or not you have several specific permissions. 
  155.      * It is simpler than checking using {@link ActivityCompat#checkSelfPermission(Context, String)} 
  156.      * for each permission and will simply return a boolean whether or not you have all the permissions. 
  157.      * If you pass in a null Context object, it will return false as otherwise it cannot check the 
  158.      * permission. However, the Activity parameter is nullable so that you can pass in a reference 
  159.      * that you are not always sure will be valid or not (e.g. getActivity() from Fragment). 
  160.      * 
  161.      * @param context     the Context necessary to check the permission 
  162.      * @param permissions the permissions to check 
  163.      * @return true if you have been granted all the permissions, false otherwise 
  164.      */  
  165.     @SuppressWarnings(“unused”)  
  166.     public synchronized boolean hasAllPermissions(@Nullable Context context, @NonNull String[] permissions) {  
  167.         if (context == null) {  
  168.             return false;  
  169.         }  
  170.         boolean hasAllPermissions = true;  
  171.         for (String perm : permissions) {  
  172.             hasAllPermissions &= hasPermission(context, perm);  
  173.         }  
  174.         return hasAllPermissions;  
  175.     }  
  176.   
  177.     /** 
  178.      * This method will request all the permissions declared in your application manifest 
  179.      * for the specified {@link PermissionsResultAction}. The purpose of this method is to enable 
  180.      * all permissions to be requested at one shot. The PermissionsResultAction is used to notify 
  181.      * you of the user allowing or denying each permission. The Activity and PermissionsResultAction 
  182.      * parameters are both annotated Nullable, but this method will not work if the Activity 
  183.      * is null. It is only annotated Nullable as a courtesy to prevent crashes in the case 
  184.      * that you call this from a Fragment where {@link Fragment#getActivity()} could yield 
  185.      * null. Additionally, you will not receive any notification of permissions being granted 
  186.      * if you provide a null PermissionsResultAction. 
  187.      * 
  188.      * @param activity the Activity necessary to request and check permissions. 
  189.      * @param action   the PermissionsResultAction used to notify you of permissions being accepted. 
  190.      */  
  191.     @SuppressWarnings(“unused”)  
  192.     public synchronized void requestAllManifestPermissionsIfNecessary(final @Nullable Activity activity,  
  193.                                                                       final @Nullable PermissionsResultAction action) {  
  194.         if (activity == null) {  
  195.             return;  
  196.         }  
  197.         String[] perms = getManifestPermissions(activity);  
  198.         requestPermissionsIfNecessaryForResult(activity, perms, action);  
  199.     }  
  200.   
  201.     /** 
  202.      * This method should be used to execute a {@link PermissionsResultAction} for the array 
  203.      * of permissions passed to this method. This method will request the permissions if 
  204.      * they need to be requested (i.e. we don’t have permission yet) and will add the 
  205.      * PermissionsResultAction to the queue to be notified of permissions being granted or 
  206.      * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately. 
  207.      * The Activity variable is nullable, but if it is null, the method will fail to execute. 
  208.      * This is only nullable as a courtesy for Fragments where getActivity() may yeild null 
  209.      * if the Fragment is not currently added to its parent Activity. 
  210.      * 
  211.      * @param activity    the activity necessary to request the permissions. 
  212.      * @param permissions the list of permissions to request for the {@link PermissionsResultAction}. 
  213.      * @param action      the PermissionsResultAction to notify when the permissions are granted or denied. 
  214.      */  
  215.     @SuppressWarnings(“unused”)  
  216.     public synchronized void requestPermissionsIfNecessaryForResult(@Nullable Activity activity,  
  217.                                                                     @NonNull String[] permissions,  
  218.                                                                     @Nullable PermissionsResultAction action) {  
  219.         if (activity == null) {  
  220.             return;  
  221.         }  
  222.         addPendingAction(permissions, action);  
  223.         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {  
  224.             doPermissionWorkBeforeAndroidM(activity, permissions, action);  
  225.         } else {  
  226.             List<String> permList = getPermissionsListToRequest(activity, permissions, action);  
  227.             if (permList.isEmpty()) {  
  228.                 //if there is no permission to request, there is no reason to keep the action int the list  
  229.                 removePendingAction(action);  
  230.             } else {  
  231.                 String[] permsToRequest = permList.toArray(new String[permList.size()]);  
  232.                 mPendingRequests.addAll(permList);  
  233.                 ActivityCompat.requestPermissions(activity, permsToRequest, 1);  
  234.             }  
  235.         }  
  236.     }  
  237.   
  238.     /** 
  239.      * This method should be used to execute a {@link PermissionsResultAction} for the array 
  240.      * of permissions passed to this method. This method will request the permissions if 
  241.      * they need to be requested (i.e. we don’t have permission yet) and will add the 
  242.      * PermissionsResultAction to the queue to be notified of permissions being granted or 
  243.      * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately. 
  244.      * The Fragment variable is used, but if {@link Fragment#getActivity()} returns null, this method 
  245.      * will fail to work as the activity reference is necessary to check for permissions. 
  246.      * 
  247.      * @param fragment    the fragment necessary to request the permissions. 
  248.      * @param permissions the list of permissions to request for the {@link PermissionsResultAction}. 
  249.      * @param action      the PermissionsResultAction to notify when the permissions are granted or denied. 
  250.      */  
  251.     @SuppressWarnings(“unused”)  
  252.     public synchronized void requestPermissionsIfNecessaryForResult(@NonNull Fragment fragment,  
  253.                                                                     @NonNull String[] permissions,  
  254.                                                                     @Nullable PermissionsResultAction action) {  
  255.         Activity activity = fragment.getActivity();  
  256.         if (activity == null) {  
  257.             return;  
  258.         }  
  259.         addPendingAction(permissions, action);  
  260.         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {  
  261.             doPermissionWorkBeforeAndroidM(activity, permissions, action);  
  262.         } else {  
  263.             List<String> permList = getPermissionsListToRequest(activity, permissions, action);  
  264.             if (permList.isEmpty()) {  
  265.                 //if there is no permission to request, there is no reason to keep the action int the list  
  266.                 removePendingAction(action);  
  267.             } else {  
  268.                 String[] permsToRequest = permList.toArray(new String[permList.size()]);  
  269.                 mPendingRequests.addAll(permList);  
  270.                 fragment.requestPermissions(permsToRequest, 1);  
  271.             }  
  272.         }  
  273.     }  
  274.   
  275.     /** 
  276.      * This method notifies the PermissionsManager that the permissions have change. If you are making 
  277.      * the permissions requests using an Activity, then this method should be called from the 
  278.      * Activity callback onRequestPermissionsResult() with the variables passed to that method. If 
  279.      * you are passing a Fragment to make the permissions request, then you should call this in 
  280.      * the {@link Fragment#onRequestPermissionsResult(int, String[], int[])} method. 
  281.      * It will notify all the pending PermissionsResultAction objects currently 
  282.      * in the queue, and will remove the permissions request from the list of pending requests. 
  283.      * 
  284.      * @param permissions the permissions that have changed. 
  285.      * @param results     the values for each permission. 
  286.      */  
  287.     @SuppressWarnings(“unused”)  
  288.     public synchronized void notifyPermissionsChange(@NonNull String[] permissions, @NonNull int[] results) {  
  289.         int size = permissions.length;  
  290.         if (results.length < size) {  
  291.             size = results.length;  
  292.         }  
  293.         Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();  
  294.         while (iterator.hasNext()) {  
  295.             PermissionsResultAction action = iterator.next().get();  
  296.             for (int n = 0; n < size; n++) {  
  297.                 if (action == null || action.onResult(permissions[n], results[n])) {  
  298.                     iterator.remove();  
  299.                     break;  
  300.                 }  
  301.             }  
  302.         }  
  303.         for (int n = 0; n < size; n++) {  
  304.             mPendingRequests.remove(permissions[n]);  
  305.         }  
  306.     }  
  307.   
  308.     /** 
  309.      * When request permissions on devices before Android M (Android 6.0, API Level 23) 
  310.      * Do the granted or denied work directly according to the permission status 
  311.      * 
  312.      * @param activity    the activity to check permissions 
  313.      * @param permissions the permissions names 
  314.      * @param action      the callback work object, containing what we what to do after 
  315.      *                    permission check 
  316.      */  
  317.     private void doPermissionWorkBeforeAndroidM(@NonNull Activity activity,  
  318.                                                 @NonNull String[] permissions,  
  319.                                                 @Nullable PermissionsResultAction action) {  
  320.         for (String perm : permissions) {  
  321.             if (action != null) {  
  322.                 if (!mPermissions.contains(perm)) {  
  323.                     action.onResult(perm, Permissions.NOT_FOUND);  
  324.                 } else if (ActivityCompat.checkSelfPermission(activity, perm)  
  325.                         != PackageManager.PERMISSION_GRANTED) {  
  326.                     action.onResult(perm, Permissions.DENIED);  
  327.                 } else {  
  328.                     action.onResult(perm, Permissions.GRANTED);  
  329.                 }  
  330.             }  
  331.         }  
  332.     }  
  333.   
  334.     /** 
  335.      * Filter the permissions list: 
  336.      * If a permission is not granted, add it to the result list 
  337.      * if a permission is granted, do the granted work, do not add it to the result list 
  338.      * 
  339.      * @param activity    the activity to check permissions 
  340.      * @param permissions all the permissions names 
  341.      * @param action      the callback work object, containing what we what to do after 
  342.      *                    permission check 
  343.      * @return a list of permissions names that are not granted yet 
  344.      */  
  345.     @NonNull  
  346.     private List<String> getPermissionsListToRequest(@NonNull Activity activity,  
  347.                                                      @NonNull String[] permissions,  
  348.                                                      @Nullable PermissionsResultAction action) {  
  349.         List<String> permList = new ArrayList<>(permissions.length);  
  350.         for (String perm : permissions) {  
  351.             if (!mPermissions.contains(perm)) {  
  352.                 if (action != null) {  
  353.                     action.onResult(perm, Permissions.NOT_FOUND);  
  354.                 }  
  355.             } else if (ActivityCompat.checkSelfPermission(activity, perm) != PackageManager.PERMISSION_GRANTED) {  
  356.                 if (!mPendingRequests.contains(perm)) {  
  357.                     permList.add(perm);  
  358.                 }  
  359.             } else {  
  360.                 if (action != null) {  
  361.                     action.onResult(perm, Permissions.GRANTED);  
  362.                 }  
  363.             }  
  364.         }  
  365.         return permList;  
  366.     }  
  367.   
  368. }  
package com.anthonycr.grant;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.util.Log;

import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * A class to help you manage your permissions simply.
 */
public class PermissionsManager {

    private static final String TAG = PermissionsManager.class.getSimpleName();

    private final Set<String> mPendingRequests = new HashSet<>(1);
    private final Set<String> mPermissions = new HashSet<>(1);
    private final List<WeakReference<PermissionsResultAction>> mPendingActions = new ArrayList<>(1);

    private static PermissionsManager mInstance = null;

    public static PermissionsManager getInstance() {
        if (mInstance == null) {
            mInstance = new PermissionsManager();
        }
        return mInstance;
    }

    private PermissionsManager() {
        initializePermissionsMap();
    }

    /**
     * This method uses reflection to read all the permissions in the Manifest class.
     * This is necessary because some permissions do not exist on older versions of Android,
     * since they do not exist, they will be denied when you check whether you have permission
     * which is problematic since a new permission is often added where there was no previous
     * permission required. We initialize a Set of available permissions and check the set
     * when checking if we have permission since we want to know when we are denied a permission
     * because it doesn't exist yet.
     */
    private synchronized void initializePermissionsMap() {
        Field[] fields = Manifest.permission.class.getFields();
        for (Field field : fields) {
            String name = null;
            try {
                name = (String) field.get("");
            } catch (IllegalAccessException e) {
                Log.e(TAG, "Could not access field", e);
            }
            mPermissions.add(name);
        }
    }

    /**
     * This method retrieves all the permissions declared in the application's manifest.
     * It returns a non null array of permisions that can be declared.
     *
     * @param activity the Activity necessary to check what permissions we have.
     * @return a non null array of permissions that are declared in the application manifest.
     */
    @NonNull
    private synchronized String[] getManifestPermissions(@NonNull final Activity activity) {
        PackageInfo packageInfo = null;
        List<String> list = new ArrayList<>(1);
        try {
            Log.d(TAG, activity.getPackageName());
            packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "A problem occurred when retrieving permissions", e);
        }
        if (packageInfo != null) {
            String[] permissions = packageInfo.requestedPermissions;
            if (permissions != null) {
                for (String perm : permissions) {
                    Log.d(TAG, "Manifest contained permission: " + perm);
                    list.add(perm);
                }
            }
        }
        return list.toArray(new String[list.size()]);
    }

    /**
     * This method adds the {@link PermissionsResultAction} to the current list
     * of pending actions that will be completed when the permissions are
     * received. The list of permissions passed to this method are registered
     * in the PermissionsResultAction object so that it will be notified of changes
     * made to these permissions.
     *
     * @param permissions the required permissions for the action to be executed.
     * @param action      the action to add to the current list of pending actions.
     */
    private synchronized void addPendingAction(@NonNull String[] permissions,
                                               @Nullable PermissionsResultAction action) {
        if (action == null) {
            return;
        }
        action.registerPermissions(permissions);
        mPendingActions.add(new WeakReference<>(action));
    }

    /**
     * This method removes a pending action from the list of pending actions.
     * It is used for cases where the permission has already been granted, so
     * you immediately wish to remove the pending action from the queue and
     * execute the action.
     *
     * @param action the action to remove
     */
    private synchronized void removePendingAction(@Nullable PermissionsResultAction action) {
        for (Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();
             iterator.hasNext(); ) {
            WeakReference<PermissionsResultAction> weakRef = iterator.next();
            if (weakRef.get() == action || weakRef.get() == null) {
                iterator.remove();
            }
        }
    }

    /**
     * This static method can be used to check whether or not you have a specific permission.
     * It is basically a less verbose method of using {@link ActivityCompat#checkSelfPermission(Context, String)}
     * and will simply return a boolean whether or not you have the permission. If you pass
     * in a null Context object, it will return false as otherwise it cannot check the permission.
     * However, the Activity parameter is nullable so that you can pass in a reference that you
     * are not always sure will be valid or not (e.g. getActivity() from Fragment).
     *
     * @param context    the Context necessary to check the permission
     * @param permission the permission to check
     * @return true if you have been granted the permission, false otherwise
     */
    @SuppressWarnings("unused")
    public synchronized boolean hasPermission(@Nullable Context context, @NonNull String permission) {
        return context != null && (ActivityCompat.checkSelfPermission(context, permission)
                == PackageManager.PERMISSION_GRANTED || !mPermissions.contains(permission));
    }

    /**
     * This static method can be used to check whether or not you have several specific permissions.
     * It is simpler than checking using {@link ActivityCompat#checkSelfPermission(Context, String)}
     * for each permission and will simply return a boolean whether or not you have all the permissions.
     * If you pass in a null Context object, it will return false as otherwise it cannot check the
     * permission. However, the Activity parameter is nullable so that you can pass in a reference
     * that you are not always sure will be valid or not (e.g. getActivity() from Fragment).
     *
     * @param context     the Context necessary to check the permission
     * @param permissions the permissions to check
     * @return true if you have been granted all the permissions, false otherwise
     */
    @SuppressWarnings("unused")
    public synchronized boolean hasAllPermissions(@Nullable Context context, @NonNull String[] permissions) {
        if (context == null) {
            return false;
        }
        boolean hasAllPermissions = true;
        for (String perm : permissions) {
            hasAllPermissions &= hasPermission(context, perm);
        }
        return hasAllPermissions;
    }

    /**
     * This method will request all the permissions declared in your application manifest
     * for the specified {@link PermissionsResultAction}. The purpose of this method is to enable
     * all permissions to be requested at one shot. The PermissionsResultAction is used to notify
     * you of the user allowing or denying each permission. The Activity and PermissionsResultAction
     * parameters are both annotated Nullable, but this method will not work if the Activity
     * is null. It is only annotated Nullable as a courtesy to prevent crashes in the case
     * that you call this from a Fragment where {@link Fragment#getActivity()} could yield
     * null. Additionally, you will not receive any notification of permissions being granted
     * if you provide a null PermissionsResultAction.
     *
     * @param activity the Activity necessary to request and check permissions.
     * @param action   the PermissionsResultAction used to notify you of permissions being accepted.
     */
    @SuppressWarnings("unused")
    public synchronized void requestAllManifestPermissionsIfNecessary(final @Nullable Activity activity,
                                                                      final @Nullable PermissionsResultAction action) {
        if (activity == null) {
            return;
        }
        String[] perms = getManifestPermissions(activity);
        requestPermissionsIfNecessaryForResult(activity, perms, action);
    }

    /**
     * This method should be used to execute a {@link PermissionsResultAction} for the array
     * of permissions passed to this method. This method will request the permissions if
     * they need to be requested (i.e. we don't have permission yet) and will add the
     * PermissionsResultAction to the queue to be notified of permissions being granted or
     * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
     * The Activity variable is nullable, but if it is null, the method will fail to execute.
     * This is only nullable as a courtesy for Fragments where getActivity() may yeild null
     * if the Fragment is not currently added to its parent Activity.
     *
     * @param activity    the activity necessary to request the permissions.
     * @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
     * @param action      the PermissionsResultAction to notify when the permissions are granted or denied.
     */
    @SuppressWarnings("unused")
    public synchronized void requestPermissionsIfNecessaryForResult(@Nullable Activity activity,
                                                                    @NonNull String[] permissions,
                                                                    @Nullable PermissionsResultAction action) {
        if (activity == null) {
            return;
        }
        addPendingAction(permissions, action);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            doPermissionWorkBeforeAndroidM(activity, permissions, action);
        } else {
            List<String> permList = getPermissionsListToRequest(activity, permissions, action);
            if (permList.isEmpty()) {
                //if there is no permission to request, there is no reason to keep the action int the list
                removePendingAction(action);
            } else {
                String[] permsToRequest = permList.toArray(new String[permList.size()]);
                mPendingRequests.addAll(permList);
                ActivityCompat.requestPermissions(activity, permsToRequest, 1);
            }
        }
    }

    /**
     * This method should be used to execute a {@link PermissionsResultAction} for the array
     * of permissions passed to this method. This method will request the permissions if
     * they need to be requested (i.e. we don't have permission yet) and will add the
     * PermissionsResultAction to the queue to be notified of permissions being granted or
     * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
     * The Fragment variable is used, but if {@link Fragment#getActivity()} returns null, this method
     * will fail to work as the activity reference is necessary to check for permissions.
     *
     * @param fragment    the fragment necessary to request the permissions.
     * @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
     * @param action      the PermissionsResultAction to notify when the permissions are granted or denied.
     */
    @SuppressWarnings("unused")
    public synchronized void requestPermissionsIfNecessaryForResult(@NonNull Fragment fragment,
                                                                    @NonNull String[] permissions,
                                                                    @Nullable PermissionsResultAction action) {
        Activity activity = fragment.getActivity();
        if (activity == null) {
            return;
        }
        addPendingAction(permissions, action);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            doPermissionWorkBeforeAndroidM(activity, permissions, action);
        } else {
            List<String> permList = getPermissionsListToRequest(activity, permissions, action);
            if (permList.isEmpty()) {
                //if there is no permission to request, there is no reason to keep the action int the list
                removePendingAction(action);
            } else {
                String[] permsToRequest = permList.toArray(new String[permList.size()]);
                mPendingRequests.addAll(permList);
                fragment.requestPermissions(permsToRequest, 1);
            }
        }
    }

    /**
     * This method notifies the PermissionsManager that the permissions have change. If you are making
     * the permissions requests using an Activity, then this method should be called from the
     * Activity callback onRequestPermissionsResult() with the variables passed to that method. If
     * you are passing a Fragment to make the permissions request, then you should call this in
     * the {@link Fragment#onRequestPermissionsResult(int, String[], int[])} method.
     * It will notify all the pending PermissionsResultAction objects currently
     * in the queue, and will remove the permissions request from the list of pending requests.
     *
     * @param permissions the permissions that have changed.
     * @param results     the values for each permission.
     */
    @SuppressWarnings("unused")
    public synchronized void notifyPermissionsChange(@NonNull String[] permissions, @NonNull int[] results) {
        int size = permissions.length;
        if (results.length < size) {
            size = results.length;
        }
        Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();
        while (iterator.hasNext()) {
            PermissionsResultAction action = iterator.next().get();
            for (int n = 0; n < size; n++) {
                if (action == null || action.onResult(permissions[n], results[n])) {
                    iterator.remove();
                    break;
                }
            }
        }
        for (int n = 0; n < size; n++) {
            mPendingRequests.remove(permissions[n]);
        }
    }

    /**
     * When request permissions on devices before Android M (Android 6.0, API Level 23)
     * Do the granted or denied work directly according to the permission status
     *
     * @param activity    the activity to check permissions
     * @param permissions the permissions names
     * @param action      the callback work object, containing what we what to do after
     *                    permission check
     */
    private void doPermissionWorkBeforeAndroidM(@NonNull Activity activity,
                                                @NonNull String[] permissions,
                                                @Nullable PermissionsResultAction action) {
        for (String perm : permissions) {
            if (action != null) {
                if (!mPermissions.contains(perm)) {
                    action.onResult(perm, Permissions.NOT_FOUND);
                } else if (ActivityCompat.checkSelfPermission(activity, perm)
                        != PackageManager.PERMISSION_GRANTED) {
                    action.onResult(perm, Permissions.DENIED);
                } else {
                    action.onResult(perm, Permissions.GRANTED);
                }
            }
        }
    }

    /**
     * Filter the permissions list:
     * If a permission is not granted, add it to the result list
     * if a permission is granted, do the granted work, do not add it to the result list
     *
     * @param activity    the activity to check permissions
     * @param permissions all the permissions names
     * @param action      the callback work object, containing what we what to do after
     *                    permission check
     * @return a list of permissions names that are not granted yet
     */
    @NonNull
    private List<String> getPermissionsListToRequest(@NonNull Activity activity,
                                                     @NonNull String[] permissions,
                                                     @Nullable PermissionsResultAction action) {
        List<String> permList = new ArrayList<>(permissions.length);
        for (String perm : permissions) {
            if (!mPermissions.contains(perm)) {
                if (action != null) {
                    action.onResult(perm, Permissions.NOT_FOUND);
                }
            } else if (ActivityCompat.checkSelfPermission(activity, perm) != PackageManager.PERMISSION_GRANTED) {
                if (!mPendingRequests.contains(perm)) {
                    permList.add(perm);
                }
            } else {
                if (action != null) {
                    action.onResult(perm, Permissions.GRANTED);
                }
            }
        }
        return permList;
    }

}
这个类主要是获取单例下的权限管理类,然后通过内部方法进行权限管理
(3) PermissionsResultAction

  1. package com.anthonycr.grant;  
  2.   
  3. import android.content.pm.PackageManager;  
  4. import android.os.Handler;  
  5. import android.os.Looper;  
  6. import android.support.annotation.CallSuper;  
  7. import android.support.annotation.NonNull;  
  8. import android.util.Log;  
  9.   
  10. import java.util.Collections;  
  11. import java.util.HashSet;  
  12. import java.util.Set;  
  13.   
  14. /** 
  15.  * This abstract class should be used to create an if/else action that the PermissionsManager 
  16.  * can execute when the permissions you request are granted or denied. Simple use involves 
  17.  * creating an anonymous instance of it and passing that instance to the 
  18.  * requestPermissionsIfNecessaryForResult method. The result will be sent back to you as 
  19.  * either onGranted (all permissions have been granted), or onDenied (a required permission 
  20.  * has been denied). Ideally you put your functionality in the onGranted method and notify 
  21.  * the user what won’t work in the onDenied method. 
  22.  */  
  23. public abstract class PermissionsResultAction {  
  24.   
  25.     private static final String TAG = PermissionsResultAction.class.getSimpleName();  
  26.     private final Set<String> mPermissions = new HashSet<>(1);  
  27.     private Looper mLooper = Looper.getMainLooper();  
  28.   
  29.     /** 
  30.      * Default Constructor 
  31.      */  
  32.     public PermissionsResultAction() {}  
  33.   
  34.     /** 
  35.      * Alternate Constructor. Pass the looper you wish the PermissionsResultAction 
  36.      * callbacks to be executed on if it is not the current Looper. For instance, 
  37.      * if you are making a permissions request from a background thread but wish the 
  38.      * callback to be on the UI thread, use this constructor to specify the UI Looper. 
  39.      * 
  40.      * @param looper the looper that the callbacks will be called using. 
  41.      */  
  42.     @SuppressWarnings(“unused”)  
  43.     public PermissionsResultAction(@NonNull Looper looper) {mLooper = looper;}  
  44.   
  45.     /** 
  46.      * This method is called when ALL permissions that have been 
  47.      * requested have been granted by the user. In this method 
  48.      * you should put all your permissions sensitive code that can 
  49.      * only be executed with the required permissions. 
  50.      */  
  51.     public abstract void onGranted();  
  52.   
  53.     /** 
  54.      * This method is called when a permission has been denied by 
  55.      * the user. It provides you with the permission that was denied 
  56.      * and will be executed on the Looper you pass to the constructor 
  57.      * of this class, or the Looper that this object was created on. 
  58.      * 
  59.      * @param permission the permission that was denied. 
  60.      */  
  61.     public abstract void onDenied(String permission);  
  62.   
  63.     /** 
  64.      * This method is used to determine if a permission not 
  65.      * being present on the current Android platform should 
  66.      * affect whether the PermissionsResultAction should continue 
  67.      * listening for events. By default, it returns true and will 
  68.      * simply ignore the permission that did not exist. Usually this will 
  69.      * work fine since most new permissions are introduced to 
  70.      * restrict what was previously allowed without permission. 
  71.      * If that is not the case for your particular permission you 
  72.      * request, override this method and return false to result in the 
  73.      * Action being denied. 
  74.      * 
  75.      * @param permission the permission that doesn’t exist on this 
  76.      *                   Android version 
  77.      * @return return true if the PermissionsResultAction should 
  78.      * ignore the lack of the permission and proceed with exection 
  79.      * or false if the PermissionsResultAction should treat the 
  80.      * absence of the permission on the API level as a denial. 
  81.      */  
  82.     @SuppressWarnings({“WeakerAccess”“SameReturnValue”})  
  83.     public synchronized boolean shouldIgnorePermissionNotFound(String permission) {  
  84.         Log.d(TAG, ”Permission not found: ” + permission);  
  85.         return true;  
  86.     }  
  87.   
  88.     @SuppressWarnings(“WeakerAccess”)  
  89.     @CallSuper  
  90.     protected synchronized final boolean onResult(final @NonNull String permission, int result) {  
  91.         if (result == PackageManager.PERMISSION_GRANTED) {  
  92.             return onResult(permission, Permissions.GRANTED);  
  93.         } else {  
  94.             return onResult(permission, Permissions.DENIED);  
  95.         }  
  96.   
  97.     }  
  98.   
  99.     /** 
  100.      * This method is called when a particular permission has changed. 
  101.      * This method will be called for all permissions, so this method determines 
  102.      * if the permission affects the state or not and whether it can proceed with 
  103.      * calling onGranted or if onDenied should be called. 
  104.      * 
  105.      * @param permission the permission that changed. 
  106.      * @param result     the result for that permission. 
  107.      * @return this method returns true if its primary action has been completed 
  108.      * and it should be removed from the data structure holding a reference to it. 
  109.      */  
  110.     @SuppressWarnings(“WeakerAccess”)  
  111.     @CallSuper  
  112.     protected synchronized final boolean onResult(final @NonNull String permission, Permissions result) {  
  113.         mPermissions.remove(permission);  
  114.         if (result == Permissions.GRANTED) {  
  115.             if (mPermissions.isEmpty()) {  
  116.                 new Handler(mLooper).post(new Runnable() {  
  117.                     @Override  
  118.                     public void run() {  
  119.                         onGranted();  
  120.                     }  
  121.                 });  
  122.                 return true;  
  123.             }  
  124.         } else if (result == Permissions.DENIED) {  
  125.             new Handler(mLooper).post(new Runnable() {  
  126.                 @Override  
  127.                 public void run() {  
  128.                     onDenied(permission);  
  129.                 }  
  130.             });  
  131.             return true;  
  132.         } else if (result == Permissions.NOT_FOUND) {  
  133.             if (shouldIgnorePermissionNotFound(permission)) {  
  134.                 if (mPermissions.isEmpty()) {  
  135.                     new Handler(mLooper).post(new Runnable() {  
  136.                         @Override  
  137.                         public void run() {  
  138.                             onGranted();  
  139.                         }  
  140.                     });  
  141.                     return true;  
  142.                 }  
  143.             } else {  
  144.                 new Handler(mLooper).post(new Runnable() {  
  145.                     @Override  
  146.                     public void run() {  
  147.                         onDenied(permission);  
  148.                     }  
  149.                 });  
  150.                 return true;  
  151.             }  
  152.         }  
  153.         return false;  
  154.     }  
  155.   
  156.     /** 
  157.      * This method registers the PermissionsResultAction object for the specified permissions 
  158.      * so that it will know which permissions to look for changes to. The PermissionsResultAction 
  159.      * will then know to look out for changes to these permissions. 
  160.      * 
  161.      * @param perms the permissions to listen for 
  162.      */  
  163.     @SuppressWarnings(“WeakerAccess”)  
  164.     @CallSuper  
  165.     protected synchronized final void registerPermissions(@NonNull String[] perms) {  
  166.         Collections.addAll(mPermissions, perms);  
  167.     }  
  168. }  
package com.anthonycr.grant;

import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.util.Log;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * This abstract class should be used to create an if/else action that the PermissionsManager
 * can execute when the permissions you request are granted or denied. Simple use involves
 * creating an anonymous instance of it and passing that instance to the
 * requestPermissionsIfNecessaryForResult method. The result will be sent back to you as
 * either onGranted (all permissions have been granted), or onDenied (a required permission
 * has been denied). Ideally you put your functionality in the onGranted method and notify
 * the user what won't work in the onDenied method.
 */
public abstract class PermissionsResultAction {

    private static final String TAG = PermissionsResultAction.class.getSimpleName();
    private final Set<String> mPermissions = new HashSet<>(1);
    private Looper mLooper = Looper.getMainLooper();

    /**
     * Default Constructor
     */
    public PermissionsResultAction() {}

    /**
     * Alternate Constructor. Pass the looper you wish the PermissionsResultAction
     * callbacks to be executed on if it is not the current Looper. For instance,
     * if you are making a permissions request from a background thread but wish the
     * callback to be on the UI thread, use this constructor to specify the UI Looper.
     *
     * @param looper the looper that the callbacks will be called using.
     */
    @SuppressWarnings("unused")
    public PermissionsResultAction(@NonNull Looper looper) {mLooper = looper;}

    /**
     * This method is called when ALL permissions that have been
     * requested have been granted by the user. In this method
     * you should put all your permissions sensitive code that can
     * only be executed with the required permissions.
     */
    public abstract void onGranted();

    /**
     * This method is called when a permission has been denied by
     * the user. It provides you with the permission that was denied
     * and will be executed on the Looper you pass to the constructor
     * of this class, or the Looper that this object was created on.
     *
     * @param permission the permission that was denied.
     */
    public abstract void onDenied(String permission);

    /**
     * This method is used to determine if a permission not
     * being present on the current Android platform should
     * affect whether the PermissionsResultAction should continue
     * listening for events. By default, it returns true and will
     * simply ignore the permission that did not exist. Usually this will
     * work fine since most new permissions are introduced to
     * restrict what was previously allowed without permission.
     * If that is not the case for your particular permission you
     * request, override this method and return false to result in the
     * Action being denied.
     *
     * @param permission the permission that doesn't exist on this
     *                   Android version
     * @return return true if the PermissionsResultAction should
     * ignore the lack of the permission and proceed with exection
     * or false if the PermissionsResultAction should treat the
     * absence of the permission on the API level as a denial.
     */
    @SuppressWarnings({"WeakerAccess", "SameReturnValue"})
    public synchronized boolean shouldIgnorePermissionNotFound(String permission) {
        Log.d(TAG, "Permission not found: " + permission);
        return true;
    }

    @SuppressWarnings("WeakerAccess")
    @CallSuper
    protected synchronized final boolean onResult(final @NonNull String permission, int result) {
        if (result == PackageManager.PERMISSION_GRANTED) {
            return onResult(permission, Permissions.GRANTED);
        } else {
            return onResult(permission, Permissions.DENIED);
        }

    }

    /**
     * This method is called when a particular permission has changed.
     * This method will be called for all permissions, so this method determines
     * if the permission affects the state or not and whether it can proceed with
     * calling onGranted or if onDenied should be called.
     *
     * @param permission the permission that changed.
     * @param result     the result for that permission.
     * @return this method returns true if its primary action has been completed
     * and it should be removed from the data structure holding a reference to it.
     */
    @SuppressWarnings("WeakerAccess")
    @CallSuper
    protected synchronized final boolean onResult(final @NonNull String permission, Permissions result) {
        mPermissions.remove(permission);
        if (result == Permissions.GRANTED) {
            if (mPermissions.isEmpty()) {
                new Handler(mLooper).post(new Runnable() {
                    @Override
                    public void run() {
                        onGranted();
                    }
                });
                return true;
            }
        } else if (result == Permissions.DENIED) {
            new Handler(mLooper).post(new Runnable() {
                @Override
                public void run() {
                    onDenied(permission);
                }
            });
            return true;
        } else if (result == Permissions.NOT_FOUND) {
            if (shouldIgnorePermissionNotFound(permission)) {
                if (mPermissions.isEmpty()) {
                    new Handler(mLooper).post(new Runnable() {
                        @Override
                        public void run() {
                            onGranted();
                        }
                    });
                    return true;
                }
            } else {
                new Handler(mLooper).post(new Runnable() {
                    @Override
                    public void run() {
                        onDenied(permission);
                    }
                });
                return true;
            }
        }
        return false;
    }

    /**
     * This method registers the PermissionsResultAction object for the specified permissions
     * so that it will know which permissions to look for changes to. The PermissionsResultAction
     * will then know to look out for changes to these permissions.
     *
     * @param perms the permissions to listen for
     */
    @SuppressWarnings("WeakerAccess")
    @CallSuper
    protected synchronized final void registerPermissions(@NonNull String[] perms) {
        Collections.addAll(mPermissions, perms);
    }
}
这个类是用来做回调使用的,方便在调用过以后进行回调。


没有做翻译,如果看不懂,用翻译软件一点一点看把。

下面写一个例子,来进行示范:

  1. public class SplashActivity extends Activity {  
  2.   
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6. //        requestWindowFeature(Window.FEATURE_NO_TITLE); //设置无标题  
  7. //        getWindow().setFlags(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);  //设置全屏  
  8.         setContentView(R.layout.activity_splash);  
  9.         requestAllPermission();//请求获取全部权限  
  10.     }  
  11.   
  12.     /** 
  13.      * 请求获取全部权限,调用权限管理类,然后放进去需要申请的权限,通过接口回调的方法获得权限获取结果 
  14.      */  
  15.     private void requestAllPermission() {  
  16.         PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(SplashActivity.this, ConstantString.permissions, new PermissionsResultAction() {  
  17.             @Override  
  18.             public void onGranted() {  
  19.                 L.i(”onGranted”);  
  20.                 myHandler.sendEmptyMessage(GETPERMISSION_SUCCESS);  
  21.             }  
  22.   
  23.             @Override  
  24.             public void onDenied(String permission) {  
  25.                 L.i(”onDenied”);  
  26.                 myHandler.sendEmptyMessage(GETPERMISSION_FAILER);  
  27.             }  
  28.         });  
  29.     }  
  30.   
  31.   
  32.   
  33.     private static final int GETPERMISSION_SUCCESS = 1;//获取权限成功  
  34.     private static final int GETPERMISSION_FAILER = 2;//获取权限失败  
  35.     private MyHandler myHandler = new MyHandler();  
  36.   
  37.     private class MyHandler extends Handler {  
  38.         @Override  
  39.         public void handleMessage(Message msg) {  
  40.             super.handleMessage(msg);  
  41.             switch (msg.what) {  
  42.                 case GETPERMISSION_SUCCESS:  
  43. <span style=”white-space:pre”>        </span>    startActivity(new Intent(SplashActivity.this,MainActivity.class));  
  44.                     break;  
  45.                 case GETPERMISSION_FAILER:  
  46.                     T.showShort(SplashActivity.this“应用没有获取权限,请重新打开应用,或者到设置页面添加权限以后再从新打开。”);  
  47.                     break;  
  48.             }  
  49.         }  
  50.     }  
  51.   
  52.     //因为权限管理类无法监听系统,所以需要重写onRequestPermissionResult方法,更新权限管理类,并回调结果。这个是必须要有的。  
  53.     @Override  
  54.     public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {  
  55.         PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);  
  56.     }  
  57. }  
public class SplashActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        requestWindowFeature(Window.FEATURE_NO_TITLE); //设置无标题
//        getWindow().setFlags(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);  //设置全屏
        setContentView(R.layout.activity_splash);
        requestAllPermission();//请求获取全部权限
    }

    /**
     * 请求获取全部权限,调用权限管理类,然后放进去需要申请的权限,通过接口回调的方法获得权限获取结果
     */
    private void requestAllPermission() {
        PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(SplashActivity.this, ConstantString.permissions, new PermissionsResultAction() {
            @Override
            public void onGranted() {
                L.i("onGranted");
                myHandler.sendEmptyMessage(GETPERMISSION_SUCCESS);
            }

            @Override
            public void onDenied(String permission) {
                L.i("onDenied");
                myHandler.sendEmptyMessage(GETPERMISSION_FAILER);
            }
        });
    }



    private static final int GETPERMISSION_SUCCESS = 1;//获取权限成功
    private static final int GETPERMISSION_FAILER = 2;//获取权限失败
    private MyHandler myHandler = new MyHandler();

    private class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case GETPERMISSION_SUCCESS:
<span style="white-space:pre">        </span>    startActivity(new Intent(SplashActivity.this,MainActivity.class));
                    break;
                case GETPERMISSION_FAILER:
                    T.showShort(SplashActivity.this, "应用没有获取权限,请重新打开应用,或者到设置页面添加权限以后再从新打开。");
                    break;
            }
        }
    }

    //因为权限管理类无法监听系统,所以需要重写onRequestPermissionResult方法,更新权限管理类,并回调结果。这个是必须要有的。
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);
    }
}

看过上面的代码以后是不是觉得6.0的权限管理变的简单了,但是还有更见的一个方法 requestAllManifestPermissionIfNecessary() 这个方法会自动查询清单文件当中申请的权限,然后自动调取系统的权限获取方法,一次解决所有问题。

上述方式用来解决权限管理对于大家的代码结构会有很大的提升,同时减少大家的代码量,期望给大家更多的问题解决方案。



猜你喜欢

转载自blog.csdn.net/u013651026/article/details/80862417