序言
我们知道Android里面启动一个Activity For Result时,回调会回到原来这个Activity的OnActivityResult中,如果此时,你正在写一个其他组件,而不能直接依赖这个Activity那是不是很尴尬?
还有当我们在写一个图片库组件时,发现要请求权限,权限请求完后在进行操作,可是权限请求的回调依然在Activity中的onRequestPermissionsResult,那我们怎么做呢?
今天介绍一个开源库 ActivityResultPermission ,一个用于帮助OnActivityResult,PermissionRequest 解耦合的库,不需要依赖Activity中的回调.
原理
解耦合Activity中的回调,有两种方式
- 一种是启动一个新的Activity来判断权限,获取ActivityForResult的结果. (可以参考RxAcitityResult,RxPermission的实现方式)
如下:
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() throws Exception {
finish();
}
})
.subscribe();
} else {
finish();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (onResult != null)
onResult.response(requestCode, resultCode, data);
}
static void setRequest(Request aRequest) {
request = aRequest;
}
}
- 一种是添加一个Fragment,在Fragment中获取回调,进行解耦合.参考本文所提到库的代码如下
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(){
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);
}
}
}
RxActivityResult,RxPermission采用都是前者,而此处采用了后者,使用Fragment.
与RxActivityResult和RxPermission有什么不同?
- 不需要依赖RxJava,但也支持链式调用.
- 功能更丰富,两者结合,使用更加方便,并支持部分国产Rom的权限判断,跳转权限设置页面.
- 代码量少,可以选择拷贝代码直接放入项目.(核心代码不到 400行)
- Fragment的方式占用资源更少.
开始使用 (minSdkVersion >= 14)
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.DingProg:ActivityResultPermission:v0.0.1'
}
OnActivityResult
Intent intent = new Intent(this, OnActivityResultActivity.class);
//通过ActivityResultPermissionUtils 去启动Activity,并注册其回调
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() {
Toast.makeText(MainActivity.this, "openActivity with result cancel", Toast.LENGTH_SHORT).show();
}
});
Permissions处理
ActivityResultPermissionUtils.requestPermissions(this, Manifest.permission.CAMERA).permissions(new Listener.PermissionResultListener() {
@Override
public void permissionDenied(String permission, boolean rationale) {
//rationale if true 仅仅点击了禁止
if(rationale){
Toast.makeText(MainActivity.this, "Denied permission", Toast.LENGTH_SHORT).show();
}else{
//点击禁止权限,并不允许在弹出
Toast.makeText(MainActivity.this, "Denied permission with ask never", Toast.LENGTH_SHORT).show();
PermissionGoSettingsPageUtils.go(MainActivity.this);
}
}
@Override
public void permissionGranted() {
releaseCamera();
try{
camera = Camera.open(0);
camera.setPreviewDisplay(surfaceView.getHolder());
camera.startPreview();
}catch (Exception e){
e.printStackTrace();
}
}
});
如果对于一些非正常Rom(如oppo,vivo手机),可以调用PermissionUtils.checkSelfPermissionsWhitNoNoramal(context,permissions);
请求权限时,调用ActivityResultPermissionUtils.requestPermissions(this, permission).permissionsWithoutCheck();
关于更多请查看sample ActivityResultPermission