美文网首页Android技术知识Android知识
提取RxPermissions核心思想, 搭建自己的权限请求框架

提取RxPermissions核心思想, 搭建自己的权限请求框架

作者: SharryChoo | 来源:发表于2018-02-03 00:11 被阅读188次

封装目的

有的项目中不需要使用 RxJava 异步事件流相关, 只需要一个好用灵活的权限请求框架, 而 RxPermissions 其内部使用的方式就比较精妙, 让我产生了把它内部精华部分提取出来的动力

使用方式

搭配上 Kotlin 的语法糖, 可以看到写起来非常的干练和舒服

 PermissionsManager.getManager(this)
                .request(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .execute {
                    if (it) {
                        Toast.makeText(this, "Granted", Toast.LENGTH_SHORT).show()
                    } else {
                        Toast.makeText(this, "Denial", Toast.LENGTH_SHORT).show()
                    }
                }

搭建过程

  1. 依赖:
    • Fragment.requestPermissions 方法, 可以用来发起对权限的请求
    • Fragment.onRequestPermissionsResult 方法, 可以监听权限请求的回调
  2. 思路:
    • 发起权限请求的时候, 根据传入的 context, 找到对应的 Activity
    • 先判断有没有添加过
      • 若未添加过: 向这个 Activity 中添加一个我们封装好的用于权限请求的 Fragment
      • 已经添加过: 通过 Activity.getFragmentManager().findFragmentByTag(TAG) 获取之前添加过的实例
    • 通过这个 Fragment 来发起权限请求
    • 请求失败后, 弹出 Dialog, 给用户跳转到设置界面去开启权限的选项

实现代码

/**
 * Created by FrankChoo on 2018/1/5.
 * Email: frankchoochina@gmail.com
 * Version:1.1
 * Description: 权限请求管理类, 实现思路来自 RxPermissions
 */
public class PermissionsManager {

    public static final String TAG = "PermissionsManager";
    private PermissionsFragment mPermissionsFragment;
    private String[] mPermissions;

    public static PermissionsManager getManager(Context context) {
        if (context instanceof Activity) {
            Activity activity = (Activity) context;
            return new PermissionsManager(activity);
        } else {
            throw new IllegalArgumentException("PermissionsManager.getManager/Context can not cast to Activity");
        }
    }

    private PermissionsManager(Activity activity) {
        mPermissionsFragment = getPermissionsFragment(activity);
        Log.e("TAG", mPermissionsFragment.toString());
    }

    /**
     * 添加需要请求的权限
     */
    public PermissionsManager request(final String... permissions) {
        ensure(permissions);
        mPermissions = permissions;
        return this;
    }

    /**
     * 执行权限请求
     */
    public void execute(PermissionsCallback permissionsCallback) {
        if (permissionsCallback == null) {
            throw new IllegalArgumentException("PermissionsManager.execute/PermissionsCallback must not be null");
        }
        requestImplementation(mPermissions, permissionsCallback);
    }

    /**
     * 判断权限是否被授权
     */
    public boolean isGranted(String permission) {
        return !isMarshmallow() || mPermissionsFragment.isGranted(permission);
    }

    /**
     * 判断权限是否被撤回
     * <p>
     * Always false if SDK &lt; 23.
     */
    @SuppressWarnings("WeakerAccess")
    public boolean isRevoked(String permission) {
        return isMarshmallow() && mPermissionsFragment.isRevoked(permission);
    }

    /**
     * 获取 PermissionsFragment
     */
    private PermissionsFragment getPermissionsFragment(Activity activity) {
        PermissionsFragment permissionsFragment = findPermissionsFragment(activity);
        if (permissionsFragment == null) {
            permissionsFragment = PermissionsFragment.getInstance();
            FragmentManager fragmentManager = activity.getFragmentManager();
            fragmentManager.beginTransaction().add(permissionsFragment, TAG).commitAllowingStateLoss();
            fragmentManager.executePendingTransactions();
        }
        return permissionsFragment;
    }

    /**
     * 在 Activity 中通过 TAG 去寻找我们添加的 Fragment
     */
    private PermissionsFragment findPermissionsFragment(Activity activity) {
        return (PermissionsFragment) activity.getFragmentManager().findFragmentByTag(TAG);
    }


    /**
     * 验证发起请求的权限是否有效
     */
    private void ensure(String[] permissions) {
        if (permissions == null || permissions.length == 0) {
            throw new IllegalArgumentException("PermissionsManager.request/requestEach requires at least one input permission");
        }
    }

    /**
     * 执行权限请求
     *
     * @param permissions
     * @param callback
     */
    private void requestImplementation(String[] permissions, PermissionsCallback callback) {
        List<String> unrequestedPermissions = new ArrayList<>();
        for (String permission : permissions) {
            mPermissionsFragment.log("Requesting permission " + permission);
            if (isGranted(permission)) {
                // Already granted, or not Android M
                // Return a granted Permission object.
                continue;
            }
            if (isRevoked(permission)) {
                // Revoked by a policy, return a denied Permission object.
                continue;
            }
            unrequestedPermissions.add(permission);
        }
        if (!unrequestedPermissions.isEmpty()) {
            // 细节, toArray的时候指定了数组的长度
            String[] unrequestedPermissionsArray = unrequestedPermissions.toArray(new String[unrequestedPermissions.size()]);
            mPermissionsFragment.requestPermissions(unrequestedPermissionsArray, callback);
        } else {
            callback.onResult(true);
        }
    }

    private boolean isMarshmallow() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
    }
}
/**
 * Created by FrankChoo on 2018/1/5.
 * Email: frankchoochina@gmail.com
 * Version:1.1
 * Description: 执行权限请求的 Fragment
 */
public class PermissionsFragment extends Fragment {

    private static final int PERMISSIONS_REQUEST_CODE = 42;
    private PermissionsCallback mCallback;

    public static PermissionsFragment getInstance() {
        return new PermissionsFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @TargetApi(Build.VERSION_CODES.M)
    void requestPermissions(@NonNull String[] permissions, PermissionsCallback callback) {
        mCallback = callback;
        requestPermissions(permissions, PERMISSIONS_REQUEST_CODE);
    }

    @Override
    @TargetApi(Build.VERSION_CODES.M)
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode != PERMISSIONS_REQUEST_CODE) return;
        boolean isAllGranted = true;
        for (int i = 0, size = permissions.length; i < size; i++) {
            if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                log("onRequestPermissionsResult: " + permissions[i] + " is Granted");
            } else {
                log("onRequestPermissionsResult: " + permissions[i] + " is Denied");
                isAllGranted = false;
            }
        }
        if (isAllGranted) {
            mCallback.onResult(true);
        } else {
            showPermissionDeniedDialog();
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    boolean isGranted(String permission) {
        return getActivity().checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
    }

    @TargetApi(Build.VERSION_CODES.M)
    boolean isRevoked(String permission) {
        return getActivity().getPackageManager().isPermissionRevokedByPolicy(permission, getActivity().getPackageName());
    }

   @TargetApi(Build.VERSION_CODES.M)
    private void showPermissionDeniedDialog() {
        //启动当前App的系统设置界面
        AlertDialog dialog = new AlertDialog.Builder(getContext())
                .setTitle("帮助")
                .setMessage("当前应用缺少必要权限")
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mCallback.onResult(false);
                        dialog.dismiss();
                    }
                })
                .setPositiveButton("设置", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // Toast.makeText(getContext(), "设置成功后请重新请求该操作", Toast.LENGTH_SHORT).show();
                        // 启动当前App的系统设置界面
                        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                        intent.setData(Uri.parse("package:" + getContext().getPackageName()));
                        startActivityForResult(intent, REQUEST_CODE_SETTING);
                    }
                }).create();
        dialog.show();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode != REQUEST_CODE_SETTING) return;
        // 从设置页面回来时, 重新检测一次申请的权限是否都已经授权
        boolean isAllGranted = true;
        for (String permission : mPermissions) {
            if (!isGranted(permission)) {
                isAllGranted = false;
                break;
            }
        }
        mCallback.onResult(isAllGranted);
    }

    void log(String message) {
        Log.d(PermissionsManager.TAG, message);
    }
}
/**
 * Created by FrankChoo on 2018/1/5.
 * Email: frankchoochina@gmail.com
 * Description: 权限请求回调
 */
public interface PermissionsCallback {
    void onResult(boolean granted);
}

相关文章

网友评论

    本文标题:提取RxPermissions核心思想, 搭建自己的权限请求框架

    本文链接:https://www.haomeiwen.com/subject/smeyzxtx.html