The preface

We know that when you start an Activity For Result in Android, the callback goes back to the Activity’s OnActivityResult. Isn’t that awkward if you’re writing another component and you can’t rely on the Activity directly? And when we write a gallery component, found to request permissions, right after the request in the operation, but still access request callback onRequestPermissionsResult in the Activity, what do we do? Today we introduce ActivityResultPermission, an open source library that helps uncouple OnActivityResult and PermissionRequest without relying on callbacks in activities.

The principle of

There are two ways to uncouple callbacks in an Activity

  • One is starting a new Activity to determine permissions, get ActivityForResult results. (you can refer to RxAcitityResult, RxPermission implementation) as follows:
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;

import io.reactivex.functions.Action;

public class HolderActivity extends Activity {
    private static Request request;
    private OnPreResult onPreResult;
    private OnResult onResult;
    private int resultCode;
    private int requestCode;
    private Intent data;
    private static int FAILED_REQUEST_CODE = -909;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (request == null) {
            finish();
            return;
        }

        onPreResult = request.onPreResult();
        onResult = request.onResult();

        if(savedInstanceState ! =null) return;

        if (request instanceof RequestIntentSender) {
            RequestIntentSender requestIntentSender = (RequestIntentSender) request;

            if (requestIntentSender.getOptions() == null) startIntentSender(requestIntentSender);
            else startIntentSenderWithOptions(requestIntentSender);
        } else {
            try {
                startActivityForResult(request.intent(), 0);
            } catch (ActivityNotFoundException e) {
                if(onResult ! =null) { onResult.error(e); }}}}private void startIntentSender(RequestIntentSender requestIntentSender) {
        try {
            startIntentSenderForResult(requestIntentSender.getIntentSender(), 0,
                    requestIntentSender.getFillInIntent(), requestIntentSender.getFlagsMask(),
                    requestIntentSender.getFlagsValues(), requestIntentSender.getExtraFlags());
        } catch (IntentSender.SendIntentException exception) {
            exception.printStackTrace();
            onResult.response(FAILED_REQUEST_CODE, RESULT_CANCELED, null); }}private void startIntentSenderWithOptions(RequestIntentSender requestIntentSender) {
        try {
            startIntentSenderForResult(requestIntentSender.getIntentSender(), 0,
                    requestIntentSender.getFillInIntent(), requestIntentSender.getFlagsMask(),
                    requestIntentSender.getFlagsValues(), requestIntentSender.getExtraFlags(), requestIntentSender.getOptions());
        } catch (IntentSender.SendIntentException exception) {
            exception.printStackTrace();
            onResult.response(FAILED_REQUEST_CODE, RESULT_CANCELED, null); }}@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        this.resultCode = resultCode;
        this.requestCode = requestCode;
        this.data = data;

        if (this.onPreResult ! =null) {
            this.onPreResult.response(requestCode, resultCode, data)
                    .doOnComplete(new Action() {
                        @Override
                        public void run(a) throws Exception {
                            finish();
                        }
                    })
                    .subscribe();
        } else{ finish(); }}@Override
    protected void onDestroy(a) {
        super.onDestroy();
        if(onResult ! =null)
            onResult.response(requestCode, resultCode, data);
    }

    static void setRequest(Request aRequest) { request = aRequest; }}Copy the code
  • One is to add a Fragment, get a callback in the Fragment, and decouple it. The code for the library mentioned in this article is shown below
import android.app.Fragment;
import android.content.Intent;

import androidx.annotation.NonNull;

/** * author:DingDeGao * time:2019-07-16-14:30 * function: ReplaceFragment */
public class ReplaceFragment extends Fragment {

    static final int ACTIVITY_REQUEST_CODE = 100;
    static final int PERMISSION_REQUEST_CODE = 101;


    private IHandle iHandle;

    public void setIHandle(IHandle iHandle) {
        this.iHandle = iHandle;
    }

    public IHandle getIHandle(a){
        return iHandle;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode ! = ACTIVITY_REQUEST_CODE)return;
        if(iHandle ! =null){ iHandle.onActivityResultHandle(resultCode,data); }}@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode ! = PERMISSION_REQUEST_CODE)return;
        if(iHandle ! =null){ iHandle.onRequestPermissionsResultHandle(getActivity(),permissions,grantResults); }}}Copy the code

RxActivityResult, RxPermission is the former, and here the latter is the Fragment.

How is it different from RxActivityResult and RxPermission?

  1. There is no need to rely on RxJava, but chained calls are also supported.
  2. The function is richer, the combination of the two, the use is more convenient, and support part of the domestic Rom permission judgment, jump permission setting page.
  3. Small amount of code, you can choose to copy the code directly into the project (less than 400 lines of core code).
  4. Fragment takes up fewer resources.

Start using (minSdkVersion >= 14)

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

dependencies {
	implementation 'com. Making. DingProg: ActivityResultPermission: v0.0.1'
}

Copy the code

OnActivityResult

 Intent intent = new Intent(this, OnActivityResultActivity.class);
 / / by ActivityResultPermissionUtils to start the Activity, and register the callback
 ActivityResultPermissionUtils.startActivityForResult(this, intent).activityResult(new Listener.ResultListener() {
            @Override
        public void onResult(Intent data) {
            if(data ! =null) {
                String testStr = data.getStringExtra("test");
                Toast.makeText(MainActivity.this."openActivity with result is:"+ testStr, Toast.LENGTH_SHORT).show(); }}@Override
        public void onCancel(a) {
            Toast.makeText(MainActivity.this."openActivity with result cancel", Toast.LENGTH_SHORT).show(); }});Copy the code

Permissions to handle

ActivityResultPermissionUtils.requestPermissions(this, Manifest.permission.CAMERA).permissions(new Listener.PermissionResultListener() {
        @Override
        public void permissionDenied(String permission, boolean rationale) {
            // Rationale if true just clicked prohibit
            if(rationale){
                Toast.makeText(MainActivity.this."Denied permission", Toast.LENGTH_SHORT).show();
            }else{
            // Click Disable permissions, do not allow in pop-up
                  Toast.makeText(MainActivity.this."Denied permission with ask never", Toast.LENGTH_SHORT).show();
                PermissionGoSettingsPageUtils.go(MainActivity.this); }}@Override
        public void permissionGranted(a) {
            releaseCamera();
            try{
                camera = Camera.open(0);
                camera.setPreviewDisplay(surfaceView.getHolder());
                camera.startPreview();
            }catch(Exception e){ e.printStackTrace(); }}});Copy the code

If for some abnormal Rom (such as oppo, vivo mobile phone), you can call PermissionUtils. CheckSelfPermissionsWhitNoNoramal (context, permissions).

Right, call ActivityResultPermissionUtils. RequestPermissions (this, permission). PermissionsWithoutCheck ();

See sample ActivityResultPermission for more information