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地址),文章请勿滥用,也希望大家尊重笔者的劳动成果。

相关文章
|
20天前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
40 19
|
20天前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
45 14
|
21天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
在数字时代,掌握安卓应用开发技能是进入IT行业的关键。本文将引导读者从零基础开始,逐步深入安卓开发的世界,通过实际案例和代码示例,展示如何构建自己的第一个安卓应用。我们将探讨基本概念、开发工具设置、用户界面设计、数据处理以及发布应用的全过程。无论你是编程新手还是有一定基础的开发者,这篇文章都将为你提供宝贵的知识和技能,帮助你在安卓开发的道路上迈出坚实的步伐。
31 5
|
20天前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
|
21天前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
21天前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
21天前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
27 0
|
缓存 安全 开发工具
Android 解决bug:Android studio 运行、编译项目时导致电脑死机
Android 解决bug:Android studio 运行、编译项目时导致电脑死机
935 0
|
Android开发
Android Studio在android Emulator中运行的项目黑屏
Android Studio在android Emulator中运行的项目黑屏
764 0
Android Studio在android Emulator中运行的项目黑屏
|
Android开发 开发者 Windows
Android Studio运行项目
一、在真机上运行(Mac没得) 二、Android Studio自带模拟器(AVD)安装以及运行项目 三、在模拟器上运行
659 0
Android Studio运行项目