diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index c80bfbe5..324d6691 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index e1248073..a58fde13 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -5,7 +5,7 @@ # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html -# If your project uses WebView with JS, uncomment the following +# If your project uses WebView withCountdownTimer JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 83f9ae0d..c2df6ee7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -190,7 +190,7 @@ android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@mipmap/ic_launcher" /> { if (bitmap != null) { @@ -535,7 +535,7 @@ public class CustomerDetailFragment extends BaseFragment implements KYCV3Present } - //Error data binding with corresponding view elements in the form. + //Error data binding withCountdownTimer corresponding view elements in the form. private void subscribeToCustomerRelatedDataError(KYCV3ViewModel kycv3ViewModel) { kycv3ViewModel.getCustomerDetailRelatedFormErrorLiveData().getFullNameErrorLiveData().observe(getViewLifecycleOwner(), error -> fullNameWrapper.setError(error)); kycv3ViewModel.getCustomerDetailRelatedFormErrorLiveData().getGenderErrorLiveData().observe(getViewLifecycleOwner(), error -> genderListWrapper.setError(error)); diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/loginV2/presenter/LoginV2Presenter.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/loginV2/presenter/LoginV2Presenter.java index 654ac725..4d1c0c3f 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/loginV2/presenter/LoginV2Presenter.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/loginV2/presenter/LoginV2Presenter.java @@ -8,7 +8,8 @@ import com.gmeremit.online.gmeremittance_native.customwidgets.CustomAlertDialog; import com.gmeremit.online.gmeremittance_native.loginV2.gateway.LoginV2Gateway; import com.gmeremit.online.gmeremittance_native.loginV2.model.LoginModelV2; import com.gmeremit.online.gmeremittance_native.security.GMEAuthManager; -import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthFailedResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthSuccessResult; import com.gmeremit.online.gmeremittance_native.security.utils.SecurityUtils; import com.gmeremit.online.gmeremittance_native.utils.Constants; import com.gmeremit.online.gmeremittance_native.utils.https.GenericApiObserverResponse; @@ -84,14 +85,15 @@ public class LoginV2Presenter extends BasePresenter implements LoginV2PresenterI GMEAuthManager.getGmeAuthManager((AppCompatActivity) view.getContext()).requestBiometricAuth() .setListener(new GMEAuthManager.GMEAuthListener() { @Override - public void onGMEAuthSuccess(GMEAuthResult result) { + public void onGMEAuthSuccess(GMEAuthSuccessResult result) { encUserPassword =result.getResult(); view.onLoginPerformTask(() -> loginUser(gateway.getPersistedUserId())); } @Override - public void onGMEAuthFailed(String errorReason) { - view.showToastMessage(errorReason); + public void onGMEAuthFailed(GMEAuthFailedResult failedResult) { + view.showFingerPrintScanner(failedResult.isRecoverable()); + view.showToastMessage(failedResult.getFailedReason()); } @Override diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/profile/view/profilechange/UserEmailChangeActivity.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/profile/view/profilechange/UserEmailChangeActivity.java index d7775ccc..49c6fcc5 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/profile/view/profilechange/UserEmailChangeActivity.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/profile/view/profilechange/UserEmailChangeActivity.java @@ -12,8 +12,8 @@ import com.gmeremit.online.gmeremittance_native.profile.ProfileChangeViewModelFa import com.gmeremit.online.gmeremittance_native.profile.presenter.profilechange.ProfileChangePresenterInterface; import com.gmeremit.online.gmeremittance_native.profile.presenter.profilechange.ProfileChangeViewModel; import com.gmeremit.online.gmeremittance_native.security.GMEAuthManager; -import com.gmeremit.online.gmeremittance_native.security.auth.profilescreen.GMEUserProfileChangeOTPRequestBottomSheetDialog; -import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthFailedResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthSuccessResult; import com.gmeremit.online.gmeremittance_native.security.model.GMEScreenBasedParam; import com.gmeremit.online.gmeremittance_native.utils.Utils; import com.jakewharton.rxbinding3.widget.RxTextView; @@ -71,12 +71,12 @@ public class UserEmailChangeActivity extends BaseActivity implements ProfileChan public void updateEmail() { GMEAuthManager.getGmeAuthManager(this).requestAuthPerScreenExplicitly(GMEScreenBasedParam.forPasswordUserProfile()).setListener(new GMEAuthManager.GMEAuthListener() { @Override - public void onGMEAuthSuccess(GMEAuthResult result) { + public void onGMEAuthSuccess(GMEAuthSuccessResult result) { viewModel.proceeedToChangeCredential(edTxtEmail.getText().toString(), result.getResult()); } @Override - public void onGMEAuthFailed(String errorReason) { + public void onGMEAuthFailed(GMEAuthFailedResult failedResult) { } @@ -93,13 +93,13 @@ public class UserEmailChangeActivity extends BaseActivity implements ProfileChan GMEAuthManager.getGmeAuthManager(this).requestAuthPerScreenExplicitly(GMEScreenBasedParam.forOTPSubmitUserProfile(targetValue,-1)) .setListener(new GMEAuthManager.GMEAuthListener() { @Override - public void onGMEAuthSuccess(GMEAuthResult result) { + public void onGMEAuthSuccess(GMEAuthSuccessResult result) { viewModel.proceeedToOTPVerification(result.getResult(),targetValue); } @Override - public void onGMEAuthFailed(String errorReason) { + public void onGMEAuthFailed(GMEAuthFailedResult failedResult) { } diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/profile/view/profilechange/UserMobileChangeActivity.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/profile/view/profilechange/UserMobileChangeActivity.java index 9faab4ff..4390b4a7 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/profile/view/profilechange/UserMobileChangeActivity.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/profile/view/profilechange/UserMobileChangeActivity.java @@ -12,8 +12,8 @@ import com.gmeremit.online.gmeremittance_native.profile.ProfileChangeViewModelFa import com.gmeremit.online.gmeremittance_native.profile.presenter.profilechange.ProfileChangePresenterInterface; import com.gmeremit.online.gmeremittance_native.profile.presenter.profilechange.ProfileChangeViewModel; import com.gmeremit.online.gmeremittance_native.security.GMEAuthManager; -import com.gmeremit.online.gmeremittance_native.security.auth.profilescreen.GMEUserProfileChangeOTPRequestBottomSheetDialog; -import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthFailedResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthSuccessResult; import com.gmeremit.online.gmeremittance_native.security.model.GMEScreenBasedParam; import com.jakewharton.rxbinding3.widget.RxTextView; @@ -72,12 +72,12 @@ public class UserMobileChangeActivity extends BaseActivity implements ProfileCha GMEAuthManager.getGmeAuthManager(this).requestAuthPerScreenExplicitly(GMEScreenBasedParam.forPasswordUserProfile()).setListener(new GMEAuthManager.GMEAuthListener() { @Override - public void onGMEAuthSuccess(GMEAuthResult result) { + public void onGMEAuthSuccess(GMEAuthSuccessResult result) { viewModel.proceeedToChangeCredential(edTxtMobile.getText().toString(), result.getResult()); } @Override - public void onGMEAuthFailed(String errorReason) { + public void onGMEAuthFailed(GMEAuthFailedResult failedResult) { } @@ -94,13 +94,13 @@ public class UserMobileChangeActivity extends BaseActivity implements ProfileCha GMEAuthManager.getGmeAuthManager(UserMobileChangeActivity.this).requestAuthPerScreenExplicitly(GMEScreenBasedParam.forOTPSubmitUserProfile(targetValue,-1)) .setListener(new GMEAuthManager.GMEAuthListener() { @Override - public void onGMEAuthSuccess(GMEAuthResult secret) { + public void onGMEAuthSuccess(GMEAuthSuccessResult secret) { viewModel.proceeedToOTPVerification(secret.getResult(),targetValue); } @Override - public void onGMEAuthFailed(String errorReason) { + public void onGMEAuthFailed(GMEAuthFailedResult failedResult) { } diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/push_notifications/NotificationHelper.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/push_notifications/NotificationHelper.java index a7be3305..83bf9bb6 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/push_notifications/NotificationHelper.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/push_notifications/NotificationHelper.java @@ -70,7 +70,7 @@ public class NotificationHelper extends ContextWrapper { * * @param title Title for notification. * @param body Message for notification. - * @return A Notification.Builder configured with the selected channel and details + * @return A Notification.Builder configured withCountdownTimer the selected channel and details */ @RequiresApi(api = Build.VERSION_CODES.O) public Notification.Builder getNotification2(String title, String body) { @@ -105,7 +105,7 @@ public class NotificationHelper extends ContextWrapper { /** * Get the notification manager. * - * Utility method as this helper works with it a lot. + * Utility method as this helper works withCountdownTimer it a lot. * * @return The system service NotificationManager */ diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/model/recipientlistingV3/ReceiverInfoV3Model.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/model/recipientlistingV3/ReceiverInfoV3Model.java index 6d7364a3..9795e896 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/model/recipientlistingV3/ReceiverInfoV3Model.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/model/recipientlistingV3/ReceiverInfoV3Model.java @@ -399,7 +399,7 @@ public class ReceiverInfoV3Model implements Parcelable { AgentV3Model agentV3Model = new AgentV3Model(); agentV3Model.setId(selectedBank.getId()); - //If current agent if not null, bind existing account number with new Bank data + //If current agent if not null, bind existing account number withCountdownTimer new Bank data if (agent != null) agentV3Model.setAccountNo(agent.getAccountNo()); diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/RecipientDetailValidatorV3.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/RecipientDetailValidatorV3.java index f8902420..03ca7e4d 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/RecipientDetailValidatorV3.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/RecipientDetailValidatorV3.java @@ -1087,7 +1087,7 @@ public class RecipientDetailValidatorV3 { switch (rule.getField()) { - //Enforcing dynamic validating rule with drop down value bankList's isBranchRequired + //Enforcing dynamic validating rule withCountdownTimer drop down value bankList's isBranchRequired case FIELD_BRANCH_NAME: if (rule.isFieldRequired()) { if (recipientInfo.getAgent() != null && recipientInfo.getAgent().getId() != null) { @@ -1102,7 +1102,7 @@ public class RecipientDetailValidatorV3 { } break; - //Enforcing dynamic validating rule with drop down value bankList's isAccountRequired + //Enforcing dynamic validating rule withCountdownTimer drop down value bankList's isAccountRequired case FIELD_ACCOUNT_NO: if (rule.isFieldRequired()) { if (recipientInfo.getAgent() != null && recipientInfo.getAgent().getId() != null) { diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/add/RecipientAddV3Presenter.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/add/RecipientAddV3Presenter.java index f4de14a3..49c21ef7 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/add/RecipientAddV3Presenter.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/add/RecipientAddV3Presenter.java @@ -29,7 +29,7 @@ import io.reactivex.disposables.CompositeDisposable; import io.reactivex.schedulers.Schedulers; /** - * Add Recipient Use Case, override any base class callback to adjust with the add use case flow. Base case will handle default flow. + * Add Recipient Use Case, override any base class callback to adjust withCountdownTimer the add use case flow. Base case will handle default flow. */ public class RecipientAddV3Presenter extends RecipientAddEditBaseV3Presenter { diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/edit/RecipientEditV3Presenter.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/edit/RecipientEditV3Presenter.java index 888bba69..9e190296 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/edit/RecipientEditV3Presenter.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/recipientV3/presenter/recipientaddeditV3/edit/RecipientEditV3Presenter.java @@ -37,7 +37,7 @@ import io.reactivex.disposables.CompositeDisposable; import io.reactivex.schedulers.Schedulers; /** - * Edit Recipient Use Case, override any base class callback to adjust with the edit use case flow. Base case will handle default flow. + * Edit Recipient Use Case, override any base class callback to adjust withCountdownTimer the edit use case flow. Base case will handle default flow. */ public class RecipientEditV3Presenter extends RecipientAddEditBaseV3Presenter { diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/ReSendMoneyActionListener.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/ReSendMoneyActionListener.java index 96ff13b7..f9243b65 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/ReSendMoneyActionListener.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/resendV2/ReSendMoneyActionListener.java @@ -4,7 +4,7 @@ import com.gmeremit.online.gmeremittance_native.resendV2.presenter.resend.ReSend /** * Created by Preyea - * Interface to bind send money indivisual transaction view with the contained activity. + * Interface to bind send money indivisual transaction view withCountdownTimer the contained activity. */ public interface ReSendMoneyActionListener { diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/reward_points/presenter/RewardsPointPresenter.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/reward_points/presenter/RewardsPointPresenter.java index dee81130..1b3d1819 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/reward_points/presenter/RewardsPointPresenter.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/reward_points/presenter/RewardsPointPresenter.java @@ -52,7 +52,7 @@ public class RewardsPointPresenter implements RewardPointsContract.IPresenter, R } /** - * Displaying No Internet Message with Dismissing Progress depending on Page + * Displaying No Internet Message withCountdownTimer Dismissing Progress depending on Page * * @param page String */ @@ -71,7 +71,7 @@ public class RewardsPointPresenter implements RewardPointsContract.IPresenter, R } /** - * Handle Submit Click with Id passed + * Handle Submit Click withCountdownTimer Id passed * Depending on Condition of Shipping Address TextField * Tells view to show Progress * On Condition to be true, Tells Model to send Reward type With Address passing Shipping Address and Id diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/GMEAuthManager.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/GMEAuthManager.java index 3ecdbfd3..f290e3e5 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/GMEAuthManager.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/GMEAuthManager.java @@ -1,16 +1,18 @@ package com.gmeremit.online.gmeremittance_native.security; import android.content.SharedPreferences; +import android.os.Handler; +import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; 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.auth.GMETxnOTPRequestBottomSheetDialog; import com.gmeremit.online.gmeremittance_native.security.auth.GMEUserPasswordPromptBottomSheetDialog; import com.gmeremit.online.gmeremittance_native.security.auth.profilescreen.GMEUserProfileChangeOTPRequestBottomSheetDialog; -import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthFailedResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthSuccessResult; import com.gmeremit.online.gmeremittance_native.security.model.GMEScreenBasedParam; import com.gmeremit.online.gmeremittance_native.security.model.GMETxnParam; import com.gmeremit.online.gmeremittance_native.security.utils.SecurityUtils; @@ -66,17 +68,17 @@ public class GMEAuthManager { public GMEAuthManager fromPaymentSource(GMETxnParam gmeTxnParam) { - this.gmeTxnParam=gmeTxnParam; - if(gmeTxnParam==null) + this.gmeTxnParam = gmeTxnParam; + if (gmeTxnParam == null) throw new IllegalArgumentException("Txn Param cannot be null"); if ("wallet".equalsIgnoreCase(gmeTxnParam.getPaymentSource())) if (checkIfUserHasEnabledBiometric()) - gmeTxnParam.setGmeTxnAuthType( GMETxnParam.GMETxnAuthType.BIOMETRIC); + gmeTxnParam.setGmeTxnAuthType(GMETxnParam.GMETxnAuthType.BIOMETRIC); else - gmeTxnParam.setGmeTxnAuthType( GMETxnParam.GMETxnAuthType.PASSWORD); + gmeTxnParam.setGmeTxnAuthType(GMETxnParam.GMETxnAuthType.PASSWORD); else if ("autodebit".equalsIgnoreCase(gmeTxnParam.getPaymentSource())) - gmeTxnParam.setGmeTxnAuthType( GMETxnParam.GMETxnAuthType.OTP); + gmeTxnParam.setGmeTxnAuthType(GMETxnParam.GMETxnAuthType.OTP); return this; @@ -103,7 +105,6 @@ public class GMEAuthManager { } - public void prompt() { if (gmeScreenBasedParam != null) { startPerScreenBasedAuth(); @@ -129,12 +130,12 @@ public class GMEAuthManager { private void returnInvalidRequest() { if (listener != null) - listener.onGMEAuthFailed("Unknown auth requested.\n" + INVALID_REQUEST); + listener.onGMEAuthFailed(new GMEAuthFailedResult("Unknown auth requested.\n" + INVALID_REQUEST)); } private void returnSecretOnly(String secret) { if (listener != null) - listener.onGMEAuthSuccess(new GMEAuthResult(secret)); + listener.onGMEAuthSuccess(new GMEAuthSuccessResult(secret)); } private void showUserPasswordPrompt() { @@ -142,7 +143,6 @@ public class GMEAuthManager { } private void showBiometricAuthPrompt() { - biometricAuthenticateAndReturnUserCredentialOnSuccess() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -155,20 +155,26 @@ public class GMEAuthManager { @Override public void onNext(String userSecret) { if (listener != null) - listener.onGMEAuthSuccess(new GMEAuthResult(userSecret,true)); + listener.onGMEAuthSuccess(new GMEAuthSuccessResult(userSecret, true)); } @Override public void onError(Throwable e) { -// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && e instanceof KeyPermanentlyInvalidatedException) { -// gateway.flushBiometricData(); -// view.showPopUpMessage(getStringfromStringId(R.string.fingerprint_changed_externally), CustomAlertDialog.AlertType.ALERT, null); -// } + if (listener != null) { if (e instanceof BiometricExceptions.BiometricAuthUserCancelledException) listener.onGMEAuthCancelled(); + else if (e instanceof BiometricExceptions.BiometricAuthNonRecoverableException) { + if(gmeTxnParam!=null&&gmeTxnParam.isFallbackAuthEnabled()) { + Toast.makeText(context, "Fingerprint authentication is not available at the moment. Please use the password instead", Toast.LENGTH_LONG).show(); + new Handler().postDelayed(() -> showUserPasswordPrompt(), 500); + } + else + listener.onGMEAuthFailed(new GMEAuthFailedResult(e.getMessage())); + } else if(e instanceof BiometricExceptions.BiometricAuthRecoverableException) + listener.onGMEAuthFailed(new GMEAuthFailedResult(e.getMessage(),true)); else - listener.onGMEAuthFailed(e.toString()); + listener.onGMEAuthFailed(new GMEAuthFailedResult(e.getMessage())); } } @@ -191,22 +197,7 @@ public class GMEAuthManager { private Observable decryptByKeyStore(String data) { return SecurityUtils.decryptUsingKeyStore(context, data) - .flatMap(authentication -> { - switch (authentication.getResult()) { - case FAILED: - return io.reactivex.Observable.error(new SecurityUtils.FailedFingerPrintException(context.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())); - } - - }) .map(FingerprintDecryptionResult::getDecrypted); - - } private void showOTPTxnPrompt() { @@ -218,10 +209,10 @@ public class GMEAuthManager { @Override public void onCancelled() { - if(listener!=null) + if (listener != null) listener.onGMEAuthCancelled(); } - }).show(context.getSupportFragmentManager(),GMETxnOTPRequestBottomSheetDialog.class.getSimpleName()); + }).show(context.getSupportFragmentManager(), GMETxnOTPRequestBottomSheetDialog.class.getSimpleName()); } @@ -287,9 +278,9 @@ public class GMEAuthManager { public interface GMEAuthListener { - void onGMEAuthSuccess(GMEAuthResult result); + void onGMEAuthSuccess(GMEAuthSuccessResult successResult); - void onGMEAuthFailed(String errorReason); + void onGMEAuthFailed(GMEAuthFailedResult failedResult); void onGMEAuthCancelled(); } diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMEAuthFailedResult.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMEAuthFailedResult.java new file mode 100644 index 00000000..4f042334 --- /dev/null +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMEAuthFailedResult.java @@ -0,0 +1,27 @@ +package com.gmeremit.online.gmeremittance_native.security.model; + +public class GMEAuthFailedResult { + + private String failedReason; + private boolean isRecoverable; + + public GMEAuthFailedResult(String failedReason) { + this.failedReason = failedReason; + isRecoverable=false; + } + + public GMEAuthFailedResult(String failedReason,boolean isRecoverable) { + this.failedReason = failedReason; + this.isRecoverable=isRecoverable; + } + + + + public String getFailedReason() { + return failedReason; + } + + public boolean isRecoverable() { + return isRecoverable; + } +} diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMEAuthResult.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMEAuthSuccessResult.java similarity index 73% rename from app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMEAuthResult.java rename to app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMEAuthSuccessResult.java index 7a063e6d..4e4d9033 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMEAuthResult.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMEAuthSuccessResult.java @@ -1,17 +1,17 @@ package com.gmeremit.online.gmeremittance_native.security.model; -public class GMEAuthResult { +public class GMEAuthSuccessResult { private String result; private boolean isBiometricUsed; - public GMEAuthResult(String result) + public GMEAuthSuccessResult(String result) { this.result=result; this.isBiometricUsed=false; } - public GMEAuthResult(String result,boolean isBiometricUsed) + public GMEAuthSuccessResult(String result, boolean isBiometricUsed) { this.result=result; this.isBiometricUsed=isBiometricUsed; diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMETxnParam.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMETxnParam.java index 9a2d6bb3..471cb480 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMETxnParam.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/model/GMETxnParam.java @@ -2,25 +2,38 @@ package com.gmeremit.online.gmeremittance_native.security.model; public class GMETxnParam { - String paymentSource; - String selectedAmount; - String kftcId; - long countDownValue; - GMETxnAuthType gmeTxnAuthType; + private String paymentSource; + private String selectedAmount; + private String kftcId; + private long countDownValue; + private GMETxnAuthType gmeTxnAuthType; + private boolean enableFallbackOption; public GMETxnParam(String paymentSource, String selectedAmount, String kftcId) { this.paymentSource=paymentSource; this.selectedAmount = selectedAmount; this.kftcId = kftcId; this.countDownValue=12000; + this.enableFallbackOption=false; } - public GMETxnParam with(long countDownValue) + public GMETxnParam withCountdownTimer(long countDownValue) { this.countDownValue=countDownValue; return this; } + public GMETxnParam enableFallbackAuth() + { + this.enableFallbackOption=true; + return this; + } + + public boolean isFallbackAuthEnabled() + { + return this.enableFallbackOption; + } + public static GMETxnParam forBiometricAuth() { GMETxnParam gmeTxnParam=new GMETxnParam(null,null,null); diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/securitykeypad/SecurityKeyboardManager.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/securitykeypad/SecurityKeyboardManager.java index 99496d8f..2238ab5e 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/securitykeypad/SecurityKeyboardManager.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/securitykeypad/SecurityKeyboardManager.java @@ -16,7 +16,7 @@ import com.softsecurity.transkey.TransKeyCtrl; /** * @author Preyea R. Regmi - *

Helper class to interact with virtual security keypad SDK.

+ *

Helper class to interact withCountdownTimer virtual security keypad SDK.

*

* The used virtual security keypad is just a view that can be inflated in any ViewGroup. This class provides overall encapsulation of all the related element provided by * the Virtual Keypad SDK in order to mimick OS like keyboard behavior. This allows us to show/hide keypad in the same Activity from where it is invoked thus providing better UX. diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/utils/AESEncryptionHelper.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/utils/AESEncryptionHelper.java index 61256e96..6af0cd48 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/utils/AESEncryptionHelper.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/utils/AESEncryptionHelper.java @@ -209,12 +209,12 @@ public class AESEncryptionHelper { */ /** - * Generates a random IV and encrypts this plain text with the given key. Then attaches + * Generates a random IV and encrypts this plain text withCountdownTimer the given key. Then attaches * a hashed MAC, which is contained in the CipherTextIvMac class. * * @param plaintext The text that will be encrypted, which - * will be serialized with UTF-8 - * @param secretKeys The AES and HMAC keys with which to encryptUsingAES + * will be serialized withCountdownTimer UTF-8 + * @param secretKeys The AES and HMAC keys withCountdownTimer which to encryptUsingAES * @return a tuple of the IV, ciphertext, mac * @throws GeneralSecurityException if AES is not implemented on this system * @throws UnsupportedEncodingException if UTF-8 is not supported in this system @@ -225,11 +225,11 @@ public class AESEncryptionHelper { } /** - * Generates a random IV and encrypts this plain text with the given key. Then attaches + * Generates a random IV and encrypts this plain text withCountdownTimer the given key. Then attaches * a hashed MAC, which is contained in the CipherTextIvMac class. * * @param plaintext The bytes that will be encrypted - * @param secretKeys The AES and HMAC keys with which to encryptUsingAES + * @param secretKeys The AES and HMAC keys withCountdownTimer which to encryptUsingAES * @return a tuple of the IV, ciphertext, mac * @throws GeneralSecurityException if AES is not implemented on this system * @throws UnsupportedEncodingException if the specified encoding is invalid @@ -240,11 +240,11 @@ public class AESEncryptionHelper { } /** - * Generates a random IV and encrypts this plain text with the given key. Then attaches + * Generates a random IV and encrypts this plain text withCountdownTimer the given key. Then attaches * a hashed MAC, which is contained in the CipherTextIvMac class. * * @param plaintext The text that will be encrypted - * @param secretKeys The combined AES and HMAC keys with which to encryptUsingAES + * @param secretKeys The combined AES and HMAC keys withCountdownTimer which to encryptUsingAES * @return a tuple of the IV, ciphertext, mac * @throws GeneralSecurityException if AES is not implemented on this system */ @@ -672,7 +672,7 @@ public class AESEncryptionHelper { // Insert and check the provider atomically. // The official Android Java libraries use synchronized methods for // insertProviderAt, etc., so synchronizing on the class should - // make things more stable, and prevent race conditions with other + // make things more stable, and prevent race conditions withCountdownTimer other // versions of this code. synchronized (java.security.Security.class) { if ((secureRandomProviders == null) @@ -836,7 +836,7 @@ public class AESEncryptionHelper { if (sUrandomIn == null) { // NOTE: Consider inserting a BufferedInputStream // between DataInputStream and FileInputStream if you need - // higher PRNG output performance and can live with future PRNG + // higher PRNG output performance and can live withCountdownTimer future PRNG // output being pulled into this process prematurely. try { sUrandomIn = new DataInputStream(new FileInputStream(URANDOM_FILE)); diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/utils/SecurityUtils.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/utils/SecurityUtils.java index 90ff520d..7e024871 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/utils/SecurityUtils.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/security/utils/SecurityUtils.java @@ -15,11 +15,11 @@ import io.reactivex.Observable; * @version 1.0 *

Security Utils Helper Class For Biometric Auth

*

- * Since we are using security keypad with Symmetric Key Encryption, we can only obtain encrypted text as password but not plain text. + * Since we are using security keypad withCountdownTimer Symmetric Key Encryption, we can only obtain encrypted text as password but not plain text. * So the length of the encrypted text exceeds 256 bit and we cannot use Public/Private Encryption Algorithm i.e. RSA encryption offfered by Android's KeyStore. * Therefore inorder to persist password and encryption key in same storage using Android's Keystore mechanism, we follow the following steps

* 1) We generate AES key seperately using "AESEncryptionHelper" class if not already generated intially. - * 2) Encrypt the confidential content with the AES Algorithm using the generated AES key and persist it. + * 2) Encrypt the confidential content withCountdownTimer the AES Algorithm using the generated AES key and persist it. * 3) That AES key is then encrypted using RSA key provided by Keystore and persist it to prevent from being exploited. * * So we can store the encryption key and encrypted data in same persistence storage without any risk. @@ -33,7 +33,7 @@ import io.reactivex.Observable; * Encrypted_AES_KEY = RSA_ENCRYPTION_USING_KEYSTORE(Generated_AES_Key) * SAVE_TO_DISK(Encrypted_AES_KEY); * - * Hence, we can persist both the key and encrypted data in same place with help of Android Key Store. + * Hence, we can persist both the key and encrypted data in same place withCountdownTimer help of Android Key Store. * */ diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/presenter/SendMoneyV2Presenter.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/presenter/SendMoneyV2Presenter.java index 256028d0..662a0295 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/presenter/SendMoneyV2Presenter.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/presenter/SendMoneyV2Presenter.java @@ -1,11 +1,8 @@ package com.gmeremit.online.gmeremittance_native.sendmoneyV2.presenter; -import android.util.Log; - import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; -import com.crashlytics.android.Crashlytics; import com.gmeremit.online.gmeremittance_native.R; import com.gmeremit.online.gmeremittance_native.accountmanage.model.accountlisting.AutoDebitAccount; import com.gmeremit.online.gmeremittance_native.accountmanage.model.accountlisting.WebRequestModel; @@ -18,7 +15,8 @@ import com.gmeremit.online.gmeremittance_native.exrate.model.datav2.ExchangeCalc import com.gmeremit.online.gmeremittance_native.homeV2.model.UserInfoModelV2; import com.gmeremit.online.gmeremittance_native.recipientV3.model.recipientlistingV3.ReceiverInfoV3Model; import com.gmeremit.online.gmeremittance_native.security.GMEAuthManager; -import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthFailedResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthSuccessResult; import com.gmeremit.online.gmeremittance_native.security.model.GMETxnParam; import com.gmeremit.online.gmeremittance_native.security.utils.SecurityUtils; import com.gmeremit.online.gmeremittance_native.sendmoneyV2.model.SendMoneyAPIRequestBody; @@ -34,8 +32,6 @@ import com.gmeremit.online.gmeremittance_native.sendmoneyV2.model.payoutmode.Pay import com.gmeremit.online.gmeremittance_native.sendmoneyV2.model.payoutmode.PayoutModeApiResponse; import com.gmeremit.online.gmeremittance_native.sendmoneyV2.model.verification.VerificationViewModel; import com.gmeremit.online.gmeremittance_native.sendmoneyV2.view.amountdetail.AmountDetailSendMoneyFragment; -import com.gmeremit.online.gmeremittance_native.transactionpasspromt.PasswordPromptListener; -import com.gmeremit.online.gmeremittance_native.transactionpasspromt.view.TransactionBiometricPromptDialog; import com.gmeremit.online.gmeremittance_native.utils.Constants; import com.gmeremit.online.gmeremittance_native.utils.Utils; import com.gmeremit.online.gmeremittance_native.utils.https.GenericApiObserverResponse; @@ -225,16 +221,16 @@ public class SendMoneyV2Presenter extends BaseViewModel implements SendMoneyV2Pr getPaymentType(), getTransactionAmount(), getKftcId() - ).with(countDownRemainingValue) + ).enableFallbackAuth().withCountdownTimer(countDownRemainingValue) ).setListener(new GMEAuthManager.GMEAuthListener() { @Override - public void onGMEAuthSuccess(GMEAuthResult result) { + public void onGMEAuthSuccess(GMEAuthSuccessResult result) { performSendMoneyTransaction(result.getResult(), result.isBiometricUsed()); } @Override - public void onGMEAuthFailed(String errorReason) { - view.showToastMessage(errorReason); + public void onGMEAuthFailed(GMEAuthFailedResult failedResult) { + view.showToastMessage(failedResult.getFailedReason()); } @Override diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/view/SendMoneyActionListener.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/view/SendMoneyActionListener.java index 10a88c19..e3d8aeb7 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/view/SendMoneyActionListener.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/sendmoneyV2/view/SendMoneyActionListener.java @@ -6,7 +6,7 @@ import com.gmeremit.online.gmeremittance_native.sendmoneyV2.presenter.SendMoneyV /** * Created by Preyea - * Interface to bind send money indivisual transaction view with the contained activity. + * Interface to bind send money indivisual transaction view withCountdownTimer the contained activity. */ public interface SendMoneyActionListener { diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/settings/view/SettingsView.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/settings/view/SettingsView.java index 709a97d5..0628555e 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/settings/view/SettingsView.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/settings/view/SettingsView.java @@ -1,9 +1,8 @@ package com.gmeremit.online.gmeremittance_native.settings.view; import android.content.Intent; -import android.content.SharedPreferences; import android.os.Bundle; -import android.os.Handler; + import androidx.annotation.Nullable; import androidx.appcompat.widget.SwitchCompat; import android.view.View; @@ -16,12 +15,12 @@ import com.gmeremit.online.gmeremittance_native.base.PrefKeys; import com.gmeremit.online.gmeremittance_native.profile.view.profilechange.UserPasswordChangeV2Activity; import com.gmeremit.online.gmeremittance_native.customwidgets.CustomAlertDialog; import com.gmeremit.online.gmeremittance_native.security.GMEAuthManager; -import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthFailedResult; +import com.gmeremit.online.gmeremittance_native.security.model.GMEAuthSuccessResult; import com.gmeremit.online.gmeremittance_native.settings.adapter.LanguageSelectionDialogRVAdapter; import com.gmeremit.online.gmeremittance_native.settings.gateway.LanguageSelectionGateway; import com.gmeremit.online.gmeremittance_native.settings.gateway.LanguageSelectionGatewayInterface; import com.gmeremit.online.gmeremittance_native.splash_screen.model.LanguageModel; -import com.gmeremit.online.gmeremittance_native.security.utils.SecurityUtils; import butterknife.BindView; import butterknife.ButterKnife; @@ -147,7 +146,7 @@ public class SettingsView extends BaseActivity implements CompoundButton.OnCheck gmeAuthManager.requestBiometricAuth().setListener(new GMEAuthManager.GMEAuthListener() { @Override - public void onGMEAuthSuccess(GMEAuthResult result) { + public void onGMEAuthSuccess(GMEAuthSuccessResult result) { GmeApplication.getStorage().edit().putBoolean(PrefKeys.APP_FINGER_PRINT_ENABLED, isChecked).apply(); view_fingerprint.setOnCheckedChangeListener(null); view_fingerprint.setChecked(isChecked); @@ -155,18 +154,9 @@ public class SettingsView extends BaseActivity implements CompoundButton.OnCheck } @Override - public void onGMEAuthFailed(String errorReason) { - view_fingerprint.setOnCheckedChangeListener(null); - view_fingerprint.setChecked(false); - view_fingerprint.setOnCheckedChangeListener(SettingsView.this); + public void onGMEAuthFailed(GMEAuthFailedResult failedResult) { + showToastMessage(failedResult.getFailedReason()); -// new Handler().postDelayed(() -> { -// GmeApplication.getStorage().edit().clear().apply(); -// showPopUpMessage(getString(R.string.fingerprint_changed_externally), CustomAlertDialog.AlertType.ALERT, -// alert -> { -// logout(); -// }); -// }, 200); } @Override diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/socials/presenter/SocialPresenter.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/socials/presenter/SocialPresenter.java index 59ff6c88..600af2f5 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/socials/presenter/SocialPresenter.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/socials/presenter/SocialPresenter.java @@ -103,7 +103,7 @@ public class SocialPresenter implements SocialContract.SocialPresenter, SocialCo /*** * This method requests to create a new feed in the social wall * @param newFeedRequest - * newFeedRequest is the object body with all data to create a new Feed + * newFeedRequest is the object body withCountdownTimer all data to create a new Feed */ @Override @@ -114,13 +114,13 @@ public class SocialPresenter implements SocialContract.SocialPresenter, SocialCo /*** * This method requests to update a feed of the social wall * @param newFeedRequest - * newFeedRequest is the object body with all updated data to update an existing Feed + * newFeedRequest is the object body withCountdownTimer all updated data to update an existing Feed */ /*** * This method requests to update a feed of the social wall * @param newFeedRequest - * newFeedRequest is the object body with all updated data to update an existing Feed + * newFeedRequest is the object body withCountdownTimer all updated data to update an existing Feed * @param feedId * feedId is the id of feed to be updated */ @@ -178,7 +178,7 @@ public class SocialPresenter implements SocialContract.SocialPresenter, SocialCo * Access Type is the key which determines if the feed is tobe shown in private wall only or both public and private * This method is used to change the Access Type of the feed * @param newFeedRequest - * newFeedRequest is the feed request body with the required data + * newFeedRequest is the feed request body withCountdownTimer the required data * @param feedId * feedId is the id of feed to be deleted * @param wall @@ -241,7 +241,7 @@ public class SocialPresenter implements SocialContract.SocialPresenter, SocialCo /*** * This method updates the comment that has been made in social post * @param commentUpdateRequest - * commentUpdateRequest is the comment request body with the required data to update the comment + * commentUpdateRequest is the comment request body withCountdownTimer the required data to update the comment * @param feedId * feedId is the id of that specific post * @param commentId @@ -255,7 +255,7 @@ public class SocialPresenter implements SocialContract.SocialPresenter, SocialCo /*** * This method is used to create a new comment on the specific post * @param commentUpdateRequest - * commentUpdateRequest is the comment request body with the required data to add new comment + * commentUpdateRequest is the comment request body withCountdownTimer the required data to add new comment * @param feedId * feedId is the id of that specific post */ diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/user_profile/presenter/UserProfilePresenter.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/user_profile/presenter/UserProfilePresenter.java index b6ee00a7..afa9a7b8 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/user_profile/presenter/UserProfilePresenter.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/user_profile/presenter/UserProfilePresenter.java @@ -100,7 +100,7 @@ public class UserProfilePresenter implements UserProfileContract.UserProfilePres /*** * This function is called when the requested user profile returns success * @param body - * It runs with the UserProfile object model + * It runs withCountdownTimer the UserProfile object model */ @Override @@ -112,7 +112,7 @@ public class UserProfilePresenter implements UserProfileContract.UserProfilePres /*** * This function is called when the requested user profile returns failure * @param statusErrorReturn - * It runs with the APIRequestErrorReturn object model + * It runs withCountdownTimer the APIRequestErrorReturn object model */ @Override public void onFailureUserProfile(APIRequestErrorReturn statusErrorReturn) { @@ -271,7 +271,7 @@ public class UserProfilePresenter implements UserProfileContract.UserProfilePres /* Update Password */ /*** - * This method checks if password matches with the confirm password + * This method checks if password matches withCountdownTimer the confirm password * It requests the password reset API */ @Override @@ -295,7 +295,7 @@ public class UserProfilePresenter implements UserProfileContract.UserProfilePres /*** * This method requests for the kyc source of fund field update * @param kycUserProfile - * KycUserProfile is object with updated data for request body + * KycUserProfile is object withCountdownTimer updated data for request body * @param id * id is the userId of current logged in user */ diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/user_profile/view/ProfileActivity.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/user_profile/view/ProfileActivity.java index b8c16079..2826ecc6 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/user_profile/view/ProfileActivity.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/user_profile/view/ProfileActivity.java @@ -332,12 +332,12 @@ public class ProfileActivity extends AppCompatActivity implements UserProfileCon public void onSuccessProfilePicUpload(String documentUrl) { profileImage.setImageBitmap(bitmap); persistenceStorageManager.setImageUrl(documentUrl); -// Picasso.with(this).load(documentUrl).into(profileImage); +// Picasso.withCountdownTimer(this).load(documentUrl).into(profileImage); // Utility.showImageFromServer(this, profileImage, documentUrl); // profileImage.setImageResource(R.drawable.ic_gme_logo_white); -// Glide.with(this).load(documentUrl).into(profileImage); +// Glide.withCountdownTimer(this).load(documentUrl).into(profileImage); // profileImage.setImageBitmap(null); -// Picasso.with(this).load(documentUrl)..into(profileImage); +// Picasso.withCountdownTimer(this).load(documentUrl)..into(profileImage); } @Override diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/FileUtils.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/FileUtils.java index 6517cbfe..82ee9da9 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/FileUtils.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/FileUtils.java @@ -494,7 +494,7 @@ public class FileUtils { /** * Get the Intent for selecting content to be used in an Intent Chooser. * - * @return The intent for opening a file with Intent.createChooser() + * @return The intent for opening a file withCountdownTimer Intent.createChooser() * @author paulburke */ public static Intent createGetContentIntent() { @@ -502,7 +502,7 @@ public class FileUtils { final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); // The MIME data type filter intent.setType("*/*"); - // Only return URIs that can be opened with ContentResolver + // Only return URIs that can be opened withCountdownTimer ContentResolver intent.addCategory(Intent.CATEGORY_OPENABLE); return intent; } diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/KeyboardUtils.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/KeyboardUtils.java index dd7310da..37094282 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/KeyboardUtils.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/KeyboardUtils.java @@ -101,7 +101,7 @@ public class KeyboardUtils implements ViewTreeObserver.OnGlobalLayoutListener /** * Force closes the soft keyboard - * @param activeView the view with the keyboard focus + * @param activeView the view withCountdownTimer the keyboard focus */ public static void forceCloseKeyboard(View activeView) { diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/LocalStorageProvider.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/LocalStorageProvider.java index 4c4fb3c7..a2ad5729 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/LocalStorageProvider.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/LocalStorageProvider.java @@ -54,7 +54,7 @@ public class LocalStorageProvider extends DocumentsProvider { @Override public Cursor queryRoots(final String[] projection) throws FileNotFoundException { - // Create a cursor with either the requested fields, or the default + // Create a cursor withCountdownTimer either the requested fields, or the default // projection if "projection" is null. final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_ROOT_PROJECTION); @@ -70,7 +70,7 @@ public class LocalStorageProvider extends DocumentsProvider { // These columns are optional row.add(Root.COLUMN_AVAILABLE_BYTES, homeDir.getFreeSpace()); // Root.COLUMN_MIME_TYPE is another optional column and useful if you - // have multiple roots with different + // have multiple roots withCountdownTimer different // types of mime types (roots that don't match the requested mime type // are automatically hidden) return result; @@ -145,7 +145,7 @@ public class LocalStorageProvider extends DocumentsProvider { @Override public Cursor queryChildDocuments(final String parentDocumentId, final String[] projection, final String sortOrder) throws FileNotFoundException { - // Create a cursor with either the requested fields, or the default + // Create a cursor withCountdownTimer either the requested fields, or the default // projection if "projection" is null. final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION); @@ -163,7 +163,7 @@ public class LocalStorageProvider extends DocumentsProvider { @Override public Cursor queryDocument(final String documentId, final String[] projection) throws FileNotFoundException { - // Create a cursor with either the requested fields, or the default + // Create a cursor withCountdownTimer either the requested fields, or the default // projection if "projection" is null. final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION); diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/RxUtils.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/RxUtils.java index 5039dcb2..33c8f838 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/RxUtils.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/RxUtils.java @@ -52,7 +52,7 @@ public class RxUtils { Log.d("RXGPSAddress","Unformatted address: "+addresses.get(0).toString()); - address = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex() + address = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check withCountdownTimer max available address lines by getMaxAddressLineIndex() address = address.replaceAll(",", ""); if (addresses.get(0).getCountryName() != null && address.contains(addresses.get(0).getCountryName())) { address = address.replace(addresses.get(0).getCountryName(), ""); diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/Utils.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/Utils.java index e95f82b4..f6ca39be 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/Utils.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/Utils.java @@ -179,7 +179,7 @@ public class Utils { //create bitmap from view and returns it private static Bitmap getBitmapFromView(View view) { - //Define a bitmap with the same size as the view + //Define a bitmap withCountdownTimer the same size as the view Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); //Bind a canvas to it Canvas canvas = new Canvas(returnedBitmap); diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/https/GenericApiObserverResponseV2.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/https/GenericApiObserverResponseV2.java index 51c7eacf..a4e3e398 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/https/GenericApiObserverResponseV2.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/https/GenericApiObserverResponseV2.java @@ -13,7 +13,7 @@ import retrofit2.HttpException; /** * @author Preyea R. Regmi - * Abstract class to deal with network related operation + * Abstract class to deal withCountdownTimer network related operation * * @param */ @@ -31,7 +31,7 @@ public abstract class GenericApiObserverResponseV2 extends DisposableObserver /** * Since Java doesn't support Higher-Kind Generics Type as Type-Erasure occurs during compile time. - * So workaround is to supply type during runtime with help of reflection. + * So workaround is to supply type during runtime withCountdownTimer help of reflection. * Any sub class should override this method and provide corresponding type. * By default, {@link com.gmeremit.online.gmeremittance_native.utils.https.MessageResponseDataModel} type is used by the base class. * Detail Explanation on Higher-Kind Generics Type, See diff --git a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/other/Utility.java b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/other/Utility.java index e05907db..ad52d635 100644 --- a/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/other/Utility.java +++ b/app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/other/Utility.java @@ -121,7 +121,7 @@ public class Utility { imageView.setImageBitmap(image); /*ByteArrayOutputStream stream = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.PNG, 100, stream); - Glide.with(context) + Glide.withCountdownTimer(context) .load(stream.toByteArray()) .asBitmap() .centerCrop() @@ -184,7 +184,7 @@ public class Utility { extension = mime.getExtensionFromMimeType(context.getContentResolver().getType(uri)); } else { //If scheme is a File - //This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file name with spaces and special characters. + //This will replace white spaces withCountdownTimer %20 and also other special characters. This will avoid returning null values on file name withCountdownTimer spaces and special characters. extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString()); } diff --git a/app/src/test/java/com/gmeremit/online/gmeremittance_native/ValidationRuleTest.java b/app/src/test/java/com/gmeremit/online/gmeremittance_native/ValidationRuleTest.java index ff455060..18076948 100644 --- a/app/src/test/java/com/gmeremit/online/gmeremittance_native/ValidationRuleTest.java +++ b/app/src/test/java/com/gmeremit/online/gmeremittance_native/ValidationRuleTest.java @@ -78,7 +78,7 @@ public class ValidationRuleTest { Mockito.when(rule.getFieldLengthIsLessThanLowerBoundDefinedErrorMessage()).thenReturn(FIELD_LENGTH_IS_LESS_ERROR_MESSAGE); assertEquals( - "Should return lower bound error message: " + FIELD_LENGTH_IS_LESS_ERROR_MESSAGE+ " for data: "+ SOME_RANDOM_STRING_WITH_KNOWN_LENGTH +" with lower bound defined: "+FIELD_LENGTH_LOWER_BOUND, + "Should return lower bound error message: " + FIELD_LENGTH_IS_LESS_ERROR_MESSAGE+ " for data: "+ SOME_RANDOM_STRING_WITH_KNOWN_LENGTH +" withCountdownTimer lower bound defined: "+FIELD_LENGTH_LOWER_BOUND, FIELD_LENGTH_IS_LESS_ERROR_MESSAGE, rule.validateValueAndReturnErrorMessageOnFail(SOME_RANDOM_STRING_WITH_LENGTH_LESS_THAN_LOWER_BOUND) ); @@ -110,7 +110,7 @@ public class ValidationRuleTest { Mockito.when(rule.getFieldLengthIsGreaterThanUpperBoundDefinedErrorMessage()).thenReturn(FIELD_LENGTH_IS_GREATER_ERROR_MESSAGE); assertEquals( - "Should return upper bound error message. for Data: \'"+ SOME_RANDOM_STRING_WITH_LENGTH_GREATER_THAN_UPPER_BOUND +"\' length: "+SOME_RANDOM_STRING_WITH_LENGTH_GREATER_THAN_UPPER_BOUND.length()+" with upper bound defined: "+FIELD_LENGTH_UPPER_BOUND, + "Should return upper bound error message. for Data: \'"+ SOME_RANDOM_STRING_WITH_LENGTH_GREATER_THAN_UPPER_BOUND +"\' length: "+SOME_RANDOM_STRING_WITH_LENGTH_GREATER_THAN_UPPER_BOUND.length()+" withCountdownTimer upper bound defined: "+FIELD_LENGTH_UPPER_BOUND, FIELD_LENGTH_IS_GREATER_ERROR_MESSAGE, rule.validateValueAndReturnErrorMessageOnFail(SOME_RANDOM_STRING_WITH_LENGTH_GREATER_THAN_UPPER_BOUND) ); diff --git a/rxkeystore/src/main/java/com/mtramin/rxfingerprint/FingerprintObservable.java b/rxkeystore/src/main/java/com/mtramin/rxfingerprint/FingerprintObservable.java index ddc03fba..bebf3163 100644 --- a/rxkeystore/src/main/java/com/mtramin/rxfingerprint/FingerprintObservable.java +++ b/rxkeystore/src/main/java/com/mtramin/rxfingerprint/FingerprintObservable.java @@ -50,6 +50,7 @@ abstract class FingerprintObservable implements ObservableOnSubscribe { private final FingerprintApiWrapper fingerprintApiWrapper; CancellationSignal cancellationSignal; + private BiometricPrompt biometricPromptDialog; /** * Default constructor for fingerprint authentication @@ -70,6 +71,20 @@ abstract class FingerprintObservable implements ObservableOnSubscribe { return; } + showBiometricDialog(emitter,cryptoObject); + + emitter.setCancellable(new Cancellable() { + @Override + public void cancel() throws Exception { + if (cancellationSignal != null && !cancellationSignal.isCanceled()) { + cancellationSignal.cancel(); + } + } + }); + } + + private void showBiometricDialog(final ObservableEmitter emitter, final BiometricPrompt.CryptoObject cryptoObject) + { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { @@ -85,52 +100,44 @@ abstract class FingerprintObservable implements ObservableOnSubscribe { .build(); - new BiometricPrompt(FingerprintObservable.this.fingerprintApiWrapper.getContext(), ContextCompat.getMainExecutor(FingerprintObservable.this.fingerprintApiWrapper.getContext()), callback) - .authenticate(promptInfo, cryptoObject); + biometricPromptDialog= new BiometricPrompt(FingerprintObservable.this.fingerprintApiWrapper.getContext(), ContextCompat.getMainExecutor(FingerprintObservable.this.fingerprintApiWrapper.getContext()), callback); + biometricPromptDialog .authenticate(promptInfo, cryptoObject); } }); - - emitter.setCancellable(new Cancellable() { - @Override - public void cancel() throws Exception { - if (cancellationSignal != null && !cancellationSignal.isCanceled()) { - cancellationSignal.cancel(); - } - } - }); } + private BiometricPrompt.AuthenticationCallback createAuthenticationCallback(final ObservableEmitter emitter) { return new BiometricPrompt.AuthenticationCallback() { @Override public void onAuthenticationError(int errMsgId, CharSequence errString) { - Log.d("GMEAuthManager", "Error code: " + errMsgId); if (!emitter.isDisposed()) { - if (errMsgId == BiometricConstants.ERROR_USER_CANCELED || errMsgId == BiometricConstants.ERROR_NEGATIVE_BUTTON) - emitter.onError(new BiometricExceptions.BiometricAuthUserCancelledException(errString)); - else - emitter.onError(new BiometricExceptions.BiometricAuthUserCancelledException(errString)); + emitter.onError( BiometricExceptions.mapErrorCodeWithException(errMsgId,errString.toString())); } } @Override public void onAuthenticationFailed() { - Log.d("GMEAuthManager", "Auth Failed"); - - if (!emitter.isDisposed()) { - FingerprintObservable.this.onAuthenticationFailed(emitter); - } +// if (!emitter.isDisposed()) { +// emitter.onError(BiometricExceptions.mapErrorCodeWithException(-1,"")); +// +// } } + + + @Override public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) { if (!emitter.isDisposed()) { FingerprintObservable.this.onAuthenticationSucceeded(emitter, result); } } + + }; } diff --git a/rxkeystore/src/main/java/com/mtramin/rxfingerprint/RsaDecryptionObservable.java b/rxkeystore/src/main/java/com/mtramin/rxfingerprint/RsaDecryptionObservable.java index d996784d..f34d62da 100644 --- a/rxkeystore/src/main/java/com/mtramin/rxfingerprint/RsaDecryptionObservable.java +++ b/rxkeystore/src/main/java/com/mtramin/rxfingerprint/RsaDecryptionObservable.java @@ -97,18 +97,18 @@ class RsaDecryptionObservable extends FingerprintObservable "+ e.getMessage()); - Log.d("GMEAuthManager","Unable to decrypt given value. RxFingerprint is only able to decrypt values previously encrypted by RxFingerprint with the same encryption mode.", e); emitter.onError(cipherProvider.mapCipherFinalOperationException(e)); } } + @Deprecated @Override protected void onAuthenticationHelp(ObservableEmitter emitter, int helpMessageId, String helpString) { emitter.onNext(new FingerprintDecryptionResult(FingerprintResult.HELP, helpString, null)); } + @Deprecated @Override protected void onAuthenticationFailed(ObservableEmitter emitter) { emitter.onNext(new FingerprintDecryptionResult(FingerprintResult.FAILED, null, null)); diff --git a/rxkeystore/src/main/java/com/mtramin/rxfingerprint/data/BiometricExceptions.java b/rxkeystore/src/main/java/com/mtramin/rxfingerprint/data/BiometricExceptions.java index f0017632..714da155 100644 --- a/rxkeystore/src/main/java/com/mtramin/rxfingerprint/data/BiometricExceptions.java +++ b/rxkeystore/src/main/java/com/mtramin/rxfingerprint/data/BiometricExceptions.java @@ -16,18 +16,25 @@ package com.mtramin.rxfingerprint.data; +import android.util.Log; + +import androidx.biometric.BiometricConstants; + /** - * Exception that gets thrown during fingerprint authentication if it fails and cannot be recovered. + * Exception that gets thrown during fingerprint authentication contains both recoverable, non-recoverable and intentional. */ public final class BiometricExceptions { + /** + * Fingerprint auth process ended with failure. + */ public static class BiometricAuthFailedException extends Exception { private final String message; public BiometricAuthFailedException(CharSequence message) { - this.message = message.toString();; + this.message = message.toString(); } @Override @@ -36,13 +43,50 @@ public final class BiometricExceptions { } } - + /** + * User cancelled authentication process intentionally. + */ public static class BiometricAuthUserCancelledException extends Exception { private final String message; public BiometricAuthUserCancelledException(CharSequence message) { - this.message = message.toString();; + this.message = message.toString(); + } + + @Override + public String getMessage() { + return message; + } + } + + + /** + * Recoverable error occured, user can retry to use biometric for authentication again + */ + public static class BiometricAuthRecoverableException extends Exception + { + private final String message; + + public BiometricAuthRecoverableException(CharSequence message) { + this.message = message.toString(); + } + + @Override + public String getMessage() { + return message; + } + } + + /** + * Non Recoverable error occured, user cannot use biometric for authentication and need to user fallback option for authenticate + */ + public static class BiometricAuthNonRecoverableException extends Exception + { + private final String message; + + public BiometricAuthNonRecoverableException(CharSequence message) { + this.message = message.toString(); } @Override @@ -52,4 +96,108 @@ public final class BiometricExceptions { } + public static Exception mapErrorCodeWithException(int errorCode,String errorMessage) + { + Log.d("GMEAuthManager","Error code: "+errorCode+" Error message"+errorMessage); + switch(errorCode) + { + + /** + * The hardware is unavailable. Try again later. + */ + case BiometricConstants.ERROR_HW_UNAVAILABLE: + return new BiometricAuthFailedException(errorMessage); + + /** + * Error state returned when the sensor was unable to process the current image. + */ + case BiometricConstants.ERROR_UNABLE_TO_PROCESS: + return new BiometricAuthRecoverableException(errorMessage); + /** + * Error state returned when the current request has been running too long. This is intended to + * prevent programs from waiting for the biometric sensor indefinitely. The timeout is platform + * and sensor-specific, but is generally on the order of 30 seconds. + */ + case BiometricConstants.ERROR_TIMEOUT: + return new BiometricAuthRecoverableException(errorMessage); + /** + * Error state returned for operations like enrollment; the operation cannot be completed + * because there's not enough storage remaining to complete the operation. + */ + case BiometricConstants.ERROR_NO_SPACE: + return new BiometricAuthRecoverableException(errorMessage); + + /** + * The operation was canceled because the biometric sensor is unavailable. For example, this may + * happen when the user is switched, the device is locked or another pending operation prevents + * or disables it. + */ + case BiometricConstants.ERROR_CANCELED: + return new BiometricAuthRecoverableException(errorMessage); + + + /** + * The operation was canceled because the API is locked out due to too many attempts. + * This occurs after 5 failed attempts, and lasts for 30 seconds. + */ + case BiometricConstants.ERROR_LOCKOUT: + return new BiometricAuthNonRecoverableException(errorMessage); + /** + * Hardware vendors may extend this list if there are conditions that do not fall under one of + * the above categories. Vendors are responsible for providing error strings for these errors. + * These messages are typically reserved for internal operations such as enrollment, but may be + * used to express vendor errors not otherwise covered. Applications are expected to show the + * error message string if they happen, but are advised not to rely on the message id since they + * will be device and vendor-specific + */ + case BiometricConstants.ERROR_VENDOR: + return new BiometricAuthNonRecoverableException(errorMessage); + + /** + * The operation was canceled because ERROR_LOCKOUT occurred too many times. + * Biometric authentication is disabled until the user unlocks with strong authentication + * (PIN/Pattern/Password) + */ + case BiometricConstants.ERROR_LOCKOUT_PERMANENT : + return new BiometricAuthNonRecoverableException(errorMessage); + /** + * The user canceled the operation. Upon receiving this, applications should use alternate + * authentication (e.g. a password). The application should also provide the means to return to + * biometric authentication, such as a "use " button. + */ + case BiometricConstants.ERROR_USER_CANCELED: + return new BiometricAuthUserCancelledException(errorMessage); + + + /** + * The user does not have any biometrics enrolled. + */ + case BiometricConstants.ERROR_NO_BIOMETRICS: + return new BiometricAuthFailedException(errorMessage); + /** + * The device does not have a biometric sensor. + */ + case BiometricConstants.ERROR_HW_NOT_PRESENT: + return new BiometricAuthFailedException(errorMessage); + + /** + * The user pressed the negative button. + */ + case BiometricConstants.ERROR_NEGATIVE_BUTTON : + return new BiometricAuthUserCancelledException(errorMessage); + + + /** + * The device does not have pin, pattern, or password set up. + */ + case BiometricConstants.ERROR_NO_DEVICE_CREDENTIAL: + return new BiometricAuthNonRecoverableException(errorMessage); + + default: + return new BiometricAuthFailedException(errorMessage); + + } + } + + }