Preyea Regmi
4 years ago
26 changed files with 187 additions and 1566 deletions
-
BIN.idea/caches/build_file_checksums.ser
-
1app/build.gradle
-
138app/src/main/java/com/gmeremit/online/gmeremittance_native/customwidgets/passwordpromptdialog/PasswordPromptDialog.java
-
7app/src/main/java/com/gmeremit/online/gmeremittance_native/domesticremit/send/presenter/DomesticRemitPresenterImpl.java
-
6app/src/main/java/com/gmeremit/online/gmeremittance_native/domesticremit/send/presenter/DomesticRemitPresenterInterface.java
-
51app/src/main/java/com/gmeremit/online/gmeremittance_native/domesticremit/send/view/DomesticRemitActivity.java
-
49app/src/main/java/com/gmeremit/online/gmeremittance_native/loginV2/view/LoginV2Activity.java
-
51app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/presenter/resend/ReSendMoneyV2Presenter.java
-
4app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/presenter/resend/ReSendMoneyV2PresenterInterface.java
-
58app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/view/ReSendMoneyV2Activity.java
-
2app/src/main/java/com/gmeremit/online/gmeremittance_native/security/auth/GMEUserPasswordPromptBottomSheetDialog.java
-
9app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/presenter/SendMoneyV2PresenterInterface.java
-
63app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/view/SendMoneyV2Activity.java
-
105app/src/main/java/com/gmeremit/online/gmeremittance_native/topup/local/presenter/topup/LocalTopUpPresenter.java
-
7app/src/main/java/com/gmeremit/online/gmeremittance_native/topup/local/presenter/topup/LocalTopUpPresenterInterface.java
-
66app/src/main/java/com/gmeremit/online/gmeremittance_native/topup/local/view/topup/LocalTopUpActivity.java
-
6app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/PasswordPromptListener.java
-
29app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/gateway/TransactionPasswordPromptV2Gateway.java
-
16app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2InteractorInterface.java
-
273app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2Presenter.java
-
46app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2PresenterInterface.java
-
240app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/view/TransactionBiometricPromptDialog.java
-
453app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/view/TransactionPasswordPromptActivity.java
-
22app/src/main/res/layout/activity_domestic_remit.xml
-
25app/src/main/res/layout/activity_login_v2.xml
-
26app/src/main/res/values/styles.xml
@ -1,138 +0,0 @@ |
|||
package com.gmeremit.online.gmeremittance_native.customwidgets.passwordpromptdialog; |
|||
|
|||
import android.app.Dialog; |
|||
import android.content.Context; |
|||
import android.content.DialogInterface; |
|||
import android.os.Bundle; |
|||
import androidx.appcompat.app.AlertDialog; |
|||
import android.util.Log; |
|||
import android.view.View; |
|||
import android.view.Window; |
|||
import android.view.WindowManager; |
|||
import android.view.inputmethod.InputMethodManager; |
|||
import android.widget.EditText; |
|||
import android.widget.TextView; |
|||
|
|||
import androidx.fragment.app.DialogFragment; |
|||
|
|||
import com.gmeremit.online.gmeremittance_native.R; |
|||
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.PasswordPromptListener; |
|||
|
|||
public class PasswordPromptDialog extends DialogFragment implements View.OnClickListener { |
|||
|
|||
|
|||
private EditText passwordEditText; |
|||
|
|||
private TextView okButton,cancelButton; |
|||
private PasswordPromptListener listener; |
|||
|
|||
|
|||
@Override |
|||
public Dialog onCreateDialog(Bundle savedInstanceState) { |
|||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
|||
View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_password_prompt, null); |
|||
|
|||
passwordEditText = view.findViewById(R.id.login_password); |
|||
cancelButton = view.findViewById(R.id.btn_cancel); |
|||
okButton=view.findViewById(R.id.btn_ok); |
|||
|
|||
builder.setView(view); |
|||
initialize(); |
|||
|
|||
Dialog d= builder.create(); |
|||
d.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); |
|||
|
|||
return d; |
|||
|
|||
|
|||
} |
|||
|
|||
private void initialize() { |
|||
cancelButton.setOnClickListener(this); |
|||
setCancelable(false); |
|||
okButton.setOnClickListener(this); |
|||
|
|||
|
|||
} |
|||
|
|||
public void setListener(PasswordPromptListener listener) { |
|||
this.listener = listener; |
|||
} |
|||
|
|||
|
|||
|
|||
@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_white_bg_with_inset); |
|||
|
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onResume() { |
|||
super.onResume(); |
|||
// showKeyBoard(passwordEditText); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void onClick(View v) { |
|||
switch (v.getId()) { |
|||
case R.id.btn_cancel: |
|||
hideKeyboard(); |
|||
dismiss(); |
|||
if(listener!=null) |
|||
listener.onCancelled(); |
|||
break; |
|||
case R.id.btn_ok: |
|||
hideKeyboard(); |
|||
dismiss(); |
|||
if(listener!=null) |
|||
listener.onPasswordSubmit(passwordEditText.getText().toString()); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onDismiss(DialogInterface dialog) { |
|||
super.onDismiss(dialog); |
|||
cancelButton.setOnClickListener(null); |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
public void hideKeyboard() { |
|||
// Check if no view has focus: |
|||
try { |
|||
View view = getActivity().getCurrentFocus(); |
|||
|
|||
InputMethodManager inputManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); |
|||
inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); |
|||
} |
|||
catch(Exception ex) |
|||
{ |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
@SuppressWarnings("HardCodedStringLiteral") |
|||
public void showKeyBoard(View view) { |
|||
try { |
|||
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); |
|||
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); |
|||
Log.d("GMEEXCEPTION", "Keyboard shown"); |
|||
} catch (NullPointerException e) { |
|||
Log.d("GMEEXCEPTION", "Null pointer while showing keyboard"); |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
@ -1,6 +0,0 @@ |
|||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt; |
|||
|
|||
public interface PasswordPromptListener { |
|||
void onPasswordSubmit(String password); |
|||
void onCancelled(); |
|||
} |
@ -1,29 +0,0 @@ |
|||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.gateway; |
|||
|
|||
import com.gmeremit.online.gmeremittance_native.GmeApplication; |
|||
import com.gmeremit.online.gmeremittance_native.base.PrefKeys; |
|||
import com.gmeremit.online.gmeremittance_native.base.PrivilegedGateway; |
|||
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter.TransactionPasswordPromptV2InteractorInterface; |
|||
import com.gmeremit.online.gmeremittance_native.utils.https.HttpClientV2; |
|||
import com.google.gson.JsonObject; |
|||
|
|||
import io.reactivex.Observable; |
|||
import okhttp3.ResponseBody; |
|||
|
|||
import static com.gmeremit.online.gmeremittance_native.base.PrefKeys.APP_FINGER_PRINT_ENABLED; |
|||
import static com.gmeremit.online.gmeremittance_native.base.PrefKeys.APP_USER_SECRET_KEY; |
|||
|
|||
public class TransactionPasswordPromptV2Gateway extends PrivilegedGateway implements TransactionPasswordPromptV2InteractorInterface.TransactionPasswordPromptV2GatewayInterface { |
|||
|
|||
|
|||
@Override |
|||
public Observable<ResponseBody> requestOtp(String auth, String Uid,String amount,String kftcId) { |
|||
JsonObject jsonObject=new JsonObject(); |
|||
jsonObject.addProperty("kftcId",kftcId); |
|||
jsonObject.addProperty("amount",amount); |
|||
jsonObject.addProperty("userId",Uid); |
|||
|
|||
return HttpClientV2.getInstance().requestOTPForSendMoney(auth,jsonObject); |
|||
} |
|||
|
|||
} |
@ -1,16 +0,0 @@ |
|||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter; |
|||
|
|||
import com.gmeremit.online.gmeremittance_native.base.BaseInteractorInterface; |
|||
import com.gmeremit.online.gmeremittance_native.base.PrivilegedGatewayInterface; |
|||
|
|||
import io.reactivex.Observable; |
|||
import okhttp3.ResponseBody; |
|||
|
|||
public interface TransactionPasswordPromptV2InteractorInterface extends BaseInteractorInterface { |
|||
|
|||
interface TransactionPasswordPromptV2GatewayInterface extends PrivilegedGatewayInterface |
|||
{ |
|||
Observable<ResponseBody> requestOtp(String auth, String Uid,String amount,String kftc); |
|||
|
|||
} |
|||
} |
@ -1,273 +0,0 @@ |
|||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter; |
|||
|
|||
import android.os.Build; |
|||
import android.security.keystore.KeyPermanentlyInvalidatedException; |
|||
import android.util.Log; |
|||
|
|||
import com.gmeremit.online.gmeremittance_native.R; |
|||
import com.gmeremit.online.gmeremittance_native.base.BasePresenter; |
|||
import com.gmeremit.online.gmeremittance_native.customwidgets.CustomAlertDialog; |
|||
import com.gmeremit.online.gmeremittance_native.utils.Constants; |
|||
import com.gmeremit.online.gmeremittance_native.utils.https.GenericApiObserverResponseV2; |
|||
import com.gmeremit.online.gmeremittance_native.utils.https.GenericResponseDataModel; |
|||
import com.gmeremit.online.gmeremittance_native.utils.https.MessageResponseDataModel; |
|||
import com.gmeremit.online.gmeremittance_native.security.utils.SecurityUtils; |
|||
import com.mtramin.rxfingerprint.data.BiometricExceptions; |
|||
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 TransactionPasswordPromptV2Presenter extends BasePresenter implements TransactionPasswordPromptV2PresenterInterface, TransactionPasswordPromptV2InteractorInterface { |
|||
|
|||
private final TransactionPasswordPromptV2PresenterInterface.TransactionPasswordPromptV2ContractInterface view; |
|||
private final TransactionPasswordPromptV2InteractorInterface.TransactionPasswordPromptV2GatewayInterface gateway; |
|||
private final CompositeDisposable compositeDisposable; |
|||
private final String selectedPaymentType; |
|||
private long updateCountdownValue; |
|||
private String selectedAmount; |
|||
private String selectedKftcId; |
|||
private Disposable fingerPrintScanningSubscription; |
|||
private boolean isKeyPermanentlyInvalidated = false; |
|||
|
|||
public TransactionPasswordPromptV2Presenter(TransactionPasswordPromptV2PresenterInterface.TransactionPasswordPromptV2ContractInterface view,TransactionPasswordPromptV2InteractorInterface.TransactionPasswordPromptV2GatewayInterface gateway, String paymentType) { |
|||
this.view = view; |
|||
this.gateway = gateway; |
|||
this.compositeDisposable = new CompositeDisposable(); |
|||
this.updateCountdownValue = -1; |
|||
this.selectedKftcId = ""; |
|||
this.selectedAmount = ""; |
|||
this.selectedPaymentType = paymentType; |
|||
|
|||
} |
|||
|
|||
|
|||
@Override |
|||
public void getOtp() { |
|||
if (updateCountdownValue == -1) { |
|||
this.compositeDisposable.add( |
|||
this.gateway.requestOtp(this.gateway.getAuth(), this.gateway.getUserID(), selectedAmount, selectedKftcId) |
|||
.doOnSubscribe(disposable -> view.showProgressBar(true, getStringfromStringId(R.string.requesting_otp_text))) |
|||
.doFinally(() -> view.showProgressBar(false, "")) |
|||
.subscribeOn(Schedulers.io()) |
|||
.observeOn(AndroidSchedulers.mainThread()) |
|||
.subscribeWith(new ResendRequestObserver()) |
|||
); |
|||
} else { |
|||
view.showResendRequestView(false); |
|||
view.startCountdownView(updateCountdownValue); |
|||
} |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void updateCountdown(long millisUntilFinished) { |
|||
this.updateCountdownValue = millisUntilFinished; |
|||
} |
|||
|
|||
@Override |
|||
public long getLatestCountDownValue() { |
|||
return updateCountdownValue; |
|||
} |
|||
|
|||
@Override |
|||
public void updateSelectedAmount(String selectedAmount) { |
|||
if (selectedAmount == null) |
|||
selectedAmount = ""; |
|||
this.selectedAmount = selectedAmount; |
|||
} |
|||
|
|||
@Override |
|||
public void updateSelectedKftcId(String selectedKftcId) { |
|||
if (selectedKftcId == null) |
|||
selectedKftcId = ""; |
|||
this.selectedKftcId = selectedKftcId; |
|||
} |
|||
|
|||
@Override |
|||
public boolean checkIfUserHasEnabledBiometricAuth() { |
|||
return false; |
|||
// return SecurityUtils.checkFingerPrintUsablity(view.getContext()) && gateway.isFingerPrintAuthEnabled() && gateway.getPersistedUserId() != null && gateway.getPersistedUserPwd() != null; |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public void startObservingFingerPrintIfRequired(boolean action) { |
|||
if (!checkIfUserHasEnabledBiometricAuth()) { |
|||
view.addFingerprintIcon(false); |
|||
return; |
|||
} |
|||
if (!action) { |
|||
view.clearImageView(); |
|||
if (fingerPrintScanningSubscription != null && !fingerPrintScanningSubscription.isDisposed()) |
|||
fingerPrintScanningSubscription.dispose(); |
|||
} else { |
|||
view.addFingerprintIcon(true); |
|||
fingerPrintScanningSubscription = authenticateFingerprint().subscribeWith(new FingerprintDecResultObserver()); |
|||
compositeDisposable.add(fingerPrintScanningSubscription); |
|||
} |
|||
|
|||
|
|||
} |
|||
|
|||
private Observable<FingerprintDecResult> authenticateFingerprint() { |
|||
return Observable.zip(Observable.fromCallable(gateway::getPersistedUserId), |
|||
Observable.fromCallable(gateway::getPersistedSecretKey) |
|||
.flatMap(storedKey -> decryptFromKeyStore(storedKey).flatMap(decAesKey -> SecurityUtils.decryptUsingAES(gateway.getPersistedUserPwd(), decAesKey))) |
|||
.subscribeOn(Schedulers.io()), |
|||
FingerprintDecResult::new) |
|||
.doOnSubscribe(subs -> { |
|||
view.animateFingerPrintAppearAnimationIfRequired(true); |
|||
}) |
|||
.observeOn(AndroidSchedulers.mainThread()); |
|||
} |
|||
|
|||
private Observable<String> decryptFromKeyStore(String data) { |
|||
return SecurityUtils.decryptUsingKeyStore(view.getContext(),null, data) |
|||
.flatMap(authentication -> { |
|||
switch (authentication.getResult()) { |
|||
case FAILED: |
|||
return io.reactivex.Observable.error(new SecurityUtils.FailedFingerPrintException(getStringfromStringId(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 BiometricExceptions.BiometricAuthFailedException) { |
|||
view.addFingerprintIcon(false); |
|||
// view.addSecureIcon(); |
|||
} else if (error instanceof SecurityUtils.FailedFingerPrintException || error instanceof SecurityUtils.SensorNotReadyException) { |
|||
view.animateFingerPrintAppearAnimationIfRequired(true); |
|||
view.showToastMessage(error.getMessage()); |
|||
return Observable.timer(100, TimeUnit.MILLISECONDS); |
|||
} |
|||
return Observable.error(error); |
|||
} |
|||
)) |
|||
.map(FingerprintDecryptionResult::getDecrypted); |
|||
|
|||
|
|||
} |
|||
|
|||
|
|||
@Override |
|||
public boolean checkIfRequiredOTPScreen() { |
|||
return "autodebit".equalsIgnoreCase(selectedPaymentType); |
|||
} |
|||
|
|||
@Override |
|||
public void verifyTxnType() { |
|||
if (checkIfRequiredOTPScreen()) { |
|||
view.setupAutoDebitTxnPasswordPromptView(); |
|||
view.addFingerprintIcon(false); |
|||
} else { |
|||
view.setupWalletTxnPasswordPromptView(); |
|||
if (checkIfUserHasEnabledBiometricAuth()) |
|||
view.addFingerprintIcon(true); |
|||
else view.addFingerprintIcon(false); |
|||
} |
|||
} |
|||
|
|||
|
|||
class ResendRequestObserver extends GenericApiObserverResponseV2<MessageResponseDataModel> { |
|||
|
|||
@Override |
|||
protected void onSuccess(GenericResponseDataModel<MessageResponseDataModel> response) { |
|||
if (response.getErrorCode().equalsIgnoreCase(Constants.SUCCESS_CODE_V2)) { |
|||
view.showPopUpMessage(response.getMsg(), CustomAlertDialog.AlertType.SUCCESS, alertType -> { |
|||
view.showResendRequestView(false); |
|||
view.startCountdownView(120000); |
|||
}); |
|||
} else { |
|||
view.showPopUpMessage(response.getMsg(), CustomAlertDialog.AlertType.FAILED, alertType -> { |
|||
view.showResendRequestView(true); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onFailed(String message) { |
|||
view.showPopUpMessage(message, CustomAlertDialog.AlertType.FAILED, alertType -> view.exitView()); |
|||
} |
|||
|
|||
@Override |
|||
protected void onConnectionNotEstablished(String message) { |
|||
view.showPopUpMessage(message, CustomAlertDialog.AlertType.NO_INTERNET, null); |
|||
view.showResendRequestView(true); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
protected void unauthorizedAccess(String message) { |
|||
gateway.clearAllUserData(); |
|||
view.showPopUpMessage(message, CustomAlertDialog.AlertType.ALERT, alertType -> view.logout()); |
|||
} |
|||
} |
|||
|
|||
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 "UserCredentialDecryptionResultDTO{" + |
|||
"userId='" + userId + '\'' + |
|||
", userPwd='" + userPwd + '\'' + |
|||
'}'; |
|||
} |
|||
} |
|||
|
|||
public class FingerprintDecResultObserver extends DisposableObserver<FingerprintDecResult> { |
|||
|
|||
@Override |
|||
public void onNext(FingerprintDecResult fingerprintDecResult) { |
|||
Log.d(SecurityUtils.TAG, "Success : " + fingerprintDecResult.toString()); |
|||
|
|||
view.onBiometricAuthSuccess(fingerprintDecResult.getUserPwd()); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void onError(Throwable e) { |
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && e instanceof KeyPermanentlyInvalidatedException) |
|||
{ |
|||
view.addFingerprintIcon(false); |
|||
gateway.flushBiometricData(); |
|||
view.showPopUpMessage(getStringfromStringId(R.string.fingerprint_changed_externally),CustomAlertDialog.AlertType.ALERT,null); |
|||
} |
|||
|
|||
Log.d(SecurityUtils.TAG, "Failed : " + e.getMessage()); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void onComplete() { |
|||
|
|||
} |
|||
} |
|||
} |
@ -1,46 +0,0 @@ |
|||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter; |
|||
|
|||
import android.content.Context; |
|||
|
|||
import com.gmeremit.online.gmeremittance_native.base.BaseContractInterface; |
|||
import com.gmeremit.online.gmeremittance_native.base.BasePresenterInterface; |
|||
|
|||
public interface TransactionPasswordPromptV2PresenterInterface extends BasePresenterInterface { |
|||
void getOtp(); |
|||
|
|||
void updateCountdown(long millisUntilFinished); |
|||
|
|||
long getLatestCountDownValue(); |
|||
|
|||
void updateSelectedAmount(String selectedAmount); |
|||
|
|||
void updateSelectedKftcId(String selectedKftcId); |
|||
|
|||
boolean checkIfUserHasEnabledBiometricAuth(); |
|||
|
|||
|
|||
void startObservingFingerPrintIfRequired(boolean action); |
|||
|
|||
boolean checkIfRequiredOTPScreen(); |
|||
|
|||
void verifyTxnType(); |
|||
|
|||
|
|||
interface TransactionPasswordPromptV2ContractInterface extends BaseContractInterface { |
|||
void startCountdownView(long durationMillisecond); |
|||
void showResendRequestView(boolean action); |
|||
|
|||
Context getContext(); |
|||
|
|||
void onBiometricAuthSuccess(String decPassword); |
|||
|
|||
void animateFingerPrintAppearAnimationIfRequired(boolean action); |
|||
|
|||
void setupAutoDebitTxnPasswordPromptView(); |
|||
void setupWalletTxnPasswordPromptView(); |
|||
void addFingerprintIcon(boolean action); |
|||
|
|||
void clearImageView(); |
|||
|
|||
} |
|||
} |
@ -1,240 +0,0 @@ |
|||
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 androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat; |
|||
import androidx.appcompat.app.AlertDialog; |
|||
|
|||
import android.util.Log; |
|||
import android.view.Gravity; |
|||
import android.view.View; |
|||
import android.widget.ImageView; |
|||
import android.widget.TextView; |
|||
import android.widget.Toast; |
|||
|
|||
import androidx.fragment.app.DialogFragment; |
|||
|
|||
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.security.utils.SecurityUtils; |
|||
import com.mtramin.rxfingerprint.data.BiometricExceptions; |
|||
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 DialogFragment { |
|||
|
|||
|
|||
private AnimatedVectorDrawableCompat fingerPrintAVDCompat; |
|||
private ImageView passwordPromptImageView; |
|||
private Disposable fingerPrintScanningSubscription; |
|||
private CompositeDisposable compositeDisposable; |
|||
private BiometricPromptResultListener listener; |
|||
private View cancelTxt; |
|||
|
|||
|
|||
@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); |
|||
cancelTxt = view.findViewById(R.id.cancel_txt); |
|||
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_fp); |
|||
|
|||
} |
|||
|
|||
public void setResultListener(BiometricPromptResultListener listener) { |
|||
this.listener = listener; |
|||
} |
|||
|
|||
@Override |
|||
public void onStart() { |
|||
super.onStart(); |
|||
startObservingFingerPrintIfRequired(true); |
|||
cancelTxt.setOnClickListener(new View.OnClickListener() { |
|||
@Override |
|||
public void onClick(View v) { |
|||
dismiss(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
@Override |
|||
public void onStop() { |
|||
super.onStop(); |
|||
startObservingFingerPrintIfRequired(false); |
|||
cancelTxt.setOnClickListener(null); |
|||
} |
|||
|
|||
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.decryptUsingAES(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.decryptUsingKeyStore(getActivity(),null, 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 "UserCredentialDecryptionResultDTO{" + |
|||
"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 BiometricExceptions.BiometricAuthFailedException) { |
|||
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,453 +0,0 @@ |
|||
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.view; |
|||
|
|||
import android.annotation.SuppressLint; |
|||
import android.app.Activity; |
|||
import android.content.Context; |
|||
import android.content.Intent; |
|||
import android.content.pm.ActivityInfo; |
|||
import android.graphics.Rect; |
|||
import android.os.Build; |
|||
import android.os.Bundle; |
|||
import android.os.CountDownTimer; |
|||
import android.os.Handler; |
|||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat; |
|||
import androidx.core.content.ContextCompat; |
|||
import androidx.core.view.GestureDetectorCompat; |
|||
import androidx.appcompat.app.AppCompatDelegate; |
|||
import android.text.Spannable; |
|||
import android.text.SpannableString; |
|||
import android.text.style.ForegroundColorSpan; |
|||
import android.view.GestureDetector; |
|||
import android.view.MotionEvent; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.view.Window; |
|||
import android.widget.FrameLayout; |
|||
import android.widget.ImageView; |
|||
import android.widget.RelativeLayout; |
|||
import android.widget.TextView; |
|||
|
|||
import com.gmeremit.online.gmeremittance_native.R; |
|||
import com.gmeremit.online.gmeremittance_native.base.BaseActivity; |
|||
import com.gmeremit.online.gmeremittance_native.customwidgets.GmeErrorTextView; |
|||
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.gateway.TransactionPasswordPromptV2Gateway; |
|||
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter.TransactionPasswordPromptV2Presenter; |
|||
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.presenter.TransactionPasswordPromptV2PresenterInterface; |
|||
import com.gmeremit.online.gmeremittance_native.security.securitykeypad.SecurityKeyboardManager; |
|||
import com.gmeremit.online.gmeremittance_native.security.securitykeypad.SecurityKeyboardView; |
|||
import com.gmeremit.online.gmeremittance_native.security.securitykeypad.SecurityKeypadRequestParamBuilder; |
|||
import com.softsecurity.transkey.TransKeyActivity; |
|||
|
|||
import java.util.Locale; |
|||
|
|||
import butterknife.BindView; |
|||
import butterknife.ButterKnife; |
|||
|
|||
public class TransactionPasswordPromptActivity extends BaseActivity implements SecurityKeyboardView.SecurityKeyboardFocusStateListener, TransactionPasswordPromptV2PresenterInterface.TransactionPasswordPromptV2ContractInterface, View.OnClickListener { |
|||
|
|||
static { |
|||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); |
|||
} |
|||
|
|||
public static final String OTP_COUNTDOWN_VALUE = "bundleCountdownValue"; |
|||
SecurityKeyboardManager securityKeyboardManager; |
|||
|
|||
@BindView(R.id.securityKeyboard) |
|||
SecurityKeyboardView securityKeyboardView; |
|||
|
|||
@BindView(R.id.keypadContainer) |
|||
FrameLayout keypadContainer; |
|||
|
|||
@BindView(R.id.keypadBallon) |
|||
RelativeLayout ballonView; |
|||
|
|||
@BindView(R.id.title) |
|||
TextView title; |
|||
|
|||
@BindView(R.id.resend_request) |
|||
TextView resendRequest; |
|||
|
|||
@BindView(R.id.rootView) |
|||
View rootView; |
|||
|
|||
@BindView(R.id.passwordPromptImageView) |
|||
ImageView passwordPromptImageView; |
|||
|
|||
@BindView(R.id.orTextView) |
|||
TextView orTextView; |
|||
|
|||
|
|||
@BindView(R.id.passwordErrorTxt) |
|||
GmeErrorTextView passwordErrorTxt; |
|||
private SecurityKeypadListener securityKeypadListener; |
|||
private GestureDetectorCompat gestureDetector; |
|||
private TransactionPasswordPromptActivityGestureDetector myViewGestureDetector; |
|||
|
|||
|
|||
public static final String TRANSACTION_PWD_ENC_DATA = "bundleKeyEncData"; |
|||
public static final String PAYMENT_TYPE_BUNDLE_KEY = "bundleKeyPaymentType"; |
|||
public static final String SELECTED_AMT_FOR_OTP_BUNDLE_KEY = "bundleKeySelectedAmtOtp"; |
|||
public static final String SELECTED_KFTC_ID_FOR_OTP_BUNDLE_KEY = "bundleKeySelectedKFTCId"; |
|||
// private String paymentType; |
|||
private TransactionPasswordPromptV2PresenterInterface presenter; |
|||
private CountDownTimer countDownTimer; |
|||
private AnimatedVectorDrawableCompat fingerPrintAVDCompat; |
|||
|
|||
|
|||
@Override |
|||
protected void onCreate(Bundle savedInstanceState) { |
|||
enableActivityToTakeScreenShot(false); |
|||
super.onCreate(savedInstanceState); |
|||
setContentView(R.layout.activity_transaction_password_prompt); |
|||
ButterKnife.bind(this); |
|||
setUpWindowWithInsets(); |
|||
preInit(); |
|||
init(); |
|||
performDefaultAction(savedInstanceState); |
|||
} |
|||
|
|||
private void setUpWindowWithInsets() { |
|||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O||Build.VERSION.SDK_INT==Build.VERSION_CODES.O_MR1) { |
|||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); |
|||
} else { |
|||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); |
|||
} |
|||
|
|||
Window window = getWindow(); |
|||
if (window != null) { |
|||
window.getAttributes().windowAnimations = R.style.SlideInAnimation; |
|||
window.setBackgroundDrawableResource(R.drawable.ic_rounded_password_prompt_activity_bg); |
|||
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); |
|||
} |
|||
} |
|||
|
|||
private void preInit() { |
|||
presenter = new TransactionPasswordPromptV2Presenter(this,new TransactionPasswordPromptV2Gateway(), getIntent().getStringExtra(PAYMENT_TYPE_BUNDLE_KEY)); |
|||
if (presenter.checkIfRequiredOTPScreen()) { |
|||
presenter.updateCountdown(getIntent().getLongExtra(OTP_COUNTDOWN_VALUE, -1)); |
|||
presenter.updateSelectedAmount(getIntent().getStringExtra(SELECTED_AMT_FOR_OTP_BUNDLE_KEY)); |
|||
presenter.updateSelectedKftcId(getIntent().getStringExtra(SELECTED_KFTC_ID_FOR_OTP_BUNDLE_KEY)); |
|||
} |
|||
else |
|||
resendRequest.setVisibility(View.GONE); |
|||
} |
|||
|
|||
private void init() { |
|||
securityKeyboardView.setKeyboardContainerView(keypadContainer); |
|||
securityKeyboardView.setKeyboardBallonView(ballonView); |
|||
securityKeypadListener = new SecurityKeypadListener(); |
|||
myViewGestureDetector = new TransactionPasswordPromptActivityGestureDetector(); |
|||
gestureDetector = new GestureDetectorCompat(this, myViewGestureDetector); |
|||
|
|||
try { |
|||
securityKeyboardManager = new SecurityKeyboardManager(this); |
|||
SecurityKeypadRequestParamBuilder request = new SecurityKeypadRequestParamBuilder(this); |
|||
request.disableKeyPadEffect(false); |
|||
presenter.verifyTxnType(); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
|
|||
private void performDefaultAction(Bundle savedInstanceState) { |
|||
securityKeyboardManager.showKeyboard(); |
|||
if (presenter.checkIfRequiredOTPScreen()) { |
|||
new Handler().postDelayed(() -> { |
|||
presenter.getOtp(); |
|||
}, 400); |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
@Override |
|||
public boolean dispatchTouchEvent(MotionEvent ev) { |
|||
return (securityKeyboardView.checkIfTouchIntersectKeypadLayout(ev) || gestureDetector.onTouchEvent(ev) || super.dispatchTouchEvent(ev)); |
|||
|
|||
} |
|||
|
|||
private boolean checkIfTouchOutsiedRootView(float x, float y) { |
|||
int posX = (int) x; |
|||
int posY = (int) y; |
|||
|
|||
int[] rootViewLeftAndTopCoordinates = new int[2]; |
|||
rootView.getLocationOnScreen(rootViewLeftAndTopCoordinates); |
|||
Rect rootViewBoundRect = new Rect(rootViewLeftAndTopCoordinates[0], rootViewLeftAndTopCoordinates[1], |
|||
rootViewLeftAndTopCoordinates[0] + rootView.getMeasuredWidth(), |
|||
rootViewLeftAndTopCoordinates[1] + rootView.getMeasuredHeight()); |
|||
|
|||
return !rootViewBoundRect.contains(posX, posY); |
|||
} |
|||
|
|||
@Override |
|||
protected void onStart() { |
|||
super.onStart(); |
|||
securityKeyboardView.setSecurityKeyboardFocusStateListener(this); |
|||
if (presenter.checkIfRequiredOTPScreen()) |
|||
resendRequest.setOnClickListener(this); |
|||
else |
|||
presenter.startObservingFingerPrintIfRequired(true); |
|||
} |
|||
|
|||
@Override |
|||
protected void onStop() { |
|||
super.onStop(); |
|||
securityKeyboardView.setSecurityKeyboardFocusStateListener(null); |
|||
if (presenter.checkIfRequiredOTPScreen()) |
|||
resendRequest.setOnClickListener(null); |
|||
else |
|||
presenter.startObservingFingerPrintIfRequired(false); |
|||
} |
|||
|
|||
@Override |
|||
protected void onResume() { |
|||
super.onResume(); |
|||
} |
|||
|
|||
@Override |
|||
protected void onPause() { |
|||
super.onPause(); |
|||
|
|||
} |
|||
|
|||
@SuppressLint("NewApi") |
|||
@Override |
|||
public void animateFingerPrintAppearAnimationIfRequired(boolean action) { |
|||
if (action) { |
|||
if (fingerPrintAVDCompat != null && !fingerPrintAVDCompat.isRunning()) { |
|||
passwordPromptImageView.setImageDrawable(fingerPrintAVDCompat); |
|||
fingerPrintAVDCompat.start(); |
|||
} |
|||
|
|||
} else { |
|||
passwordPromptImageView.setImageDrawable(null); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void setupAutoDebitTxnPasswordPromptView() { |
|||
SecurityKeypadRequestParamBuilder request = new SecurityKeypadRequestParamBuilder(this); |
|||
request.disableKeyPadEffect(false); |
|||
request.setKeypadType(TransKeyActivity.mTK_TYPE_KEYPAD_NUMBER); |
|||
request.setHintString(getString(R.string.otp_password_hint_text)); |
|||
title.setText(getString(R.string.enter_otp_password_text)); |
|||
request.setMaxLength(4); |
|||
ballonView.setVisibility(View.INVISIBLE); |
|||
securityKeyboardManager.bindWithSecurityWidgetView(securityKeyboardView) |
|||
.setBallonView(ballonView) |
|||
.setKeyboardContainer(keypadContainer) |
|||
.setRequestParams(request) |
|||
.setActionListener(securityKeypadListener) |
|||
.build(); |
|||
} |
|||
|
|||
@Override |
|||
public void setupWalletTxnPasswordPromptView() { |
|||
SecurityKeypadRequestParamBuilder request = new SecurityKeypadRequestParamBuilder(this); |
|||
request.disableKeyPadEffect(false); |
|||
request.setHintString(getString(R.string.password_text)); |
|||
title.setText(getString(R.string.enter_login_password_text)); |
|||
resendRequest.setVisibility(View.INVISIBLE); |
|||
securityKeyboardManager.bindWithSecurityWidgetView(securityKeyboardView) |
|||
.setBallonView(ballonView) |
|||
.setKeyboardContainer(keypadContainer) |
|||
.setRequestParams(request) |
|||
.setActionListener(securityKeypadListener) |
|||
.build(); |
|||
} |
|||
|
|||
@Override |
|||
public void addFingerprintIcon(boolean action) { |
|||
if (action) { |
|||
orTextView.setVisibility(View.VISIBLE); |
|||
passwordPromptImageView.setImageResource(0); |
|||
passwordPromptImageView.setImageDrawable(null); |
|||
if (fingerPrintAVDCompat == null) |
|||
fingerPrintAVDCompat = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_fp); |
|||
} else { |
|||
orTextView.setVisibility(View.GONE); |
|||
fingerPrintAVDCompat = null; |
|||
passwordPromptImageView.setImageResource(0); |
|||
passwordPromptImageView.setImageDrawable(null); |
|||
passwordPromptImageView.setImageResource(R.drawable.ic_penny_test_pending); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void clearImageView() { |
|||
passwordPromptImageView.setImageResource(0); |
|||
passwordPromptImageView.setImageDrawable(null); |
|||
} |
|||
|
|||
@Override |
|||
public void onSecurityViewRecievedFocus() { |
|||
if (securityKeyboardManager != null && !securityKeyboardManager.isKeyboardVisible()) |
|||
securityKeyboardManager.showKeyboard(); |
|||
} |
|||
|
|||
@Override |
|||
public void onSecurityViewLostFocus() { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void startCountdownView(long durationMillisecond) { |
|||
countDownTimer = new CountDownTimer(durationMillisecond, 1000) { |
|||
|
|||
int redColor = ContextCompat.getColor(TransactionPasswordPromptActivity.this, R.color.colorPrimary); |
|||
int grayColor = ContextCompat.getColor(TransactionPasswordPromptActivity.this, R.color.darkgray2); |
|||
|
|||
@Override |
|||
public void onTick(long millisUntilFinished) { |
|||
presenter.updateCountdown(millisUntilFinished); |
|||
int seconds = (int) (millisUntilFinished / 1000); |
|||
|
|||
int hours = seconds / (60 * 60); |
|||
int tempMint = (seconds - (hours * 60 * 60)); |
|||
int minutes = tempMint / 60; |
|||
seconds = tempMint - (minutes * 60); |
|||
|
|||
String timeRemaining = String.format(Locale.US, "%02d", minutes) |
|||
+ ":" + String.format(Locale.US, "%02d", seconds); |
|||
|
|||
Spannable tryInText = new SpannableString(getString(R.string.resend_code_text)); |
|||
tryInText.setSpan(new ForegroundColorSpan(grayColor), 0, tryInText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
|||
resendRequest.setText(tryInText); |
|||
|
|||
Spannable timeText = new SpannableString(" " + timeRemaining); |
|||
timeText.setSpan(new ForegroundColorSpan(redColor), 0, timeText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
|||
|
|||
resendRequest.append(timeText); |
|||
} |
|||
|
|||
@Override |
|||
public void onFinish() { |
|||
showResendRequestView(true); |
|||
presenter.updateCountdown(-1); |
|||
} |
|||
|
|||
|
|||
}; |
|||
countDownTimer.start(); |
|||
} |
|||
|
|||
private void updateIntentOnCanellationAndFinish() { |
|||
boolean result = presenter.checkIfRequiredOTPScreen(); |
|||
if (result) { |
|||
Intent backIntent = new Intent(); |
|||
setResult(RESULT_CANCELED, backIntent); |
|||
backIntent.putExtra(OTP_COUNTDOWN_VALUE, presenter.getLatestCountDownValue()); |
|||
} |
|||
finish(); |
|||
} |
|||
|
|||
@Override |
|||
public void showResendRequestView(boolean action) { |
|||
if (resendRequest.getVisibility() != View.VISIBLE) |
|||
resendRequest.setVisibility(View.VISIBLE); |
|||
if (action) { |
|||
if (countDownTimer != null) |
|||
countDownTimer.cancel(); |
|||
presenter.updateCountdown(-1); |
|||
resendRequest.setText(getString(R.string.resend_request_text)); |
|||
resendRequest.setOnClickListener(this); |
|||
|
|||
} else { |
|||
resendRequest.setText(""); |
|||
resendRequest.setOnClickListener(null); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Context getContext() { |
|||
return this; |
|||
} |
|||
|
|||
@Override |
|||
public void onBiometricAuthSuccess(String decPassword) { |
|||
Intent returnIntent = new Intent(); |
|||
returnIntent.putExtra(TRANSACTION_PWD_ENC_DATA, decPassword); |
|||
setResult(Activity.RESULT_OK, returnIntent); |
|||
finish(); |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public void onBackPressed() { |
|||
updateIntentOnCanellationAndFinish(); |
|||
} |
|||
|
|||
@Override |
|||
public void onClick(View v) { |
|||
switch (v.getId()) { |
|||
case R.id.resend_request: |
|||
this.presenter.getOtp(); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
class SecurityKeypadListener implements SecurityKeyboardManager.SecurityKeyboardActionListenerFacade { |
|||
@Override |
|||
public void done(Intent intent) { |
|||
String encData = intent.getStringExtra(TransKeyActivity.mTK_PARAM_SECURE_DATA); |
|||
if (validateStringNotEmpty(encData)) { |
|||
passwordErrorTxt.setErrorText(null); |
|||
Intent returnIntent = new Intent(); |
|||
returnIntent.putExtra(TRANSACTION_PWD_ENC_DATA, encData); |
|||
setResult(Activity.RESULT_OK, returnIntent); |
|||
finish(); |
|||
} else { |
|||
if (presenter.checkIfRequiredOTPScreen()) |
|||
passwordErrorTxt.setErrorText(getString(R.string.otp_empty_error)); |
|||
else |
|||
passwordErrorTxt.setErrorText(getString(R.string.password_empty_error)); |
|||
if (securityKeyboardManager != null && !securityKeyboardManager.isKeyboardVisible()) |
|||
securityKeyboardManager.showKeyboard(); |
|||
} |
|||
|
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void cancel(Intent intent) { |
|||
updateIntentOnCanellationAndFinish(); |
|||
} |
|||
|
|||
private boolean validateStringNotEmpty(String data) { |
|||
return (data != null && data.length() > 0); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void input(int i) { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void minTextSizeCallback() { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void maxTextSizeCallback() { |
|||
|
|||
} |
|||
} |
|||
|
|||
class TransactionPasswordPromptActivityGestureDetector extends GestureDetector.SimpleOnGestureListener { |
|||
@Override |
|||
public boolean onSingleTapUp(MotionEvent e) { |
|||
if (e.getAction() == MotionEvent.ACTION_UP) { |
|||
|
|||
boolean hasToucheOutsideTheView = checkIfTouchOutsiedRootView(e.getX(), e.getY()); |
|||
if (hasToucheOutsideTheView) |
|||
updateIntentOnCanellationAndFinish(); |
|||
return hasToucheOutsideTheView; |
|||
} |
|||
return super.onSingleTapUp(e); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue