android权限申请库解析

    开发android项目 权限是不可或缺的;最常见的请求网络的权限、读写文件的权限等 都是保证使用这些权限的项目的正常运行的前提。
     android 我们都知道他是非常开源的、开放的;开放到在6.0 之前基本上所有的权限都可以直接添加到清单文件中使用而不需要管他是否允许;因为6.0系统以前他默认就是允许的。
     but … 也许是android的使用大军或者是andorid的系统研发大神们感觉 android太开放了 亦或者也是希望向传说中的最安全的系统:iOS过度?所以在6.0 以后的系统中对android的权限 申请添加一些用户的选择操作处理? 留给后来人讨论O(∩_∩)O~
具体关于权限的详细情况可以关注我的博客:
http://blog.csdn.net/u013472738/article/details/52441268

上篇的博客充分解释了传统的权限使用方式很单个或者多个权限的申请方式。
下面 为了优化代码 我们这里 使用三方的库来理解权限申请的方式 :下面我们对三方权限的源码进行简单的使用说明和类的解析。

首先上传送门:https://github.com/anthonycr/Grant

权限库的方便之处:(来自文档说明)

1:它可以以单一方法请求所有您声明的权限,并在授予它们时给予回调。
2:它可以通过检查应用程序是否具有权限并请求许可(如果您尚未拥有该权限),可以在将来的某个时间执行任务,需要特定许可。
3:它使您的应用程序逻辑更简单,无需管理您的权限敏感代码,onRequestPermissionsResult并找出您需要调用的内容。
总之 用个人的一句话就是:使用方便 快捷,提高代码可读性。

开搞——————–

添加库到项目中

1:方式一:直接添加:
在app–>build.gradle中添加:

dependencies {
     //... 其他操作库
    compile 'com.anthonycr.grant:permissions:1.0'
      //...
}

2:方式二:下载传送门中的library库 ;添加到项目依赖中。

源码使用解析

传统的权限申请:
http://blog.csdn.net/u013472738/article/details/52441268 已经详细说明。
下面我们就来通过源码 大致了解下 这个新的权限库的使用方式:
1:类:Permissions.java

enum Permissions {
    GRANTED,
    DENIED,
    NOT_FOUND
}

很明白 一个枚举类用来对应三种状态:已授权,授权失败,未发现的权限;
没什么东西可以看的; 就是看做一个全局的量 用的时候调用一下:方法.属性;没啥;如果你很闲 把他删掉在使用的时候 单独写上里面的属性 也是可以的O(∩_∩)O哈哈~
重头戏总是在后面:

2:重点来了:PermissionsManager.java 类
我们通过名字就可以看出来 他是一个权限的管理类;也就是说他是用来管理权限的; 那么OK;我们在使用这个库的时候 这个类的重要性 就很显而易见了。
看看源码:


/**
 * A class to help you manage your permissions simply.
 * 一个帮助您简单地管理权限的类。
 */
public class PermissionsManager {

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

    private final Set mPendingRequests = new HashSet<>(1);
    private final Set mPermissions = new HashSet<>(1);
    private final List> 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.
     * *此方法使用反射来读取Manifest类中的所有权限。
     *这是必要的,因为在老版本的Android上不存在一些权限,
     *由于他们不存在,当你检查你是否得到许可时,他们会被拒绝
     *这是有问题的,因为一个新的许可经常被添加到没有以前的地方
     *许可要求。我们初始化了一组可用的权限并检查集合
     *当检查我们是否有许可的时候,我们想知道什么时候我们被拒绝了
     因为它还不存在。
     */
    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.
     * *此方法检索应用程序清单中声明的所有权限。
     *它返回可以声明的非零值数组。

     *
     * TJ:这个是比较重要:用来一次性获取清单中的所有权限的方法;后面我们在代码使用中会提到。
     */
    @NonNull
    private synchronized String[] getManifestPermissions(@NonNull final Activity activity) {
        PackageInfo packageInfo = null;
        List 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.
     *
     * 此方法将{ @ link PermissionsResultAction }添加到当前列表
     *等待权限时将完成的未决操作*
     *收到。传递给该方法的权限列表已注册
     *在PermissionsResultAction对象中,这样它将被通知更改
     *对这些权限进行了操作。
     * *
     * @ param权限为要执行的操作所需的权限。
     * @ param动作,将动作添加到当前挂起的动作列表中。
     */
    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
     * 此方法从挂起动作的列表中移除一个挂起的操作。
     *它用于已经获得许可的情况下
     *您立即希望从队列中删除挂起的操作
     *执行行动。
     * *
     * @ param动作移除
     *
     *  TJ:说白了 就是没有权限需要执行的时候  就不在处理权限的逻辑问题了。
     */
    private synchronized void removePendingAction(@Nullable PermissionsResultAction action) {
        for (Iterator> iterator = mPendingActions.iterator();
             iterator.hasNext(); ) {
            WeakReference 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
     *
     * *此静态方法可用于检查您是否有特定的权限。
     *使用{ @ link ActivityCompat # checkSelfPermission(上下文,字符串)}的方法比较简单
     *无论你是否得到许可,都会返回一个布尔值。如果你通过
     *在null上下文对象中,它将返回false,否则它无法检查权限。
     *然而,活动参数是可空的,以便您可以传递一个引用
     *不总是确定是否有效(例如,从片段中获得getActivity())。
     * *
     * @ param上下文需要检查权限
     * @ param允许进行检查
    如果您获得了许可,则返回true,否则将是false
     *
     * TJ:这个方法更简单了:就是判断你的摸一个权限是否申请成功了。
     */
    @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
     * *这个静态方法可以用来检查你是否有几个特定的权限。
     *它比使用{ @ link ActivityCompat # checkSelfPermission(上下文,字符串)}检查更简单
     *对于每个权限,只返回一个布尔值,不管您是否拥有所有权限。
     *如果您传递的是空上下文对象,它将返回false,否则它无法检查
     *许可。然而,活动参数是可空的,因此可以在引用中传递
     *您并不总是确定是否有效(例如,从片段中获得getActivity())。
     * *
     * @ param上下文需要检查权限
     * @ param权限检查权限
    如果您已经获得了所有权限,则返回true,否则将是false
     *
     *
     * TJ:这个方法是上一个方法的 扩大版:上一个方法是判断一个权限;这个方法判断是所有的传入参数中的权限 ;(当然也可以是一个;如果你高兴的话)
     */
    @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.
     *
     *                 *此方法将请求在您的应用程序清单中声明的所有权限
     *对于指定的{ @ link PermissionsResultAction }。这种方法的目的是为了启用
     *所有权限应在一次拍摄。PermissionsResultAction被用来通知
     *用户允许或拒绝每个权限。的活动和PermissionsResultAction
     *参数都是可空的,但如果活动,此方法将不起作用
     *是null。它仅被注释为可空的,以防止在案例中发生崩溃
     *从{ @ link碎片# getActivity()}可以产生的片段中调用这个
     * null。此外,您将不会收到授予权限的任何通知
     *如果您提供一个空的PermissionsResultAction。
     * *
     * @ param活动,请求和检查权限所必需的活动。
     * @ param操作的PermissionsResultAction用于通知您被接受的权限。
     *
     *  TJ:重点:这个就是上面提到的一次性申请所有权限的操作。(当然这种方式对用户来说不太友好;如果你的权限过多的话。)
     */
    @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.
     *
     *
     *
     *  该方法应该用于对数组执行{ @ link PermissionsResultAction }
    传递给该方法的权限*。该方法将请求权限
    他们需要被要求(即我们还没有得到许可),并将添加
     * PermissionsResultAction到队列,以获得授予权限的通知
     *否认。在android前Marshmallow的情况下,权限将立即被授予。
     *活动变量为nullable,但如果它为null,则该方法将无法执行。
     *对于getActivity()可能yeild null的片段,这仅仅是空的
     *如果该片段当前未添加到其父活动中。
     * *
     * @ param活动需要请求权限的活动。
     * @ param权限列表请求{ @ link PermissionsResultAction }。
     * @ param操作的PermissionsResultAction通知当权限被授予或拒绝时
     *
     *
     *
     */
    @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 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.
     *
     *                    *该方法应该用于对数组执行{ @ link PermissionsResultAction }
    传递给该方法的权限*。该方法将请求权限
    他们需要被要求(即我们还没有得到许可),并将添加
     * PermissionsResultAction到队列,以获得授予权限的通知
     *否认。在android前Marshmallow的情况下,权限将立即被授予。
     *使用片段变量,但如果{ @ link片段# getActivity()}返回null,此方法
     *将无法正常工作,因为活动引用需要检查权限。
     * *
     * @ param片段需要请求权限的片段。
     * @ param权限列表请求{ @ link PermissionsResultAction }。
     * @ param操作的PermissionsResultAction通知当权限被授予或拒绝时。
     *
     *
     */
    @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 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.
     *
     *                    该方法通知PermissionsManager,权限有更改。如果你正在
     *使用活动的权限请求,然后从该方法调用该方法
     *活动调onRequestPermissionsResult()的变量传递给方法。如果
     *您正在传递一个片段来进行权限请求,那么您应该调用这个片段
     * { # onRequestPermissionsResult @link片段(String[]int,int[])}的方法。
     *它将通知当前所有挂起的PermissionsResultAction对象
     *在队列中,并将从待处理请求列表中删除权限请求。
     * *
     * @ param权限更改的权限。
     * @ param结果每个权限的值
     *
     *  TJ:重点:这一步 不管你是执行一个或者多个权限申请 ;这个回调更新都是要执行的;  类似于BaseAdapter中的:notifyDataSetChanged;对 :就是一个逻辑操作完后的更新操作。
     */
    @SuppressWarnings("unused")
    public synchronized void notifyPermissionsChange(@NonNull String[] permissions, @NonNull int[] results) {
        int size = permissions.length;
        if (results.length < size) {
            size = results.length;
        }
        Iterator> 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
     *
     * 在Android M(Android 6.0,API Level 23)之前对设备的请求权限
     *授权或拒绝工作直接根据许可状态
     * *
     * @ param活动来检查权限
     * @ param权限名称
     * @ param操作回调工作对象,包含我们要做的事情
     *权限检查
     *
     *
     *  TJ:这个就是在6.0 一下的兼容了;默认权限就不用申请了
     */
    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
     *
     *
     *
     *
     * *过滤权限列表:
     *如果未获得许可,将其添加到结果列表
    如果获得了许可,那么就做授予的工作,不要将其添加到结果列表中
     * *
     * @ param活动来检查权限
     * @ param权限所有权限名称
     * @ param操作回调工作对象,包含我们要做的事情
     *权限检查
     * @返回未授予的权限名称列表
     *
     * TJ:很简单 ;一个过滤功能(查询)权限的列表;当然是在清单文件中查。
     */
    @NonNull
    private List getPermissionsListToRequest(@NonNull Activity activity,
                                                     @NonNull String[] permissions,
                                                     @Nullable PermissionsResultAction action) {
        List 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.java 类
这个类就不占内容了:就是一个回调 类使用。

OK 到这里基本上就介绍完了;下面我们看下具体的使用情况:
案例中的主类:MainActivity.java类 ;


public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = MainActivity.class.getSimpleName();
    private static final String PATH = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + "/test.txt";
    private TextView textView;

    @SuppressLint("InlinedApi")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Requesting all the permissions in the manifest
        //TJ:下面的注释 的操作是 一次性获取Mainfest.xml 清单中的所有权限的申请
        PermissionsManager.getInstance().requestAllManifestPermissionsIfNecessary(this, new PermissionsResultAction() {
            @Override
            public void onGranted() {
                Toast.makeText(MainActivity.this, R.string.message_granted, Toast.LENGTH_SHORT).show();
                writeToStorage("Hello, World!");
                readFromStorage();
            }

            @Override
            public void onDenied(String permission) {
                String message = String.format(Locale.getDefault(), getString(R.string.message_denied), permission);
                Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
            }
        });

        boolean hasPermissiona = PermissionsManager.getInstance().hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
        Log.d(TAG, "Has " + Manifest.permission.READ_EXTERNAL_STORAGE + " permission: " + hasPermissiona);

        Button writeStorage = (Button) findViewById(R.id.button_write_storage);
//        Button readStorage = (Button) findViewById(R.id.button_read_storage);
//        Button readContacts = (Button) findViewById(R.id.button_read_contacts);
//        Button getLocation = (Button) findViewById(R.id.button_get_location);

        this.textView = (TextView) findViewById(R.id.text);

        writeStorage.setOnClickListener(this);
//        readStorage.setOnClickListener(this);
//        readContacts.setOnClickListener(this);
//        getLocation.setOnClickListener(this);
    }

    /**
     * Requires Permission: Manifest.permission.WRITE_EXTERNAL_STORAGE
     */
    private void writeToStorage(String text) {
        File file = new File(PATH);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            outputStream.write(text.getBytes());
            this.textView.setText(String.format(Locale.getDefault(), getString(R.string.text_write), text));
        } catch (IOException e) {
            Log.e(TAG, "Unable to write to storage", e);
            this.textView.setText(R.string.text_failure_write);
        } finally {
            close(outputStream);
        }
    }

    /**
     * Requires Permission: Manifest.permission.READ_EXTERNAL_STORAGE
     */
    private void readFromStorage() {
        File file = new File(PATH);
        BufferedReader inputStream = null;
        FileInputStream input = null;
        try {
            input = new FileInputStream(file);
            inputStream = new BufferedReader(new InputStreamReader(input));
            String test = inputStream.readLine();
            this.textView.setText(String.format(Locale.getDefault(), getString(R.string.text_read), test));
        } catch (IOException e) {
            Log.e(TAG, "Unable to read from storage", e);
            this.textView.setText(R.string.text_failure_read);
        } finally {
            close(input);
            close(inputStream);
        }
    }

    //TJ:不可或缺:操作PermissionsManager授予您的应用程序权限的所有更改:也就是 权限申请请求后 更新应用的使用权限。
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        Log.i(TAG, "Activity-onRequestPermissionsResult() PermissionsManager.notifyPermissionsChange()");
        PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);
    }

    @SuppressLint("InlinedApi")
    @Override
    public void onClick(View v) {
        //TJ:下面是单个权限申请:用到的时候 执行操作申请权限
        switch (v.getId()) {
            case R.id.button_write_storage:
                PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, new PermissionsResultAction() {

                            @Override
                            public void onGranted() {
                                Log.i(TAG, "onGranted: Write Storage");
                                writeToStorage("Hello, World!");
                            }

                            @Override
                            public void onDenied(String permission) {
                                Log.i(TAG, "onDenied: Write Storage: " + permission);
                                String message = String.format(Locale.getDefault(), getString(R.string.message_denied), permission);
                                Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
                            }
                        }
                );
                break;


        }
    }

    private static void close(@Nullable Closeable closeable) {
        if (closeable == null) {
            return;
        }
        try {
            closeable.close();
        } catch (IOException ignored) {
        }
    }


}

代码做了部分简化 ;基本操作都很清晰。
OK 我们通过查看 发现:几个重要的部分:
单个权限申请例如:WRITE_EXTERNAL_STORAGE

 PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, new PermissionsResultAction() {

                            @Override
                            public void onGranted() {
                                Log.i(TAG, "onGranted: Write Storage");
                                writeToStorage("Hello, World!");
                            }

                            @Override
                            public void onDenied(String permission) {
                                Log.i(TAG, "onDenied: Write Storage: " + permission);
                                String message = String.format(Locale.getDefault(), getString(R.string.message_denied), permission);
                                Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
                            }
                        }
                );

申请清单所有权限:

PermissionsManager.getInstance().requestAllManifestPermissionsIfNecessary(this, new PermissionsResultAction() {
            @Override
            public void onGranted() {
                Toast.makeText(MainActivity.this, R.string.message_granted, Toast.LENGTH_SHORT).show();
                writeToStorage("Hello, World!");
                readFromStorage();
            }

            @Override
            public void onDenied(String permission) {
                String message = String.format(Locale.getDefault(), getString(R.string.message_denied), permission);
                Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
            }
        });

最后都要执行回调:

@Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        Log.i(TAG, "Activity-onRequestPermissionsResult() PermissionsManager.notifyPermissionsChange()");
        PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);
    }

OK 到这里就没有了; 集成很简单;使用很轻巧。 愿和大家共同学习进步。

你可能感兴趣的:(库使用解析)