RxPermissions主成分分析

動的権限を申請する必要がある理由

6.0より前のAndroidアプリケーションの権限はマニフェストで構成されていましたが、バージョン6.0では、ユーザーのプライバシーを保護するために新しい権限モードが導入されました。この権限モードは2つのタイプに分けられます。

  • 機密性の低いアクセス許可:このアクセス許可は動的に適用する必要はなく、マニフェストで構成する必要があるだけです。これは、6.0より前のアクセス許可の要求と同じです。

  • 機密性の高いアクセス許可:ユーザーが機密性の高いアクセス許可を使用する必要がある場合、システムに動的に適用する必要があります。そのようなアクセス許可はグループ化されます。アクセス許可のグループがいずれかに適用される限り、同じグループの他のアクセス許可も適用されます。 。

    特別許可グループ(Googleドキュメントから

    許可グループ 権限
    CALENDAR READ_CALENDAR``WRITE_CALENDAR
    CALL_LOG READ_CALL_LOG WRITE_CALL_LOG``PROCESS_OUTGOING_CALLS
    CAMERA CAMERA
    CONTACTS READ_CONTACTS``WRITE_CONTACTS``GET_ACCOUNTS
    LOCATION ACCESS_FINE_LOCATION``ACCESS_COARSE_LOCATION
    MICROPHONE RECORD_AUDIO
    PHONE READ_PHONE_STATE``READ_PHONE_NUMBERS``CALL_PHONE``ANSWER_PHONE_CALLS``ADD_VOICEMAIL``USE_SIP
    SENSORS BODY_SENSORS
    SMS SEND_SMS``RECEIVE_SMS``READ_SMS``RECEIVE_WAP_PUSH``RECEIVE_MMS
    STORAGE READ_EXTERNAL_STORAGE``WRITE_EXTERNAL_STORAGE

ネイティブアプリケーションの許可方法

  1. システムに権限があるかどうかを確認し、ない場合はrequestPermissionsメソッドを呼び出します

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
          
          
      ActivityCompat.requestPermissions(this, Manifest.permission.CAMERA,10)
    }
    
  2. onRequestPermissionsResultをオーバーライドして、アプリケーションが成功したかどうかを判断します

    if (requestCode == 10) {
          
          
                if (TextUtils.equals(permissions[0],Manifest.permission.WRITE_EXTERNAL_STORAGE) && grantResults[0] == PackageManager.PERMISSION_DENIED) {
          
          
                    //用户不同意,向用户展示该权限作用
                    if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
          
          
                        alertDialog( "请注意", "本应用需要使用访问本地存储权限,否则无法正常使用!", false, "确定", "取消", DialogInterface.OnClickListener {
          
           _, _ -> finish() }, DialogInterface.OnClickListener {
          
           _, _ -> finish() })
                        return
                    }
                }
            }
    

RxPermissionsアプリケーションのアクセス許可メソッド

  • 単一許可申請

    RxPermissions(this).request(Manifest.permission.ACCESS_COARSE_LOCATION)
            .subscribe {
          
          
                if (it) {
          
          
                    //申请成功
                } else {
          
          
                    //申请被拒
                }
    
            }
    
  • 複数の権限のアプリケーション

    RxPermissions(this).requestEach(
            Manifest.permission.READ_CONTACTS,
            Manifest.permission.WRITE_CONTACTS
        )
            .subscribe {
          
           permission ->
                when {
          
          
                    permission.granted -> {
          
          
                        //申请成功
                    }
                    permission.shouldShowRequestPermissionRationale -> {
          
          
                        // 用户拒绝了该权限,没有选择 不再提示 ,下次请求时,还会提示请求权限的对话框
                    }
                    else -> {
          
          
                        // 用户拒绝了该权限,选择了 不再提示 ,再次请求不会询问,需要在setting中开启
                    }
                }
            }
    

RxPermissionsパーミッションリクエストがシステムパーミッションリクエストよりもはるかに簡潔なのはなぜですか?実際、フレームワークはこれらの複雑な操作を実現するのに役立ちます。次に、RxPermissionsが内部でどのように実装されているかを見てみましょう。

ソースコード分析

すなわち、3つの主な種類を備えRxPermissions PermissionRxPermissionsRxPermissionsFragment

ここに画像の説明を挿入

まず、構築メソッドを見てみましょう。このメソッドには、フラグメントを取得するためのコードが1行しかありません。

public RxPermissions(@NonNull Activity activity) {
    
    
        mRxPermissionsFragment = getRxPermissionsFragment(activity);
    }

getRxPermissionsFragmentメソッドで、TAGに従って検索しますrxPermissionFragmentタグが空の場合は、タグを作成rxPermissionFragmentしてアクティビティに追加します。アクセス許可のリクエストとコールバックは、このフラグメントで完了します。詳細については、以下で説明します。

private RxPermissionsFragment getRxPermissionsFragment(Activity activity) {
    
    
        RxPermissionsFragment rxPermissionsFragment = findRxPermissionsFragment(activity);
        boolean isNewInstance = rxPermissionsFragment == null;
        if (isNewInstance) {
    
    
            rxPermissionsFragment = new RxPermissionsFragment();
            FragmentManager fragmentManager = activity.getFragmentManager();
            fragmentManager
                    .beginTransaction()
                    .add(rxPermissionsFragment, TAG)
                    .commitAllowingStateLoss();
            fragmentManager.executePendingTransactions();
        }
        return rxPermissionsFragment;
    }
private RxPermissionsFragment findRxPermissionsFragment(Activity activity) {
    
    
  			//根据TAG找到fragment
        return (RxPermissionsFragment) activity.getFragmentManager().findFragmentByTag(TAG);
    }

その後、メソッドを呼び出してrequestensurerequestImplementation

public Observable<Boolean> request(final String... permissions) {
    
    
        return Observable.just(TRIGGER).compose(ensure(permissions));
    }

public <T> ObservableTransformer<T, Boolean> ensure(final String... permissions) {
    
    
  			// 将Observable<Permission>转换为Observable<Boolean>
        return new ObservableTransformer<T, Boolean>() {
    
    
            @Override
            public ObservableSource<Boolean> apply(Observable<T> o) {
    
    
                return request(o, permissions)
                        .buffer(permissions.length)
                        .flatMap(new Function<List<Permission>, ObservableSource<Boolean>>() {
    
    
                            @Override
                            public ObservableSource<Boolean> apply(List<Permission> permissions) throws Exception {
    
    
                              //如果permissions为空,直接返回Observable.empty(),不执行下面的逻辑
                                if (permissions.isEmpty()) {
    
    
                                    return Observable.empty();
                                }
                              //遍历permissions,如果有一个Permission被拒,则返回false并发送出去
                                for (Permission p : permissions) {
    
    
                                    if (!p.granted) {
    
    
                                        return Observable.just(false);
                                    }
                                }
                              //如果权限都申请成功,则发送true
                                return Observable.just(true);
                            }
                        });
            }
        };
    }

private Observable<Permission> requestImplementation(final String... permissions) {
    
    
        List<Observable<Permission>> list = new ArrayList<>(permissions.length);
        List<String> unrequestedPermissions = new ArrayList<>();

        //遍历permissions,在mRxPermissionsFragment中判断该权限是否已经请求成功,如果成功构建成Permission通过Observable.just()发送出去并将Observable添加到list中
        for (String permission : permissions) {
    
    
            mRxPermissionsFragment.log("Requesting permission " + permission);
            if (isGranted(permission)) {
    
    
                list.add(Observable.just(new Permission(permission, true, false)));
                continue;
            }
          // 如果权限被拒绝
            if (isRevoked(permission)) {
    
    
                list.add(Observable.just(new Permission(permission, false, false)));
                continue;
            }

          //如果权限还没有申请过,则创建一个PublishSubject并添加到 unrequestedPermissions中
            PublishSubject<Permission> subject = mRxPermissionsFragment.getSubjectByPermission(permission);
            if (subject == null) {
    
    
                unrequestedPermissions.add(permission);
                subject = PublishSubject.create();
                mRxPermissionsFragment.setSubjectForPermission(permission, subject);
            }

            list.add(subject);
        }

        if (!unrequestedPermissions.isEmpty()) {
    
    
            String[] unrequestedPermissionsArray = unrequestedPermissions.toArray(new String[unrequestedPermissions.size()]);
          //调用requestPermissionsFromFragment中的方法申请权限
            requestPermissionsFromFragment(unrequestedPermissionsArray);
        }
  				//将多个Observable结合成一个Observable发射出去
        return Observable.concat(Observable.fromIterable(list));
    }

ここで最も重要なメソッドは、RxPermissionsFragmentパーミッションリクエストとデータコールバックを含むこのクラスにあります

void requestPermissions(@NonNull String[] permissions) {
    
    
 				//调用系统的请求权限的方法
        requestPermissions(permissions, PERMISSIONS_REQUEST_CODE);
    }

void onRequestPermissionsResult(String permissions[], int[] grantResults, boolean[] shouldShowRequestPermissionRationale) {
    
    
        for (int i = 0, size = permissions.length; i < size; i++) {
    
    
            PublishSubject<Permission> subject = mSubjects.get(permissions[i]);
            ...
            boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
          //将结果封装成Permission发送出去
            subject.onNext(new Permission(permissions[i], granted, shouldShowRequestPermissionRationale[i]));
        }
    }

これまでのところ、requestプロセス全体を分析しましたrequestEach、分析は残っていません。実際のrequestEachプロセスは上記と同様であるため、ここでは分析しません。全体として、RxPermissionsのプロセスは非常に単純ですが、多くのRxJava演算子が使用されており、要求結果はリスナーモードを介して取得されて送信されます。

総括する

  1. 空のフラグメントを作成し、アクティビティに追加します
  2. 許可リストをトラバースし、許可を要求せずにフラグメントを介して許可を要求するメソッドを呼び出します
  3. FragmentonRequestPermissionsResultでメソッドを書き直して、結果を送信します
  4. 観測可能なデータストリームを組み合わせる

おすすめ

転載: blog.csdn.net/ZYJWR/article/details/93390749