Browse Source

Biometric setup done

master
Preyea Regmi 5 years ago
parent
commit
4bb0fa8721
  1. BIN
      .idea/caches/build_file_checksums.ser
  2. 2
      app/build.gradle
  3. 3
      app/src/main/AndroidManifest.xml
  4. 3
      app/src/main/java/com/gmeremit/online/gmeremittance_native/base/PrefKeys.java
  5. 58
      app/src/main/java/com/gmeremit/online/gmeremittance_native/settings/view/SettingsView.java
  6. 14
      app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/gateway/TransactionPasswordPromptV2Gateway.java
  7. 4
      app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2InteractorInterface.java
  8. 49
      app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2Presenter.java
  9. 9
      app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2PresenterInterface.java
  10. 102
      app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/view/TransactionPasswordPromptActivity.java
  11. 44
      app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/security/SecurityUtils.java
  12. 6
      app/src/main/res/layout/activity_settings.xml

BIN
.idea/caches/build_file_checksums.ser

2
app/build.gradle

@ -153,7 +153,7 @@ dependencies {
implementation 'com.android.support:cardview-v7:28.0.0'
implementation 'com.theartofdev.edmodo:android-image-cropper:2.7.0'
implementation 'com.scottyab:rootbeer-lib:0.0.7'
implementation 'com.github.heasley:RxFingerprint:1.0.1'
implementation 'com.mtramin:rxfingerprint:2.2.1'
implementation project(':securitykeypad')
implementation project(':SpinnerDatePickerLib-release')
}

3
app/src/main/AndroidManifest.xml

@ -11,6 +11,9 @@
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<application
android:name=".GmeApplication"

3
app/src/main/java/com/gmeremit/online/gmeremittance_native/base/PrefKeys.java

@ -47,4 +47,7 @@ public class PrefKeys {
public static String USER_PREFERRED_LOCALE ="USER_PREFERRED_LOCALE";
public static String USER_PREFERRED_LANGUAGE ="USER_PREFERRED_LANGUAGE";
public static String USER_PREFERRED_COUNTRY_CODE ="USER_PREFERRED_COUNTRY_CODE";
public static String APP_FINGER_PRINT_ENABLED ="APP_FINGER_PRINT_ENABLED";
public static String APP_USER_SECRET_KEY ="APP_USER_SECRET_KEY";
}

58
app/src/main/java/com/gmeremit/online/gmeremittance_native/settings/view/SettingsView.java

@ -4,20 +4,32 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.View;
import com.gmeremit.online.gmeremittance_native.GmeApplication;
import com.gmeremit.online.gmeremittance_native.R;
import com.gmeremit.online.gmeremittance_native.base.BaseActivity;
import com.gmeremit.online.gmeremittance_native.base.PrefKeys;
import com.gmeremit.online.gmeremittance_native.changepasswordV2.view.ChangePasswordV2Activity;
import com.gmeremit.online.gmeremittance_native.customwidgets.CustomAlertDialog;
import com.gmeremit.online.gmeremittance_native.settings.adapter.LanguageSelectionDialogRVAdapter;
import com.gmeremit.online.gmeremittance_native.splash_screen.model.LanguageModel;
import com.gmeremit.online.gmeremittance_native.transactionpasspromt.view.TransactionPasswordPromptActivity;
import com.gmeremit.online.gmeremittance_native.utils.security.SecurityUtils;
import com.mtramin.rxfingerprint.RxFingerprint;
import com.mtramin.rxfingerprint.data.FingerprintEncryptionResult;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import static com.gmeremit.online.gmeremittance_native.base.PrefKeys.USER_PREFERRED_COUNTRY_CODE;
import static com.gmeremit.online.gmeremittance_native.base.PrefKeys.USER_PREFERRED_LANGUAGE;
@ -29,7 +41,11 @@ import static com.gmeremit.online.gmeremittance_native.base.PrefKeys.USER_PREFER
public class SettingsView extends BaseActivity {
@BindView(R.id.view_fingerprint)
View view_fingerprint;
@BindView(R.id.view_fingerprint_divider)
View view_fingerprint_divider;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -39,6 +55,11 @@ public class SettingsView extends BaseActivity {
private void init() {
ButterKnife.bind(this);
if(!SecurityUtils.doesAppHasBiometricFeature(this))
{
view_fingerprint.setVisibility(View.GONE);
view_fingerprint_divider.setVisibility(View.GONE);
}
}
@OnClick({R.id.view_change_password, R.id.iv_back, R.id.view_language, R.id.view_fingerprint})
@ -58,7 +79,7 @@ public class SettingsView extends BaseActivity {
break;
case R.id.view_fingerprint:
promptForFingerprintAuth();
mockEncryption("1234");
break;
}
}
@ -67,6 +88,41 @@ public class SettingsView extends BaseActivity {
}
private void mockEncryption(String abc) {
SecurityUtils.encryptSecret(this, abc)
.doOnSubscribe(subs->showProgressBar(true,getString(R.string.processing_request_text)))
.doFinally(()->showProgressBar(false,""))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<FingerprintEncryptionResult>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(FingerprintEncryptionResult fingerprintEncryptionResult) {
if(fingerprintEncryptionResult.isSuccess()) {
showPopUpMessage("Now you can use your fingerprint to perform transactions",CustomAlertDialog.AlertType.SUCCESS,action->GmeApplication.getStorage().edit().putString(PrefKeys.APP_USER_SECRET_KEY, fingerprintEncryptionResult.getEncrypted()).apply());
}
else
showPopUpMessage(fingerprintEncryptionResult.getMessage(),CustomAlertDialog.AlertType.FAILED,null);
}
@Override
public void onError(Throwable e) {
showPopUpMessage(e.getMessage(),CustomAlertDialog.AlertType.FAILED,null);
}
@Override
public void onComplete() {
}
});
}
private void promptLanguageSelectionDialog() {
LanguageSelectionListingDialog languageSelectionDialog = new LanguageSelectionListingDialog();

14
app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/gateway/TransactionPasswordPromptV2Gateway.java

@ -1,5 +1,6 @@
package com.gmeremit.online.gmeremittance_native.transactionpasspromt.gateway;
import com.gmeremit.online.gmeremittance_native.GmeApplication;
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;
@ -8,6 +9,9 @@ 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 {
private final TransactionPasswordPromptV2InteractorInterface interactor;
@ -25,4 +29,14 @@ public class TransactionPasswordPromptV2Gateway extends PrivilegedGateway implem
return HttpClientV2.getInstance().requestOTPForSendMoney(auth,jsonObject);
}
@Override
public boolean isFingerPrintEnabled() {
return GmeApplication.getStorage().getBoolean(APP_FINGER_PRINT_ENABLED,false);
}
@Override
public String getStoredSecretKey() {
return GmeApplication.getStorage().getString(APP_USER_SECRET_KEY,"");
}
}

4
app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2InteractorInterface.java

@ -11,5 +11,9 @@ public interface TransactionPasswordPromptV2InteractorInterface extends BaseInte
interface TransactionPasswordPromptV2GatewayInterface extends PrivilegedGatewayInterface
{
Observable<ResponseBody> requestOtp(String auth, String Uid,String amount,String kftc);
boolean isFingerPrintEnabled();
String getStoredSecretKey();
}
}

49
app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2Presenter.java

@ -8,6 +8,7 @@ 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.utils.security.SecurityUtils;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
@ -16,7 +17,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
public class TransactionPasswordPromptV2Presenter extends BasePresenter implements TransactionPasswordPromptV2PresenterInterface,TransactionPasswordPromptV2InteractorInterface {
public class TransactionPasswordPromptV2Presenter extends BasePresenter implements TransactionPasswordPromptV2PresenterInterface, TransactionPasswordPromptV2InteractorInterface {
private final TransactionPasswordPromptV2PresenterInterface.TransactionPasswordPromptV2ContractInterface view;
private final TransactionPasswordPromptV2InteractorInterface.TransactionPasswordPromptV2GatewayInterface gateway;
@ -26,29 +27,27 @@ public class TransactionPasswordPromptV2Presenter extends BasePresenter implemen
private String selectedKftcId;
public TransactionPasswordPromptV2Presenter(TransactionPasswordPromptV2PresenterInterface.TransactionPasswordPromptV2ContractInterface view) {
this.view=view;
this.gateway=new TransactionPasswordPromptV2Gateway(this);
this.view = view;
this.gateway = new TransactionPasswordPromptV2Gateway(this);
this.compositeDisposable = new CompositeDisposable();
this.updateCountdownValue =-1;
this.selectedKftcId="";
this.selectedAmount="";
this.updateCountdownValue = -1;
this.selectedKftcId = "";
this.selectedAmount = "";
}
@Override
public void getOtp() {
if(updateCountdownValue==-1) {
if (updateCountdownValue == -1) {
this.compositeDisposable.add(
this.gateway.requestOtp(this.gateway.getAuth(), this.gateway.getUserID(),selectedAmount,selectedKftcId)
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
{
} else {
view.showResendRequestView(false);
view.startCountdownView(updateCountdownValue);
}
@ -57,7 +56,7 @@ public class TransactionPasswordPromptV2Presenter extends BasePresenter implemen
@Override
public void updateCountdown(long millisUntilFinished) {
this.updateCountdownValue =millisUntilFinished;
this.updateCountdownValue = millisUntilFinished;
}
@Override
@ -67,26 +66,33 @@ public class TransactionPasswordPromptV2Presenter extends BasePresenter implemen
@Override
public void updateSelectedAmount(String selectedAmount) {
if(selectedAmount==null)
selectedAmount="";
this.selectedAmount=selectedAmount;
if (selectedAmount == null)
selectedAmount = "";
this.selectedAmount = selectedAmount;
}
@Override
public void updateSelectedKftcId(String selectedKftcId) {
if(selectedKftcId==null)
selectedKftcId="";
this.selectedKftcId=selectedKftcId;
if (selectedKftcId == null)
selectedKftcId = "";
this.selectedKftcId = selectedKftcId;
}
@Override
public boolean checkIfUserHasEnabledBiometricAuth() {
return true;
// return gateway.isFingerPrintEnabled()&&SecurityUtils.doesAppHasBiometricFeature(view.getContext());
}
@Override
public String getSecretKey() {
return gateway.getStoredSecretKey();
class ResendRequestObserver extends GenericApiObserverResponseV2<MessageResponseDataModel>
{
}
class ResendRequestObserver extends GenericApiObserverResponseV2<MessageResponseDataModel> {
@Override
protected Type setType() {
@ -100,8 +106,7 @@ public class TransactionPasswordPromptV2Presenter extends BasePresenter implemen
view.showResendRequestView(false);
view.startCountdownView(120000);
});
}
else {
} else {
view.showPopUpMessage(response.getMsg(), CustomAlertDialog.AlertType.FAILED, alertType -> {
view.showResendRequestView(true);
});

9
app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/presenter/TransactionPasswordPromptV2PresenterInterface.java

@ -1,5 +1,7 @@
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;
@ -16,10 +18,17 @@ public interface TransactionPasswordPromptV2PresenterInterface extends BasePrese
boolean checkIfUserHasEnabledBiometricAuth();
String getSecretKey();
interface TransactionPasswordPromptV2ContractInterface extends BaseContractInterface {
void startCountdownView(long durationMillisecond);
void showResendRequestView(boolean action);
Context getContext();
}
}

102
app/src/main/java/com/gmeremit/online/gmeremittance_native/transactionpasspromt/view/TransactionPasswordPromptActivity.java

@ -2,11 +2,11 @@ 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.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
@ -29,6 +29,7 @@ import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.gmeremit.online.gmeremittance_native.GmeApplication;
import com.gmeremit.online.gmeremittance_native.R;
import com.gmeremit.online.gmeremittance_native.base.BaseActivity;
import com.gmeremit.online.gmeremittance_native.customwidgets.GmeErrorTextView;
@ -38,12 +39,21 @@ import com.gmeremit.online.gmeremittance_native.utils.security.SecurityUtils;
import com.gmeremit.online.gmeremittance_native.utils.security.securitykeypad.SecurityKeyboardManager;
import com.gmeremit.online.gmeremittance_native.utils.security.securitykeypad.SecurityKeyboardView;
import com.gmeremit.online.gmeremittance_native.utils.security.securitykeypad.SecurityKeypadRequestParamBuilder;
import com.mtramin.rxfingerprint.RxFingerprint;
import com.mtramin.rxfingerprint.data.FingerprintDecryptionResult;
import com.mtramin.rxfingerprint.data.FingerprintEncryptionResult;
import com.softsecurity.transkey.TransKeyActivity;
import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.observers.DisposableObserver;
public class TransactionPasswordPromptActivity extends BaseActivity implements SecurityKeyboardView.SecurityKeyboardFocusStateListener, TransactionPasswordPromptV2PresenterInterface.TransactionPasswordPromptV2ContractInterface, View.OnClickListener {
@ -91,6 +101,9 @@ public class TransactionPasswordPromptActivity extends BaseActivity implements S
private CountDownTimer countDownTimer;
private AnimatedVectorDrawable fingerPrintAVD;
private AnimatedVectorDrawableCompat fingerPrintAVDCompat;
private Disposable fingerPrintReaderSubs;
String TAG = "FingerPrintObserver";
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -169,14 +182,14 @@ public class TransactionPasswordPromptActivity extends BaseActivity implements S
}
private void setupFingerPrintIconIfRequired() {
//TODO if biometric is on
if (SecurityUtils.doesAppHasBiometricFeature(this) && presenter.checkIfUserHasEnabledBiometricAuth()) {
if (presenter.checkIfUserHasEnabledBiometricAuth()) {
orTextView.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
fingerPrintAVD = (AnimatedVectorDrawable) ContextCompat.getDrawable(this, R.drawable.avd_fingerprint_off_to_on);
} else {
fingerPrintAVDCompat = (AnimatedVectorDrawableCompat) ContextCompat.getDrawable(this, R.drawable.avd_fingerprint_off_to_on);
}
} else {
passwordPromptImageView.setBackgroundResource(R.drawable.ic_penny_test_pending);
}
@ -222,6 +235,8 @@ public class TransactionPasswordPromptActivity extends BaseActivity implements S
securityKeyboardView.setSecurityKeyboardFocusStateListener(this);
if (checkIfRequiredOTPScreen())
resendRequest.setOnClickListener(this);
else if (presenter.checkIfUserHasEnabledBiometricAuth())
fingerPrintReaderSubs = startObservingFingerPrintScanner();
}
@Override
@ -230,35 +245,63 @@ public class TransactionPasswordPromptActivity extends BaseActivity implements S
securityKeyboardView.setSecurityKeyboardFocusStateListener(null);
if (checkIfRequiredOTPScreen())
resendRequest.setOnClickListener(null);
if (fingerPrintReaderSubs != null && !fingerPrintReaderSubs.isDisposed())
fingerPrintReaderSubs.dispose();
}
@Override
protected void onResume() {
super.onResume();
new Handler().postDelayed(this::animateFingerPrintAppearAnimationIfRequired, 400);
animateFingerPrintAppearAnimationIfRequired(true);
}
@Override
protected void onPause() {
super.onPause();
if (!checkIfRequiredOTPScreen() && SecurityUtils.doesAppHasBiometricFeature(this) && presenter.checkIfUserHasEnabledBiometricAuth())
new Handler().postDelayed(() -> passwordPromptImageView.setImageDrawable(null), 200);
animateFingerPrintAppearAnimationIfRequired(false);
}
@SuppressLint("NewApi")
private void animateFingerPrintAppearAnimationIfRequired() {
if (!checkIfRequiredOTPScreen()) {
if (fingerPrintAVD != null && !fingerPrintAVD.isRunning()) {
passwordPromptImageView.setImageDrawable(fingerPrintAVD);
fingerPrintAVD.start();
} else if (fingerPrintAVDCompat != null && !fingerPrintAVDCompat.isRunning()) {
passwordPromptImageView.setImageDrawable(fingerPrintAVDCompat);
fingerPrintAVDCompat.start();
}
private void animateFingerPrintAppearAnimationIfRequired(boolean action) {
if (!checkIfRequiredOTPScreen() && presenter.checkIfUserHasEnabledBiometricAuth() && action) {
new Handler().postDelayed(() -> {
if (fingerPrintAVD != null && !fingerPrintAVD.isRunning()) {
passwordPromptImageView.setImageDrawable(fingerPrintAVD);
fingerPrintAVD.start();
} else if (fingerPrintAVDCompat != null && !fingerPrintAVDCompat.isRunning()) {
passwordPromptImageView.setImageDrawable(fingerPrintAVDCompat);
fingerPrintAVDCompat.start();
}
}, 400);
} else {
new Handler().postDelayed(() -> {
passwordPromptImageView.setImageDrawable(null);
}, 200);
}
}
private Disposable startObservingFingerPrintScanner() {
return SecurityUtils.decryptSecret(this, presenter.getSecretKey())
.flatMap(authentication -> {
Log.d(TAG, authentication.getResult().toString());
switch (authentication.getResult()) {
case FAILED:
return io.reactivex.Observable.error(new SecurityUtils.FailedFingerPrintException(authentication.getMessage()));
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()));
}
})
.subscribeWith(new FingerPrintScannerObserver());
}
@Override
public void onSecurityViewRecievedFocus() {
if (securityKeyboardManager != null && !securityKeyboardManager.isKeyboardVisible())
@ -338,6 +381,13 @@ public class TransactionPasswordPromptActivity extends BaseActivity implements S
}
}
@Override
public Context getContext() {
return this;
}
@Override
public void onBackPressed() {
@ -416,4 +466,26 @@ public class TransactionPasswordPromptActivity extends BaseActivity implements S
}
class FingerPrintScannerObserver extends DisposableObserver<FingerprintDecryptionResult> {
@Override
public void onNext(FingerprintDecryptionResult fingerprintAuthenticationResult) {
Intent returnIntent = new Intent();
returnIntent.putExtra(TRANSACTION_PWD_ENC_DATA, fingerprintAuthenticationResult.getDecrypted());
setResult(Activity.RESULT_OK, returnIntent);
finish();
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
}
}

44
app/src/main/java/com/gmeremit/online/gmeremittance_native/utils/security/SecurityUtils.java

@ -2,13 +2,53 @@ package com.gmeremit.online.gmeremittance_native.utils.security;
import android.content.Context;
import com.mtramin.rxfingerprint.EncryptionMethod;
import com.mtramin.rxfingerprint.RxFingerprint;
import com.mtramin.rxfingerprint.data.FingerprintAuthenticationResult;
import com.mtramin.rxfingerprint.data.FingerprintDecryptionResult;
import com.mtramin.rxfingerprint.data.FingerprintEncryptionResult;
import io.reactivex.Observable;
public class SecurityUtils {
private static final String KEY_STORE_SECRET_ALIAS="gmeSecret321";
public static boolean doesAppHasBiometricFeature(Context context)
{
// return RxFingerprint.isAvailable(context);
return true;
return RxFingerprint.isAvailable(context);
}
public static Observable<FingerprintEncryptionResult> encryptSecret(Context context, String secret)
{
return RxFingerprint.encrypt(EncryptionMethod.RSA,context,KEY_STORE_SECRET_ALIAS,secret);
}
public static Observable<FingerprintDecryptionResult> decryptSecret(Context context, String secret)
{
return RxFingerprint.decrypt(EncryptionMethod.RSA,context,KEY_STORE_SECRET_ALIAS,secret);
}
public static Observable<FingerprintAuthenticationResult> authenticateFingerPrint(Context context)
{
return RxFingerprint.authenticate(context);
}
public static class SensorNotReadyException extends Exception
{
public SensorNotReadyException(String message) {
super(message);
}
}
public static class FailedFingerPrintException extends Exception
{
public FailedFingerPrintException(String message) {
super(message);
}
}
}

6
app/src/main/res/layout/activity_settings.xml

@ -135,6 +135,12 @@
android:textColor="@color/darkgray"
android:textSize="14sp" />
<View
android:id="@+id/view_fingerprint_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider_dark" />
</LinearLayout>
</ScrollView>
Loading…
Cancel
Save