Last active
June 1, 2018 06:45
-
-
Save aucd29/f10dba3204868989fdfa5a8a7681b5c8 to your computer and use it in GitHub Desktop.
Runtime 퍼미션을 Rx 화 시키기 위해서 끄적거려본 코드 RxPermsisions, Rx 시작을 이제 한달 째라 아직 잘 모르지만 =_ = 암튼 그냥 그냥 만들어 봄
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class PermissionFragment extends Fragment { | |
private static final Logger mLog = LoggerFactory.getLogger(PermissionFragment.class); | |
/** 퍼미션 처리에 필요한 파라메터 값 */ | |
protected PermissionParams mParams; | |
@Override | |
public void onCreate(@Nullable Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setRetainInstance(true); | |
} | |
@Override | |
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { | |
boolean grantResult = true; | |
for (int result : grantResults) { | |
if (result == PackageManager.PERMISSION_DENIED) { | |
grantResult = false; | |
break; | |
} | |
} | |
onPermissionResult(grantResult); | |
} | |
/** | |
* 런타임 퍼미션 결과를 처리 한다. | |
* @param result 처리 결과 | |
*/ | |
protected void onPermissionResult(boolean result) { | |
if (mLog.isDebugEnabled()) { | |
mLog.debug("PERMISSION RESULT : " + result); | |
} | |
if (result) { | |
mParams.listener.onResult(mParams.reqCode, true); | |
} else { | |
showPermissionDialog(); | |
} | |
} | |
/** | |
* 런타임 퍼미션을 요청 한다. | |
* @param params 런타임 퍼미션에 필요한 파라메터 정보 | |
*/ | |
public void requestPermissions(@NonNull PermissionParams params) { | |
mParams = params; | |
if (mLog.isDebugEnabled()) { | |
mLog.debug("REQUEST PERMISSION"); | |
} | |
requestPermissions(params.toArrayPermissions(), params.reqCode); | |
} | |
/** | |
* 퍼미션 결과가 negative 일 경우 팝업창을 띄워 퍼미션을 승낙 하도록 유도 한다. | |
*/ | |
protected void showPermissionDialog() { | |
if (mLog.isDebugEnabled()) { | |
mLog.debug("PARAMS : " + mParams); | |
} | |
if (mParams.reqCode == PermissionUtils.REQ_MAIN) { | |
eventNegative(); | |
return ; | |
} | |
IDialogDelegate delegate = PermissionUtils.getDialogDelegate(); | |
String msg = getString(R.string.permission_message); | |
if (delegate != null) { | |
delegate.show(IDialogDelegate.CONFIRM, getString(R.string.permission_title), msg, (result, value) -> { | |
switch (result) { | |
case OnResultListener.FALSE: | |
eventNegative(); | |
break; | |
default: | |
eventPositive(); | |
break; | |
} | |
}); | |
return ; | |
} | |
AlertDialog.Builder builder = new AlertDialog.Builder(mParams.activity); | |
builder.setTitle(R.string.permission_title); | |
builder.setMessage(msg); | |
builder.setNegativeButton(string("button_cancel"), (dialog, which) -> { | |
dialog.dismiss(); | |
eventNegative(); | |
}); | |
builder.setPositiveButton(string("button_set"), (dialog, which) -> { | |
dialog.dismiss(); | |
eventPositive(); | |
}); | |
builder.setCancelable(false); | |
builder.show(); | |
} | |
/** | |
* showPermissionDialog 에서 negative 버튼을 선택 시 발생 시켜야할 이벤트 | |
*/ | |
protected void eventNegative() { | |
mParams.listener.onResult(mParams.reqCode, false); | |
} | |
/** | |
* showPermissionDialog 에서 positive 버튼을 선택 시 발생 시켜야할 이벤트 | |
*/ | |
protected void eventPositive() { | |
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); | |
intent.setData(Uri.parse("package:" + mParams.activity.getPackageName())); | |
startActivityForResult(intent, PermissionUtils.RESULT_ACTION_PERMISSION); | |
} | |
/** | |
* 문자열을 반환 한다. | |
* @param key 문자열에 해당하는 키 값 | |
* @return 문자열 값 | |
*/ | |
protected String string(@NonNull String key) { | |
return getString(getResources().getIdentifier(key, "string", getContext().getPackageName())); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class PermissionParams { | |
/** request code */ | |
int reqCode; | |
/** 타깃이 되는 activity */ | |
FragmentActivity activity; | |
/** 허용해야할 퍼미션 목록 */ | |
List<String> permissions; | |
/** 결과를 전달할 리스너 */ | |
OnPermissionListener listener; | |
private PermissionParams(Builder builder) { | |
this.reqCode = builder.reqCode; | |
this.activity = builder.activity; | |
this.permissions = builder.permissions; | |
this.listener = builder.listener; | |
} | |
public String[] toArrayPermissions() { | |
return permissions.toArray(new String[permissions.size()]); | |
} | |
public int reqCode() { | |
return reqCode; | |
} | |
public FragmentActivity activity() { | |
return activity; | |
} | |
public static Builder builder() { | |
return new Builder(); | |
} | |
//////////////////////////////////////////////////////////////////////////////////// | |
// | |
// Builder | |
// | |
//////////////////////////////////////////////////////////////////////////////////// | |
public static class Builder { | |
private int reqCode = 0; | |
private FragmentActivity activity; | |
private List<String> permissions = new ArrayList<>(); | |
private OnPermissionListener listener; | |
public Builder reqCode(int reqCode) { | |
this.reqCode = reqCode; | |
return this; | |
} | |
public Builder activity(FragmentActivity activity) { | |
this.activity = activity; | |
return this; | |
} | |
public Builder activity(Activity activity) { | |
this.activity = (FragmentActivity) activity; | |
return this; | |
} | |
public Builder permission(@NonNull String permission) { | |
permissions.add(permission); | |
return this; | |
} | |
public Builder permissions(@NonNull String[] permissions) { | |
this.permissions.addAll(Arrays.asList(permissions)); | |
return this; | |
} | |
public Builder listener(@NonNull OnPermissionListener listener) { | |
this.listener = listener; | |
return this; | |
} | |
public PermissionParams build() { | |
return new PermissionParams(this); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class RxPermissionFragment extends PermissionFragment { | |
private static final Logger mLog = LoggerFactory.getLogger(RxPermissionFragment.class); | |
private Observer<? super RxPermissionResult> mObserver; | |
@Override | |
protected void onPermissionResult(boolean result) { | |
if (mLog.isDebugEnabled()) { | |
mLog.debug("PERMISSION RESULT : " + result); | |
} | |
if (result) { | |
mObserver.onNext(new RxPermissionResult(mParams.reqCode(), true)); | |
} else { | |
showPermissionDialog(); | |
} | |
} | |
public void setObserver(Observer<? super RxPermissionResult> observer) { | |
mObserver = observer; | |
} | |
public void requestPermissions(@NonNull PermissionParams params) { | |
mParams = params; | |
if (mLog.isDebugEnabled()) { | |
mLog.debug("REQUEST PERMISSION"); | |
} | |
requestPermissions(params.toArrayPermissions(), params.reqCode()); | |
} | |
@Override | |
protected void eventNegative() { | |
mObserver.onNext(new RxPermissionResult(mParams.reqCode(), false)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class RxPermissionResult { | |
public int code; | |
public boolean result; | |
public RxPermissionResult(int code, boolean result) { | |
this.code = code; | |
this.result = result; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public final class RxPermissions extends Observable<RxPermissionResult> { | |
private final PermissionParams mParams; | |
/** | |
* 퍼미션을 체크 하기 위해 클래스를 인스턴스 한다. | |
* @param params 퍼미션 체크에 필요한 파라메터 | |
* @return RxPermissions 객체 | |
*/ | |
public static RxPermissions params(PermissionParams params) { | |
return new RxPermissions(params); | |
} | |
private RxPermissions(PermissionParams params) { | |
mParams = params; | |
} | |
@Override | |
protected void subscribeActual(Observer<? super RxPermissionResult> observer) { | |
if (!checkLooperThread(observer)) { | |
return ; | |
} | |
RxPermissionsDisposable disposable = new RxPermissionsDisposable(observer); | |
observer.onSubscribe(disposable); | |
if (!PermissionUtils.checkSelfPermission(mParams.activity(), mParams.toArrayPermissions())) { | |
RxPermissionFragment frgmt = permissionFragment(); | |
frgmt.setObserver(observer); | |
frgmt.requestPermissions(mParams); | |
return ; | |
} | |
observer.onNext(new RxPermissionResult(mParams.reqCode(), true)); | |
} | |
private boolean checkLooperThread(final Observer observer) { | |
if (Looper.myLooper() == null) { | |
observer.onSubscribe(Disposables.empty()); | |
observer.onError(new IllegalStateException("Calling thread is not associated with Looper")); | |
return false; | |
} | |
return true; | |
} | |
private @NonNull RxPermissionFragment permissionFragment() { | |
FragmentManager manager = mParams.activity().getSupportFragmentManager(); | |
RxPermissionFragment frgmt = (RxPermissionFragment) manager | |
.findFragmentByTag(RxPermissionFragment.class.getName()); | |
if (frgmt != null) { | |
return frgmt; | |
} | |
frgmt = new RxPermissionFragment(); | |
manager.beginTransaction() | |
.add(frgmt, RxPermissionFragment.class.getName()) | |
.commitAllowingStateLoss(); | |
manager.executePendingTransactions(); | |
return frgmt; | |
} | |
private class RxPermissionsDisposable implements Disposable { | |
private final AtomicBoolean disposed = new AtomicBoolean(false); | |
private final Observer<? super RxPermissionResult> observer; | |
RxPermissionsDisposable(Observer<? super RxPermissionResult> observer) { | |
this.observer = observer; | |
} | |
@Override | |
public void dispose() { | |
if (disposed.compareAndSet(false, true)) { | |
observer.onComplete(); | |
} | |
} | |
@Override | |
public boolean isDisposed() { | |
return disposed.get(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment