序言
我們知道Android里面啟動一個Activity For Result時嗜诀,回調(diào)會回到原來這個Activity的OnActivityResult中,如果此時孔祸,你正在寫一個其他組件隆敢,而不能直接依賴這個Activity那是不是很尷尬?
還有當我們在寫一個圖片庫組件時崔慧,發(fā)現(xiàn)要請求權(quán)限拂蝎,權(quán)限請求完后在進行操作,可是權(quán)限請求的回調(diào)依然在Activity中的onRequestPermissionsResult惶室,那我們怎么做呢温自?
今天介紹一個開源庫 ActivityResultPermission ,一個用于幫助OnActivityResult皇钞,PermissionRequest 解耦合的庫悼泌,不需要依賴Activity中的回調(diào).
原理
解耦合Activity中的回調(diào),有兩種方式
- 一種是啟動一個新的Activity來判斷權(quán)限夹界,獲取ActivityForResult的結(jié)果. (可以參考RxAcitityResult,RxPermission的實現(xiàn)方式)
如下:
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中獲取回調(diào),進行解耦合.參考本文所提到庫的代碼如下
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营密,但也支持鏈式調(diào)用.
- 功能更豐富械媒,兩者結(jié)合,使用更加方便卵贱,并支持部分國產(chǎn)Rom的權(quán)限判斷滥沫,跳轉(zhuǎn)權(quán)限設置頁面.
- 代碼量少,可以選擇拷貝代碼直接放入項目.(核心代碼不到 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现诀,并注冊其回調(diào)
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{
//點擊禁止權(quán)限屿聋,并不允許在彈出
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手機),可以調(diào)用PermissionUtils.checkSelfPermissionsWhitNoNoramal(context,permissions);
請求權(quán)限時龙致,調(diào)用ActivityResultPermissionUtils.requestPermissions(this, permission).permissionsWithoutCheck();
關(guān)于更多請查看sample ActivityResultPermission