Preyea Regmi
5 years ago
12 changed files with 388 additions and 80 deletions
-
1app/src/main/java/com/gmeremit/online/gmeremittance_native/homeV2/view/HomeActivityV2.java
-
27app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/presenter/resend/ReSendMoneyV2Presenter.java
-
6app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/presenter/resend/ReSendMoneyV2PresenterInterface.java
-
14app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/view/ReSendMoneyV2Activity.java
-
10app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/model/SendMoneyAPIRequestBody.java
-
23app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/presenter/SendMoneyV2Presenter.java
-
7app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/presenter/SendMoneyV2PresenterInterface.java
-
14app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/view/SendMoneyV2Activity.java
-
3app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2Presenter.java
-
236app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/view/TransactionBiometricPromptDialog.java
-
45app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/view/TransactionPasswordPromptDialog.java
-
52app/src/main/res/layout/dialog_password_prompt_v2.xml
@ -0,0 +1,236 @@ |
|||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.view; |
|||
|
|||
import android.app.Dialog; |
|||
import android.content.SharedPreferences; |
|||
import android.os.Build; |
|||
import android.os.Bundle; |
|||
import android.os.Handler; |
|||
import android.security.keystore.KeyPermanentlyInvalidatedException; |
|||
import android.support.graphics.drawable.AnimatedVectorDrawableCompat; |
|||
import android.support.v7.app.AlertDialog; |
|||
import android.util.Log; |
|||
import android.view.Gravity; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.view.Window; |
|||
import android.widget.ImageView; |
|||
import android.widget.TextView; |
|||
import android.widget.Toast; |
|||
|
|||
import com.gmeremit.online.gmeremittance_native.GmeApplication; |
|||
import com.gmeremit.online.gmeremittance_native.R; |
|||
import com.gmeremit.online.gmeremittance_native.base.PrefKeys; |
|||
import com.gmeremit.online.gmeremittance_native.customwidgets.CustomAlertDialog; |
|||
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter.TransactionPasswordPromptV2Presenter; |
|||
import com.gmeremit.online.gmeremittance_native.utils.security.SecurityUtils; |
|||
import com.mtramin.rxfingerprint.data.FingerprintAuthenticationException; |
|||
import com.mtramin.rxfingerprint.data.FingerprintDecryptionResult; |
|||
|
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
import io.reactivex.Observable; |
|||
import io.reactivex.android.schedulers.AndroidSchedulers; |
|||
import io.reactivex.disposables.CompositeDisposable; |
|||
import io.reactivex.disposables.Disposable; |
|||
import io.reactivex.observers.DisposableObserver; |
|||
import io.reactivex.schedulers.Schedulers; |
|||
|
|||
public class TransactionBiometricPromptDialog extends android.support.v4.app.DialogFragment { |
|||
|
|||
|
|||
private AnimatedVectorDrawableCompat fingerPrintAVDCompat; |
|||
private ImageView passwordPromptImageView; |
|||
private Disposable fingerPrintScanningSubscription; |
|||
private CompositeDisposable compositeDisposable; |
|||
private BiometricPromptResultListener listener; |
|||
|
|||
|
|||
@Override |
|||
public Dialog onCreateDialog(Bundle savedInstanceState) { |
|||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
|||
View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_password_prompt_v2, null); |
|||
passwordPromptImageView=view.findViewById(R.id.passwordPromptImageView); |
|||
builder.setView(view); |
|||
Dialog dialog= builder.create(); |
|||
try { |
|||
dialog.getWindow().setBackgroundDrawableResource(R.drawable.ic_rounded_white); |
|||
|
|||
} catch (NullPointerException e) { |
|||
|
|||
} |
|||
initialize(); |
|||
return dialog; |
|||
|
|||
} |
|||
|
|||
private void initialize() { |
|||
this.compositeDisposable = new CompositeDisposable(); |
|||
fingerPrintAVDCompat = AnimatedVectorDrawableCompat.create(getActivity(), R.drawable.avd_fingerprint_off_to_on); |
|||
|
|||
} |
|||
|
|||
public void setResultListener(BiometricPromptResultListener listener) |
|||
{ |
|||
this.listener=listener; |
|||
} |
|||
|
|||
@Override |
|||
public void onStart() { |
|||
super.onStart(); |
|||
startObservingFingerPrintIfRequired(true); |
|||
} |
|||
|
|||
@Override |
|||
public void onStop() { |
|||
super.onStop(); |
|||
startObservingFingerPrintIfRequired(false); |
|||
} |
|||
|
|||
public void animateFingerPrintAppearAnimationIfRequired(boolean action) { |
|||
if (action) { |
|||
if (fingerPrintAVDCompat != null && !fingerPrintAVDCompat.isRunning()) { |
|||
passwordPromptImageView.setImageDrawable(fingerPrintAVDCompat); |
|||
fingerPrintAVDCompat.start(); |
|||
} |
|||
} else { |
|||
passwordPromptImageView.setImageDrawable(null); |
|||
} |
|||
} |
|||
|
|||
public void startObservingFingerPrintIfRequired(boolean action) { |
|||
|
|||
if (!action) { |
|||
if (fingerPrintScanningSubscription != null && !fingerPrintScanningSubscription.isDisposed()) |
|||
fingerPrintScanningSubscription.dispose(); |
|||
} else { |
|||
animateFingerPrintAppearAnimationIfRequired(true); |
|||
fingerPrintScanningSubscription = authenticateFingerprint().subscribeWith(new FingerprintDecResultObserver()); |
|||
compositeDisposable.add(fingerPrintScanningSubscription); |
|||
} |
|||
|
|||
|
|||
} |
|||
|
|||
private Observable<FingerprintDecResult> authenticateFingerprint() { |
|||
return Observable.zip(Observable.fromCallable(()-> GmeApplication.getStorage().getString(PrefKeys.APP_USER_ID_SECRET_KEY,null)), |
|||
Observable.fromCallable(()->GmeApplication.getStorage().getString(PrefKeys.APP_SECRET_KEY,null)) |
|||
.flatMap(storedKey -> decryptFromKeyStore(storedKey).flatMap(decAesKey -> SecurityUtils.decryptSymmetric(GmeApplication.getStorage().getString(PrefKeys.APP_USER_SECRET_KEY,null), decAesKey))) |
|||
.subscribeOn(Schedulers.io()), |
|||
FingerprintDecResult::new) |
|||
.doOnSubscribe(subs -> { |
|||
animateFingerPrintAppearAnimationIfRequired(true); |
|||
}) |
|||
.observeOn(AndroidSchedulers.mainThread()); |
|||
} |
|||
|
|||
private Observable<String> decryptFromKeyStore(String data) { |
|||
return SecurityUtils.decryptFromKeyStore(getActivity(), data) |
|||
.flatMap(authentication -> { |
|||
switch (authentication.getResult()) { |
|||
case FAILED: |
|||
return io.reactivex.Observable.error(new SecurityUtils.FailedFingerPrintException(getString(R.string.fingerprint_not_recognized))); |
|||
case HELP: |
|||
return io.reactivex.Observable.error(new SecurityUtils.SensorNotReadyException(authentication.getMessage())); |
|||
case AUTHENTICATED: |
|||
return Observable.just(authentication); |
|||
default: |
|||
return io.reactivex.Observable.error(new Throwable(authentication.getMessage())); |
|||
} |
|||
}) |
|||
.observeOn(AndroidSchedulers.mainThread()) |
|||
.retryWhen(errors -> errors.flatMap( |
|||
error -> { |
|||
if (error instanceof SecurityUtils.FailedFingerPrintException || error instanceof SecurityUtils.SensorNotReadyException) { |
|||
animateFingerPrintAppearAnimationIfRequired(true); |
|||
showToastMessage(error.getMessage()); |
|||
return Observable.timer(100, TimeUnit.MILLISECONDS); |
|||
} |
|||
return Observable.error(error); |
|||
} |
|||
)) |
|||
.map(FingerprintDecryptionResult::getDecrypted); |
|||
|
|||
|
|||
} |
|||
|
|||
private void showToastMessage(String message) { |
|||
Toast toast=Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT); |
|||
TextView v = (TextView) toast.getView().findViewById(android.R.id.message); |
|||
if( v != null) v.setGravity(Gravity.CENTER); |
|||
toast.show(); |
|||
} |
|||
|
|||
public class FingerprintDecResult { |
|||
String userId; |
|||
String userPwd; |
|||
|
|||
public FingerprintDecResult(String userId, String userPwd) { |
|||
this.userId = userId; |
|||
this.userPwd = userPwd; |
|||
} |
|||
|
|||
public String getUserId() { |
|||
return userId; |
|||
} |
|||
|
|||
public String getUserPwd() { |
|||
return userPwd; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return "FingerprintDecResult{" + |
|||
"userId='" + userId + '\'' + |
|||
", userPwd='" + userPwd + '\'' + |
|||
'}'; |
|||
} |
|||
} |
|||
|
|||
public class FingerprintDecResultObserver extends DisposableObserver<FingerprintDecResult> { |
|||
|
|||
@Override |
|||
public void onNext(FingerprintDecResult fingerprintDecResult) { |
|||
dismiss(); |
|||
if(listener!=null) |
|||
listener.onBiometricAuthSuccess(fingerprintDecResult.getUserPwd()); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void onError(Throwable e) { |
|||
|
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && e instanceof KeyPermanentlyInvalidatedException) |
|||
{ |
|||
|
|||
SharedPreferences.Editor editor = GmeApplication.getStorage().edit(); |
|||
editor.putString(PrefKeys.APP_USER_ID_SECRET_KEY,null); |
|||
editor.putBoolean(PrefKeys.APP_FINGER_PRINT_ENABLED,false); |
|||
editor.putString(PrefKeys.APP_USER_SECRET_KEY,null); |
|||
editor.putString(PrefKeys.APP_SECRET_KEY,null); |
|||
editor.apply(); |
|||
|
|||
showToastMessage(getString(R.string.fingerprint_changed_externally)); |
|||
} |
|||
else if(e instanceof FingerprintAuthenticationException) |
|||
{ |
|||
showToastMessage(e.getMessage()); |
|||
new Handler().postDelayed(TransactionBiometricPromptDialog.this::dismiss,200); |
|||
} |
|||
|
|||
Log.d(SecurityUtils.TAG, "Failed : " + e.getMessage()); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void onComplete() { |
|||
|
|||
} |
|||
} |
|||
|
|||
|
|||
public interface BiometricPromptResultListener |
|||
{ |
|||
void onBiometricAuthSuccess(String decResult); |
|||
} |
|||
|
|||
} |
@ -1,45 +0,0 @@ |
|||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.view; |
|||
|
|||
import android.app.Dialog; |
|||
import android.os.Bundle; |
|||
import android.support.v7.app.AlertDialog; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.view.Window; |
|||
|
|||
import com.gmeremit.online.gmeremittance_native.R; |
|||
|
|||
public class TransactionPasswordPromptDialog extends android.support.v4.app.DialogFragment { |
|||
|
|||
|
|||
@Override |
|||
public Dialog onCreateDialog(Bundle savedInstanceState) { |
|||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
|||
View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_password_prompt_v2, null); |
|||
|
|||
builder.setView(view); |
|||
|
|||
|
|||
initialize(); |
|||
return builder.create(); |
|||
|
|||
} |
|||
|
|||
private void initialize() { |
|||
|
|||
} |
|||
|
|||
|
|||
@Override |
|||
public void onStart() { |
|||
super.onStart(); |
|||
|
|||
|
|||
Window window = getDialog().getWindow(); |
|||
if (window != null) { |
|||
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); |
|||
window.setBackgroundDrawableResource(R.drawable.ic_rounded_password_prompt); |
|||
|
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue