妙用Fragment轻松实现Android动态权限申请库

Android M之后,有的在manifest定位的权限需要在运行时动态申请才可以使用,这方面的详细信息可以参考官方文档:https://developer.android.com/training/permissions/requesting?hl=zh-cn,一般是需要申请权限时,需要检查是否已经有权限,如果没有则申请,主要使用到如下步骤:
首先使用ContextCompat.checkSelfPermission检查,第一参数是context,第二个是要检查的权限名称,然后用ActivityCompat.requestPermissions去申请权限,第一个参数是context,第二个是要申请的权限,第三个是这次申请的requestCode

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
                Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {

        // Show an expanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.

    } else {

        // No explanation needed, we can request the permission.

        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}

在调用ActivityCompat.requestPermissions申请后,系统会弹出一个提示框提示用户是否允许,当用户点了允许或拒绝时会回调到activity的onRequestPermissionsResult函数:

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

第一个参数是申请时的requestCode,第二个是申请的权限,第三个是申请权限的结果.
以上是官方的教程,如果按这个教程去做的话,你需要在每个activity都写一遍onRequestPermissionsResult回调的处理,这对于代码的维护来说是非常不好的,也干扰了正常的业务逻辑代码。那提取一个权限申请库就非常有必要了,要实现申请功能并不难,难点在于,怎么让申请库的代码不跟原有的activity代码耦合在一起呢,下面就介绍一种解耦的方法:
方法一:
自己建一个用来权限申请没有界面的activity,在申请是启动这个activity去申请,然后在这个activty里的回调来接收结果,这种方法可以做到解耦,但是需要在manifest里定义这个activity,AndPermission就是这样实现的,这样个人感觉还不够极致,那进一步的方法是方法
方法二:
这种方法是不使用activity了,而是使用Fragment,因为Fragment也有activity一样的申请权限函数和回调,这种就不用在manifest中定义什么了,RxPermission就是这样实现的
这里不去具体讲实现的代码了,这里是想分享一种跟生命周期有关的逻辑怎么跟原有代码逻辑解耦方法,上面两种其实都是可以达到目的的方法,这种方法在一些开源库中其实都有,在Glide中,就有使用Fragment在onDestroy时做资源释放的,代码:

// RequestmanagerRetriever.java
private RequestManager fragmentGet(@NonNull Context context,
    @NonNull android.app.FragmentManager fm,
    @Nullable android.app.Fragment parentHint,
    boolean isParentVisible) {
  RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
  RequestManager requestManager = current.getRequestManager();
  if (requestManager == null) {
    // TODO(b/27524013): Factor out this Glide.get() call.
    Glide glide = Glide.get(context);
    requestManager =
        factory.build(
            glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
    current.setRequestManager(requestManager);
  }
  return requestManager;
}

// RequestManagerFragment.java
@NonNull
ActivityFragmentLifecycle getGlideLifecycle() {
  return lifecycle;
}
@Override
public void onStop() {
  super.onStop();
  lifecycle.onStop();
}

// RequestManagerFragment.java
  @Override
  public void onDestroy() {
    super.onDestroy();
    lifecycle.onDestroy();
    unregisterFragmentWithRoot();
  }

Glide在Fragment的onDestory会调用Glide的lifecycle的onDestroy,然后做资源的释放,这个使用的过程不会有任何干扰,开发者只管放心地使用,那用这种方式使用的权限申请库也是一样,开发者不用关心这些细节,只要简单的调用接口就好,下面实现的申请库使用示例:

 PermissionChecker.with(this)
        .permission(Manifest.permission.WRITE_EXTERNAL_STORAGE, "存储权限不可用", "XXX需要存储权限以正常工作,是否允许?")
        .permission(Manifest.permission.ACCESS_COARSE_LOCATION, "定位权限不可用", "XXX需要定位权限以正常工作,是否允许?")
        .onAllow(new PermissionChecker.AllowCallback() {
                    @Override
                    public void onAllow(String permission) {
                        Toast.makeText(MainActivity.this, "allow", Toast.LENGTH_SHORT).show();
                    }
        }).onDeny(new PermissionChecker.DenyCallback() {
            @Override
            public void onDeny(String permission) {
                Toast.makeText(MainActivity.this, "deny", Toast.LENGTH_SHORT).show();
        }
    }).build().check();

代码在github:https://github.com/Cmdmac/PermissionChecker

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 中,有些权限需要动态申请,例如访问摄像头、存储等权限。以下是动态申请权限的步骤: 1. 在 AndroidManifest.xml 文件中声明需要申请权限。 2. 在 Activity 或 Fragment 中发起权限请求,通过调用 `ActivityCompat.requestPermissions()` 方法发起权限请求,该方法需要传入权限数组和请求码。 3. 在 `onRequestPermissionsResult()` 方法中处理权限请求结果,根据用户授权或拒绝的结果做出相应的处理。 下面是一个示例代码: ```java // 检查权限是否已经被授权 if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { // 如果没有授权,则发起权限请求 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUEST_CAMERA); } else { // 如果已经授权,则执行相关操作 openCamera(); } // 处理权限请求结果 @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_CAMERA: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 用户授权,执行相关操作 openCamera(); } else { // 用户拒绝授权,提示需要权限才能继续使用该功能 Toast.makeText(this, "需要摄像头权限才能使用该功能", Toast.LENGTH_SHORT).show(); } break; } } ``` 在上述示例中,如果用户没有授权访问摄像头,就会发起一个摄像头权限请求,请求码为 `MY_PERMISSIONS_REQUEST_CAMERA`,请求结果将在 `onRequestPermissionsResult()` 方法中处理。如果用户授权,则执行 `openCamera()` 方法打开摄像头,否则提示用户需要该权限才能继续使用该功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值