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
-
41app/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
-
39app/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