Android开发之深度项目设计探索(三)

简介: 本文是《Android开发之深度项目设计探索》系列的第三篇,主要介绍的是 基于最新RxPermissions 类库的使用及源码分析,本系列历史文章:《Android开发之深度项目设计探索(一)》《Android开发之深度项目设计探索(二)》Permission,这个单词翻译过来的意思有:允许、许可、权限。

本文是《Android开发之深度项目设计探索》系列的第三篇,主要介绍的是 基于最新RxPermissions 类库的使用及源码分析,本系列历史文章:
《Android开发之深度项目设计探索(一)》
《Android开发之深度项目设计探索(二)》
Permission,这个单词翻译过来的意思有:允许、许可、权限。我们Android开发亲切的将其称为权限。

权限是一种安全机制。Android权限机制主要用于:限制应用程序内部某些具有限制特性的功能使用以及应用程序之间的组件访问。

在Android系统6.0版本(也就是 SdkVersion = 23)之前,权限的声明仅需要在清单配置文件中,通过标签uses-permission来声明应用,也就意味所需要的权限,如:

    <uses-permission android:name="android.permission.CAMERA"/>

这行配置代码的意思意味着该应用允许使用CAMERA(照相机)权限;

由于时代的发展以及各种因素,谷歌Android技术团队出于安全角度这一原则设计考虑,在Android系统6.0版本开始,之后的版本提出了一些新概念,整理下来有以下几点:
概念一:权限分为两种、一种是普通权限;还有一种是危险权限
概念二:普通权限,直接在清单文件中配置声明即可
概念三:危险权限,谷歌觉得部分权限涉及到用户的隐私,因此必须明确告知用户应用需要那些权限,但是这样的危险权限需要用户手动授权

既然谷歌在新版本给我们带来了新概念和需要解决的问题,那么就需要解决这个权限问题:

  • 解决方式一:暂时不适配Android6.0系统版本,也就是将targetSdkVersion降到23以上(这种法子算曲线救国)
  • 解决方式二:直接适配危险权限,主动告知用户打开权限

那么这篇文章介绍的 RxPermissions-官方文档,这是一款基于Rxjava2的运行时权限解决方案,

  • 这个库的minSdkVersion 最低不能低于11,也就是 "use this library your minSdkVersion must be >= 11"

  • 在gradle导入最新版本的RxPermissions依赖:" implementation 'com.github.tbruyelle:rxpermissions:0.10.2' "

集成和使用步骤如下:

  • 首先:创建RxPermissions实例:
 //这里的this就是Activity or Fragment instance
 RxPermissions rxPermissions = new RxPermissions(this);
  • 接着:代码使用,需搭配Rxjava2使用,写法如下:
A:获取单个权限

        RxPermissions rxPermissions = new RxPermissions(this);

//      申请单个权限
        rxPermissions.request(Manifest.permission.CAMERA).subscribe(new Consumer<Boolean>() {
            @Override
            public void accept(Boolean aBoolean) throws Exception {
                if (aBoolean == true){
//              用户已经同意该权限
                    Log.i(TAG, "accept: CAMERA 权限成功");
                }else {
//              用户拒绝权限
                    Log.i(TAG, "accept: CAMERA 权限失败");
                }
            }
        });
B:获取多个权限

获取多个权限方式有两种写法:

  • 写法一:
//      用户同时申请多个权限,方式一:
//      如果用户全部申请成功,才会返回true
//      如果用户有一个权限拒绝申请,那么就会返回失败
        rxPermissions.requestEach(
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_CALENDAR,
                Manifest.permission.READ_PHONE_STATE).
                subscribe(new Consumer<Permission>() {
            @Override
            public void accept(Permission permission) throws Exception {
                if (permission.granted) {
                    // 用户已经同意该权限
                    Log.d(TAG, permission.name + "用户授予权限");
                } else if (permission.shouldShowRequestPermissionRationale) {
                    // 用户拒绝了该权限,没有选中『不再询问』(Never ask again),那么下次再次启动时,还会提示请求权限的对话框
                    Log.d(TAG, permission.name + "用户拒绝权限——下次启动可以继续申请");
                } else {
                    // !!!注意!!!
                    // 用户拒绝了该权限,并且选中了『不再询问』
                    // 需要去 APP设置 里面去打开对应的申请权限
                    Log.d(TAG, permission.name + "用户拒绝权限——勾选了不在询问——提示用户后续去手动申请");
                }
            }
        });

  • 写法二:
//      用户同时申请多个权限,方式二:
//      对应每个权限申请的操作
//      思考:
//      我们可以在应用启动之前也打开获取权限,然后记录每个权限是否申请成功,记录的方式可以通过sp存储状态
//      在需要权限的时候,首先判断SP存储的状态是否为权限授权成功,如果没有授权成功,那么就再次请求授权
        rxPermissions.requestEachCombined(
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_CALENDAR,
                Manifest.permission.READ_PHONE_STATE).
                subscribe(new Consumer<Permission>() {
            @Override
            public void accept(Permission permission) throws Exception {
//              判断具体的对应权限

                if (permission.name.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    if (permission.granted){
                        Log.i(TAG, "WRITE_EXTERNAL_STORAGE_accept: 权限申请成功");
                    }else {
                        Log.i(TAG, "WRITE_EXTERNAL_STORAGE_accept: 权限授权失败");
                    }
                }

                if (permission.name.equals(Manifest.permission.READ_PHONE_STATE)) {
                    if (permission.granted){
                        Log.i(TAG, "READ_PHONE_STATE: 权限申请成功");
                    }else {
                        Log.i(TAG, "READ_PHONE_STATE: 权限授权失败");
                    }
                }
            }
        });

嗯,没错,基本上,这款框架的使用就已经介绍完了,是不是很简单优雅。
但是有一些细节我们需要注意,如该库的作者不建议我们在 onResume()这个生命周期里面进行申请权限, RxPermissions-官方文档 也给了详细说明,

下面是源码解读

Rxpermissions源码分析:
使用一:

我们知道,Rxpermissions使用的第一步是在Activity中创建RxPermissions这个实例化对象。实际上,RxPermission采用的方式是利用了一个隐形的Fragment来请求权限,然后在回调中用RxJava进行数据的组装和转化,最后变成了布尔类型的数据回调回来。这个隐形的Fragment,就是类库中的RxPermissionsFragment

public class RxPermissionsFragment extends Fragment {

    private static final int PERMISSIONS_REQUEST_CODE = 42;

    // Contains all the current permission requests.
    // Once granted or denied, they are removed from it.
    private Map<String, PublishSubject<Permission>> mSubjects = new HashMap<>();
    private boolean mLogging;

    public RxPermissionsFragment() {
    }

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

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

    @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[] shouldShowRequestPermissionRationale = new boolean[permissions.length];

        for (int i = 0; i < permissions.length; i++) {
            shouldShowRequestPermissionRationale[i] = shouldShowRequestPermissionRationale(permissions[i]);
        }

        onRequestPermissionsResult(permissions, grantResults, shouldShowRequestPermissionRationale);
    }

    void onRequestPermissionsResult(String permissions[], int[] grantResults, boolean[] shouldShowRequestPermissionRationale) {
        for (int i = 0, size = permissions.length; i < size; i++) {
            log("onRequestPermissionsResult  " + permissions[i]);
            // Find the corresponding subject
            PublishSubject<Permission> subject = mSubjects.get(permissions[i]);
            if (subject == null) {
                // No subject found
                Log.e(RxPermissions.TAG, "RxPermissions.onRequestPermissionsResult invoked but didn't find the corresponding permission request.");
                return;
            }
            mSubjects.remove(permissions[i]);
            boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
            subject.onNext(new Permission(permissions[i], granted, shouldShowRequestPermissionRationale[i]));
            subject.onComplete();
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    boolean isGranted(String permission) {
        final FragmentActivity fragmentActivity = getActivity();
        if (fragmentActivity == null) {
            throw new IllegalStateException("This fragment must be attached to an activity.");
        }
        return fragmentActivity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
    }

    @TargetApi(Build.VERSION_CODES.M)
    boolean isRevoked(String permission) {
        final FragmentActivity fragmentActivity = getActivity();
        if (fragmentActivity == null) {
            throw new IllegalStateException("This fragment must be attached to an activity.");
        }
        return fragmentActivity.getPackageManager().isPermissionRevokedByPolicy(permission, getActivity().getPackageName());
    }

    public void setLogging(boolean logging) {
        mLogging = logging;
    }

    public PublishSubject<Permission> getSubjectByPermission(@NonNull String permission) {
        return mSubjects.get(permission);
    }

    public boolean containsByPermission(@NonNull String permission) {
        return mSubjects.containsKey(permission);
    }

    public void setSubjectForPermission(@NonNull String permission, @NonNull PublishSubject<Permission> subject) {
        mSubjects.put(permission, subject);
    }

    void log(String message) {
        if (mLogging) {
            Log.d(RxPermissions.TAG, message);
        }
    }

}

可以看到,这个类继承了Fragment。然后在onCreate中并没有创建具体的UI布局,我们知道。Fragment具有属性retainInstance,默认值为false。 当设备旋转时,fragment会随托管activity一起销毁并重建。解决办法是:调用setRetainInstance(true)方法可保留fragment不会重新创建(例如旋转屏幕)

你可能会问,那这个隐形的Fragment又是在那里创建的?答案:创建的时机,是在创建RxPermissions的对象中,顺带创建了这个实例对象(通过构造方法实现):下面是Rxpermissions这个类的构造方法以及部分函数源码:

public class RxPermissions {

    static final String TAG = RxPermissions.class.getSimpleName();
    static final Object TRIGGER = new Object();

    @VisibleForTesting
    Lazy<RxPermissionsFragment> mRxPermissionsFragment;

    public RxPermissions(@NonNull final FragmentActivity activity) {
        mRxPermissionsFragment = getLazySingleton(activity.getSupportFragmentManager());
    }

    public RxPermissions(@NonNull final Fragment fragment) {
        mRxPermissionsFragment = getLazySingleton(fragment.getChildFragmentManager());
    }

    @NonNull
    private Lazy<RxPermissionsFragment> getLazySingleton(@NonNull final FragmentManager fragmentManager) {
        return new Lazy<RxPermissionsFragment>() {

            private RxPermissionsFragment rxPermissionsFragment;

            @Override
            public synchronized RxPermissionsFragment get() {
                if (rxPermissionsFragment == null) {
                    rxPermissionsFragment = getRxPermissionsFragment(fragmentManager);
                }
                return rxPermissionsFragment;
            }

        };
    }

    private RxPermissionsFragment getRxPermissionsFragment(@NonNull final FragmentManager fragmentManager) {
        RxPermissionsFragment rxPermissionsFragment = findRxPermissionsFragment(fragmentManager);
        boolean isNewInstance = rxPermissionsFragment == null;
        if (isNewInstance) {
            rxPermissionsFragment = new RxPermissionsFragment();
            fragmentManager
                    .beginTransaction()
                    .add(rxPermissionsFragment, TAG)
                    .commitNow();
        }
        return rxPermissionsFragment;
    }
//.............省略部分源码................
}

这个隐形的Fragment很重要,因为权限的申请与申请结果的回调都是在Fragment中完成的。基于此,开发人员才不需要为申请结果重写回调方法。

使用二:

接着,是Rxpermissions基本使用的代码,也就是rxPermissions.request......,对应的源码如下:


    /**
     * Request permissions immediately, <b>must be invoked during initialization phase
     * of your application</b>.
     */
    @SuppressWarnings({"WeakerAccess", "unused"})
    public Observable<Boolean> request(final String... permissions) {
        return Observable.just(TRIGGER).compose(ensure(permissions));
    }

    /**
     * Request permissions immediately, <b>must be invoked during initialization phase
     * of your application</b>.
     */
    @SuppressWarnings({"WeakerAccess", "unused"})
    public Observable<Permission> requestEach(final String... permissions) {
        return Observable.just(TRIGGER).compose(ensureEach(permissions));
    }

    /**
     * Request permissions immediately, <b>must be invoked during initialization phase
     * of your application</b>.
     */
    public Observable<Permission> requestEachCombined(final String... permissions) {
        return Observable.just(TRIGGER).compose(ensureEachCombined(permissions));
    }

从中可以看到,上面使用的三种写法,最终是调到了

Observable.just(TRIGGER).compose(ensureEach(permissions));
  • 步骤一:
    这里的 Just 操作符,简单点理解就是可以将某个对象转化为Observable对象。Just操作符,是RxJava中非常快捷的创建Observable对象的方法。如果通过just操作符创建了一个Observable,继续使用subscriber订阅则会依次调用其onNext()和onCompleted()方法。这里的TRIGGER,源码里面就是一个Object对象。
    static final Object TRIGGER = new Object();

通过源码可以看到,根据just操作符创建完Observable对象之后紧接着调用了compose()方法。
compose()操作符主要是将一个Observable对象(具体的数据类型)转换成另一个Observable(对应的数据类型)对象,我们发现此方法最终调用的是ensure(permissions)这个方法

  • 步骤二:
    ensure(permissions)这个方法的源码如下:
    public <T> ObservableTransformer<T, Boolean> ensure(final String... permissions) {

        ObservableTransformer<T, Boolean> observableTransformer = new ObservableTransformer<T, Boolean>() {
            @Override
            public ObservableSource<Boolean> apply(Observable<T> o) {

                Observable<Boolean> booleanObservable = request(o, permissions)
                        // Transform Observable<Permission> to Observable<Boolean>
                        .buffer(permissions.length)
                        .flatMap(new Function<List<Permission>, ObservableSource<Boolean>>() {
                            @Override
                            public ObservableSource<Boolean> apply(List<Permission> permissions) {

                                if (permissions.isEmpty()) {
                                    // Occurs during orientation change, when the subject receives onComplete.
                                    // In that case we don't want to propagate that empty list to the
                                    // subscriber, only the onComplete.
                                    return Observable.empty();
                                }
                                // Return true if all permissions are granted.
                                for (Permission p : permissions) {
                                    if (!p.granted) {
                                        return Observable.just(false);
                                    }
                                }
                                return Observable.just(true);
                            }
                        });
                return booleanObservable;
            }
        };

        return observableTransformer;
    }

这个buffer()的操作符作用是什么呢,它的作用是为了将一个序列的Observable<Permission>对象转换成Observable<List<Permission>>对象,

抛开Rxjava2常规的操作符除外,首先看下这段来自RxPermissions类库部分源码提供的自定义方法有:request(o, permissions);源码还自定义了一个类:Permission,其中p.granted这种写法貌似就是类名.成员变量的操作,那我们就先看一眼Permission这个最基本的Java类
Permission源码如下:

public class Permission {
    public final String name;
    public final boolean granted;
    public final boolean shouldShowRequestPermissionRationale;

    public Permission(String name, boolean granted) {
        this(name, granted, false);
    }

    public Permission(String name, boolean granted, boolean shouldShowRequestPermissionRationale) {
        this.name = name;
        this.granted = granted;
        this.shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale;
    }

    public Permission(List<Permission> permissions) {
        name = combineName(permissions);
        granted = combineGranted(permissions);
        shouldShowRequestPermissionRationale = combineShouldShowRequestPermissionRationale(permissions);
    }

    @Override
    @SuppressWarnings("SimplifiableIfStatement")
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        final Permission that = (Permission) o;

        if (granted != that.granted) return false;
        if (shouldShowRequestPermissionRationale != that.shouldShowRequestPermissionRationale)
            return false;
        return name.equals(that.name);
    }

    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + (granted ? 1 : 0);
        result = 31 * result + (shouldShowRequestPermissionRationale ? 1 : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Permission{" +
                "name='" + name + '\'' +
                ", granted=" + granted +
                ", shouldShowRequestPermissionRationale=" + shouldShowRequestPermissionRationale +
                '}';
    }

    private String combineName(List<Permission> permissions) {
        return Observable.fromIterable(permissions)
                .map(new Function<Permission, String>() {
                    @Override
                    public String apply(Permission permission) throws Exception {
                        return permission.name;
                    }
                }).collectInto(new StringBuilder(), new BiConsumer<StringBuilder, String>() {
                    @Override
                    public void accept(StringBuilder s, String s2) throws Exception {
                        if (s.length() == 0) {
                            s.append(s2);
                        } else {
                            s.append(", ").append(s2);
                        }
                    }
                }).blockingGet().toString();
    }

    private Boolean combineGranted(List<Permission> permissions) {
        return Observable.fromIterable(permissions)
                .all(new Predicate<Permission>() {
                    @Override
                    public boolean test(Permission permission) throws Exception {
                        return permission.granted;
                    }
                }).blockingGet();
    }

    private Boolean combineShouldShowRequestPermissionRationale(List<Permission> permissions) {
        return Observable.fromIterable(permissions)
                .any(new Predicate<Permission>() {
                    @Override
                    public boolean test(Permission permission) throws Exception {
                        return permission.shouldShowRequestPermissionRationale;
                    }
                }).blockingGet();
    }
}

这个类我们先放在这里,在看一眼类库自定义的request(o, permissions)这个方法的源码:

    private Observable<Permission> request(final Observable<?> trigger, final String... permissions) {
        if (permissions == null || permissions.length == 0) {
            throw new IllegalArgumentException("RxPermissions.request/requestEach " +
                    "requires at least one input permission");
        }
        Observable<Permission> permissionObservable =
                oneOf(trigger, pending(permissions))
                        .flatMap(new Function<Object, Observable<Permission>>() {
                    @Override
                    public Observable<Permission> apply(Object o) {
                        return requestImplementation(permissions);
                    }
                });

        return permissionObservable;

    }

可以看到这个方法返回的对象是一个Observable< Permission >,内部逻辑首先判断permissions 是否为null,长度是否大于0,如果满足其中一个条件就抛异常;如果permissions 不为null,长度且大于0,在调用oneOf方法和pending( )方法来创建合并Observable对象。其中,oneOf()和pending( )方法的函数如下:


    private Observable<?> oneOf(Observable<?> trigger, Observable<?> pending) {
        if (trigger == null) {
            return Observable.just(TRIGGER);
        }
        return Observable.merge(trigger, pending);
    }
    
    private Observable<?> pending(final String... permissions) {
        for (String p : permissions) {
            if (!mRxPermissionsFragment.get().containsByPermission(p)) {
                return Observable.empty();
            }
        }
        return Observable.just(TRIGGER);
    }

pending(final String... permissions)这个函数的主要功能有:

  • 首先循环遍历,查询该权限是否已经在申请过了
  • 如果列表中有一个权限没有在RxPermissionsFragment的HashMap集合中保存,
    就返回Observeble.empty(),返回的这个Observable对象会调用onComplete()方法,所以并不会进入flatMap

oneOf(Observable<?> trigger, Observable<?> pending)这个函数的主要是:

  • 首先判断trigger对象是否为null,如果为空,则通过Just操作符创建一个Observable
  • 最后返回合并的Observable对象。

我们知道,request(o, permissions)最终是调用了requestImplementation(permissions);这个方法,下面就看下requestImplementation(permissions);方法的内部源码:

  @TargetApi(Build.VERSION_CODES.M)
    private Observable<Permission> requestImplementation(final String... permissions) {

        List<Observable<Permission>> list = new ArrayList<>(permissions.length);

        List<String> unrequestedPermissions = new ArrayList<>();

        // In case of multiple permissions, we create an Observable for each of them.
        // At the end, the observables are combined to have a unique response.
        for (String permission : permissions) {
            mRxPermissionsFragment.get().log("Requesting permission " + permission);
            if (isGranted(permission)) {
                // Already granted, or not Android M
                // Return a granted Permission object.
                list.add(Observable.just(new Permission(permission, true, false)));
                continue;
            }

            if (isRevoked(permission)) {
                // Revoked by a policy, return a denied Permission object.
                list.add(Observable.just(new Permission(permission, false, false)));
                continue;
            }

            PublishSubject<Permission> subject = mRxPermissionsFragment.get().getSubjectByPermission(permission);
            // Create a new subject if not exists
            if (subject == null) {
                unrequestedPermissions.add(permission);
                subject = PublishSubject.create();
                mRxPermissionsFragment.get().setSubjectForPermission(permission, subject);
            }

            list.add(subject);
        }

        if (!unrequestedPermissions.isEmpty()) {
            String[] unrequestedPermissionsArray = unrequestedPermissions.toArray(new String[unrequestedPermissions.size()]);
            requestPermissionsFromFragment(unrequestedPermissionsArray);
        }
        return Observable.concat(Observable.fromIterable(list));
    }
这段代码的主要意思有以下几个方面(按照顺序):

A:创建第一个集合(也就是源码的List<Observable<Permission>> list)保存已经申请的权限
B:创建第二个集合(也就是List<String> unrequestedPermissions)用来保存没有请求成功的权限
C:对具体申请的权限列表进行循环遍历:

  • 如果权限已经申请过了,则直接保存到集合中(if (isGranted(permission)) {...}
  • 如果权限被撤销,则将其作为申请被拒绝的权限保存到集合中:if (isRevoked(permission)) {...}

D:在RxPermissionsFragment中,寻找是否已经存在对应的权限,如果不存在(subject == null),则创建PublishSubject对象,将其添加到unrequestedPermissions集合中,然后将subject对象保存在第一个集合中,
E:如果有未申请的权限,则进行权限的申请操作,也就是requestPermissionsFromFragment(unrequestedPermissionsArray);这个函数

F:利用第一个集合创建Observable对象,用concat操作符进行链接,最终返回一个Observable<Permission>对象

结论:
这个方法主要的操作就是,定义集合保存一次申请的所有权限。无论这个权限是已经申请,还是被撤销,还是未申请,最终都会保存到list这个集合中。在后续的操作中,才可以进行转换。

同时,定义集合用于保存未申请的权限,然后在循环结束之后进行未申请权限的申请。

因此,现在的关键就是requestPermissionsFromFragment(unrequestedPermissionsArray);这个函数,源码继续跟进:

   @TargetApi(Build.VERSION_CODES.M)
    void requestPermissionsFromFragment(String[] permissions) {
        mRxPermissionsFragment.get().log("requestPermissionsFromFragment " + TextUtils.join(", ", permissions));
        mRxPermissionsFragment.get().requestPermissions(permissions);
    }

继续跟进:

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

看到这里,最终是调用了requestPermissions(permissions, PERMISSIONS_REQUEST_CODE);,这个PERMISSIONS_REQUEST_CODE,的值是42,源码里面有。这个方法是Fragment提供的系统方法,那么回调的处理结果理所当然在RxPermissionsFragment中:

   @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[] shouldShowRequestPermissionRationale = new boolean[permissions.length];

        for (int i = 0; i < permissions.length; i++) {
            shouldShowRequestPermissionRationale[i] = shouldShowRequestPermissionRationale(permissions[i]);
        }

        onRequestPermissionsResult(permissions, grantResults, shouldShowRequestPermissionRationale);
    }

    void onRequestPermissionsResult(String permissions[], int[] grantResults, boolean[] shouldShowRequestPermissionRationale) {
        for (int i = 0, size = permissions.length; i < size; i++) {
            log("onRequestPermissionsResult  " + permissions[i]);
            // Find the corresponding subject
            PublishSubject<Permission> subject = mSubjects.get(permissions[i]);
            if (subject == null) {
                // No subject found
                Log.e(RxPermissions.TAG, "RxPermissions.onRequestPermissionsResult invoked but didn't find the corresponding permission request.");
                return;
            }
            mSubjects.remove(permissions[i]);
            boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
            subject.onNext(new Permission(permissions[i], granted, shouldShowRequestPermissionRationale[i]));
            subject.onComplete();
        }
    }

这段回调处理的源码意思主要有:
A:首先判断请求码,如果请求码不等于42,则直接返回
B:以权限列表的长度为size,创建一个boolean数组
C:循环遍历,看权限是否被永久拒绝了。这里会调用Fragment中的shouldShowRequestPermissionRationale()方法。这个方法如果权限申请成功会返回true;用户点击了不在提醒,且拒绝权限时,会返回false。
D:调用下面的重载方法

进入重载方法以后的操作有:
A:对权限列表进行循环操作。寻找相对应的:subject,也就是( PublishSubject<Permission> subject = mSubjects.get(permissions[i]);
B:如果没有对应的subject,则直接返回
C:如果有对应的subject,首先将集合中的permission的PublishSubject对象进行移除;接着判断是否申请成功;最后执行onNext( )返回相应的Permission对象

基本的源码分析就到这了。

评语:可以看到,RxPermissions这个库的主要逻辑就是在通过隐形的Fragment以及Rxjava2的操作符来进行实践的,通过合理搭配才让这个库使用起来比较方便。

如果这篇文章对你有帮助,希望各位看官留下宝贵的star,谢谢。

Ps:著作权归作者所有,转载请注明作者, 商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用,也希望大家尊重笔者的劳动成果。

相关文章
|
7天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
9天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异和挑战
【10月更文挑战第37天】在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统扮演着主角。它们各自拥有独特的特性、优势以及面临的开发挑战。本文将深入探讨这两个平台在开发过程中的主要差异,从编程语言到用户界面设计,再到市场分布的不同影响,旨在为开发者提供一个全面的视角,帮助他们更好地理解并应对在不同平台上进行应用开发时可能遇到的难题和机遇。
|
11天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
【10月更文挑战第35天】在数字化时代,安卓应用的开发成为了一个热门话题。本文旨在通过浅显易懂的语言,带领初学者了解安卓开发的基础知识,同时为有一定经验的开发者提供进阶技巧。我们将一起探讨如何从零开始构建第一个安卓应用,并逐步深入到性能优化和高级功能的实现。无论你是编程新手还是希望提升技能的开发者,这篇文章都将为你提供有价值的指导和灵感。
|
9天前
|
存储 API 开发工具
探索安卓开发:从基础到进阶
【10月更文挑战第37天】在这篇文章中,我们将一起探索安卓开发的奥秘。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和建议。我们将从安卓开发的基础开始,逐步深入到更复杂的主题,如自定义组件、性能优化等。最后,我们将通过一个代码示例来展示如何实现一个简单的安卓应用。让我们一起开始吧!
|
10天前
|
存储 XML JSON
探索安卓开发:从新手到专家的旅程
【10月更文挑战第36天】在这篇文章中,我们将一起踏上一段激动人心的旅程,从零基础开始,逐步深入安卓开发的奥秘。无论你是编程新手,还是希望扩展技能的老手,这里都有适合你的知识宝藏等待发掘。通过实际的代码示例和深入浅出的解释,我们将解锁安卓开发的关键技能,让你能够构建自己的应用程序,甚至贡献于开源社区。准备好了吗?让我们开始吧!
23 2
|
11天前
|
Android开发
布谷语音软件开发:android端语音软件搭建开发教程
语音软件搭建android端语音软件开发教程!
|
14天前
|
移动开发 Java Android开发
探索Android与iOS开发的差异性与互联性
【10月更文挑战第32天】在移动开发的大潮中,Android和iOS两大平台各领风骚。本文将深入浅出地探讨这两个平台的开发差异,并通过实际代码示例,展示如何在各自平台上实现相似的功能。我们将从开发环境、编程语言、用户界面设计、性能优化等多个角度进行对比分析,旨在为开发者提供跨平台开发的实用指南。
37 0
|
缓存 安全 开发工具
Android 解决bug:Android studio 运行、编译项目时导致电脑死机
Android 解决bug:Android studio 运行、编译项目时导致电脑死机
899 0
|
Android开发
Android Studio在android Emulator中运行的项目黑屏
Android Studio在android Emulator中运行的项目黑屏
752 0
Android Studio在android Emulator中运行的项目黑屏
|
Android开发 开发者 Windows
Android Studio运行项目
一、在真机上运行(Mac没得) 二、Android Studio自带模拟器(AVD)安装以及运行项目 三、在模拟器上运行
654 0
Android Studio运行项目