diff --git a/README.md b/README.md index af607d6..a457236 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ## Min SDK Version - 15 -PFLockScreen - Lock Screen Library for Android Application. Library support **pin code** and **fingerprint** authorization for API level 23+. +PFLockScreen - Lock Screen Library for Android Application. Library support **pin code** and **biometric** authorization for API level 23+.


@@ -72,7 +72,7 @@ PFFLockScreenConfiguration.Builder(this).setMode(PFFLockScreenConfiguration.MODE
```java
PFFLockScreenConfiguration.Builder builder = new PFFLockScreenConfiguration.Builder(this)
.setTitle("Unlock")
- .setUseFingerprint(true).
+ .setUseBiometric(true).
.setMode(PFFLockScreenConfiguration.MODE_AUTH)
.setCodeLength(6)
.setLeftButton("Can't remeber",
@@ -87,7 +87,7 @@ PFFLockScreenConfiguration.Builder builder = new PFFLockScreenConfiguration.Buil
*setTitle(String)* - set custom string on the top of the screen.
-*setUseFingerprint(boolean)* - by default fingerprint button will be shown for all device 23+ with a fingerprint sensor. If you don't want use fingerprint at all set *false*.
+*setUseBiometric(boolean)* - by default fingerprint(biometric authentication) button will be shown for all device 23+ with a fingerprint sensor and/or face recognition. If you don't want use biometric authentication at all set *false*.
*setMode(PFLockScreenMode)* - MODE_CREATE or MODE_AUTH. See details above.
*setCodeLength(int)* - set the length of the pin code. By default, length is 4. Minimum length is 4.
*setLeftButton(String, View.OnClickListener)* - set string for the left button and ClickListener.
diff --git a/app/build.gradle b/app/build.gradle
index e0d8a56..790fb2b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -20,11 +20,11 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
- implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
- implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
- testImplementation 'junit:junit:4.12'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.2-alpha01'
- androidTestImplementation 'androidx.test:runner:1.1.2-alpha01'
- androidTestImplementation 'androidx.test:rules:1.1.2-alpha01'
+ implementation 'androidx.appcompat:appcompat:1.3.0-alpha01'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta6'
+ testImplementation 'junit:junit:4.13'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-rc01'
+ androidTestImplementation 'androidx.test:runner:1.3.0-rc01'
+ androidTestImplementation 'androidx.test:rules:1.3.0-rc01'
implementation project(':pflockscreen')
}
diff --git a/app/src/main/java/com/beautycoder/applicationlockscreenexample/MainActivity.java b/app/src/main/java/com/beautycoder/applicationlockscreenexample/MainActivity.java
index 8ac9e5d..553a0e9 100644
--- a/app/src/main/java/com/beautycoder/applicationlockscreenexample/MainActivity.java
+++ b/app/src/main/java/com/beautycoder/applicationlockscreenexample/MainActivity.java
@@ -42,13 +42,13 @@ public void onNewCodeValidationFailed() {
@Override
public void onCodeInputSuccessful() {
- Toast.makeText(MainActivity.this, "Code successfull", Toast.LENGTH_SHORT).show();
+ Toast.makeText(MainActivity.this, "Code successful", Toast.LENGTH_SHORT).show();
showMainFragment();
}
@Override
- public void onFingerprintSuccessful() {
- Toast.makeText(MainActivity.this, "Fingerprint successfull", Toast.LENGTH_SHORT).show();
+ public void onBiometricAuthSuccessful() {
+ Toast.makeText(MainActivity.this, "Biometric authentication successful", Toast.LENGTH_SHORT).show();
showMainFragment();
}
@@ -58,8 +58,8 @@ public void onPinLoginFailed() {
}
@Override
- public void onFingerprintLoginFailed() {
- Toast.makeText(MainActivity.this, "Fingerprint failed", Toast.LENGTH_SHORT).show();
+ public void onBiometricAuthLoginFailed() {
+ Toast.makeText(MainActivity.this, "Biometric authentication failed", Toast.LENGTH_SHORT).show();
}
};
@@ -89,7 +89,8 @@ private void showLockScreenFragment(boolean isPinExist) {
.setLeftButton("Can't remeber")
.setNewCodeValidation(true)
.setNewCodeValidationTitle("Please input code again")
- .setUseFingerprint(true);
+ .setAutoShowBiometric(true)
+ .setUseBiometric(true);
final PFLockScreenFragment fragment = new PFLockScreenFragment();
fragment.setOnLeftButtonClickListener(new View.OnClickListener() {
diff --git a/pflockscreen/build.gradle b/pflockscreen/build.gradle
index db00931..d8abca7 100644
--- a/pflockscreen/build.gradle
+++ b/pflockscreen/build.gradle
@@ -32,6 +32,8 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
+ implementation "androidx.biometric:biometric:1.0.1"
+
//Livecycles & ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
diff --git a/pflockscreen/src/main/java/com/beautycoder/pflockscreen/PFFLockScreenConfiguration.java b/pflockscreen/src/main/java/com/beautycoder/pflockscreen/PFFLockScreenConfiguration.java
index 6d0c5b5..bc8483f 100644
--- a/pflockscreen/src/main/java/com/beautycoder/pflockscreen/PFFLockScreenConfiguration.java
+++ b/pflockscreen/src/main/java/com/beautycoder/pflockscreen/PFFLockScreenConfiguration.java
@@ -15,8 +15,9 @@ public class PFFLockScreenConfiguration implements Serializable {
private String mLeftButton = "";
private String mNextButton = "";
- private boolean mUseFingerprint = false;
- private boolean mAutoShowFingerprint = false;
+ private boolean mUseBiometric = false;
+ private boolean mAutoShowBiometric = false;
+ private int mBiometricBackground = -1;
private String mTitle = "";
private int mMode = MODE_AUTH;
private int mCodeLength = 4;
@@ -29,8 +30,9 @@ public class PFFLockScreenConfiguration implements Serializable {
private PFFLockScreenConfiguration(Builder builder) {
mLeftButton = builder.mLeftButton;
mNextButton = builder.mNextButton;
- mUseFingerprint = builder.mUseFingerprint;
- mAutoShowFingerprint = builder.mAutoShowFingerprint;
+ mUseBiometric = builder.mUseBiometric;
+ mAutoShowBiometric = builder.mAutoShowBiometric;
+ mBiometricBackground = builder.mBiometricBackground;
mTitle = builder.mTitle;
mMode = builder.mMode;
mCodeLength = builder.mCodeLength;
@@ -49,12 +51,16 @@ public String getNextButton() {
return mNextButton;
}
- public boolean isUseFingerprint() {
- return mUseFingerprint;
+ public boolean isUseBiometric() {
+ return mUseBiometric;
}
- public boolean isAutoShowFingerprint() {
- return mAutoShowFingerprint;
+ public boolean isAutoShowBiometric() {
+ return mAutoShowBiometric;
+ }
+
+ public int getBiometricBackground() {
+ return mBiometricBackground;
}
public String getTitle() {
@@ -94,8 +100,9 @@ public static class Builder {
private String mLeftButton = "";
private String mNextButton = "";
- private boolean mUseFingerprint = false;
- private boolean mAutoShowFingerprint = false;
+ private boolean mUseBiometric = false;
+ private boolean mAutoShowBiometric = false;
+ private int mBiometricBackground = -1;
private String mTitle = "";
private int mMode = 0;
private int mCodeLength = 4;
@@ -125,13 +132,18 @@ public Builder setNextButton(String nextButton) {
return this;
}
- public Builder setUseFingerprint(boolean useFingerprint) {
- mUseFingerprint = useFingerprint;
+ public Builder setUseBiometric(boolean useBiometric) {
+ mUseBiometric = useBiometric;
+ return this;
+ }
+
+ public Builder setAutoShowBiometric(boolean autoShowBiometric) {
+ mAutoShowBiometric = autoShowBiometric;
return this;
}
- public Builder setAutoShowFingerprint(boolean autoShowFingerprint) {
- mAutoShowFingerprint = autoShowFingerprint;
+ public Builder setBiometricBackground(int biometricBackground) {
+ mBiometricBackground = biometricBackground;
return this;
}
diff --git a/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/BiometricUIStarter.java b/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/BiometricUIStarter.java
new file mode 100644
index 0000000..c52c2bf
--- /dev/null
+++ b/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/BiometricUIStarter.java
@@ -0,0 +1,67 @@
+package com.beautycoder.pflockscreen.fragments;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import androidx.biometric.BiometricManager;
+import androidx.biometric.BiometricPrompt;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
+
+import com.beautycoder.pflockscreen.R;
+
+import java.util.concurrent.Executor;
+
+public class BiometricUIStarter {
+ private final BiometricManager biometricManager;
+ private final BiometricPrompt biometricPrompt;
+ private String title = "Biometric Authentication";
+ private String description;
+ private boolean confirmationRequired;
+ private String usePin;
+
+ public BiometricUIStarter(BiometricManager bioManager, Context context, Fragment fragment, BiometricPrompt.AuthenticationCallback callback) {
+ biometricManager = bioManager;
+ usePin = context.getResources().getString(R.string.use_pin_pf);
+ biometricPrompt = instanceOfBiometricPrompt(context, fragment, callback);
+ }
+
+ private BiometricPrompt instanceOfBiometricPrompt(Context context, Fragment fragment, BiometricPrompt.AuthenticationCallback callback) {
+ Executor executor = ContextCompat.getMainExecutor(context);
+ return new BiometricPrompt(fragment, executor ,callback);
+ }
+
+ public boolean isBiometricAuthAvailable() {
+ return biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS;
+ }
+
+ public boolean isBiometricAuthNotSet() {
+ return biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED;
+ }
+
+ private BiometricPrompt.PromptInfo getPromptInfo() {
+ return new BiometricPrompt.PromptInfo.Builder()
+ .setTitle(title)
+ .setDescription(description)
+ .setDeviceCredentialAllowed(false)
+ .setNegativeButtonText(usePin)
+ .setConfirmationRequired(confirmationRequired)
+ .build();
+ }
+
+ public void startUI() {
+ biometricPrompt.authenticate(getPromptInfo());
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public void setConfirmationRequired(boolean confirmationRequired) {
+ this.confirmationRequired = confirmationRequired;
+ }
+}
diff --git a/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/PFFingerprintAuthDialogFragment.java b/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/PFFingerprintAuthDialogFragment.java
deleted file mode 100644
index 829d4a9..0000000
--- a/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/PFFingerprintAuthDialogFragment.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.beautycoder.pflockscreen.fragments;
-
-import android.content.Context;
-import android.os.Build;
-import android.os.Bundle;
-import androidx.annotation.RequiresApi;
-import androidx.fragment.app.DialogFragment;
-import androidx.core.hardware.fingerprint.FingerprintManagerCompat;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.beautycoder.pflockscreen.R;
-
-/**
- * A dialog which uses fingerprint APIs to authenticate the user, and falls back to password
- * authentication if fingerprint is not available.
- */
-@RequiresApi(api = Build.VERSION_CODES.M)
-public class PFFingerprintAuthDialogFragment extends DialogFragment {
-
- private Button mCancelButton;
- private View mFingerprintContent;
-
- private Stage mStage = Stage.FINGERPRINT;
-
- private FingerprintManagerCompat.CryptoObject mCryptoObject;
-
- private PFFingerprintUIHelper mFingerprintCallback;
-
- private Context mContext;
-
- private PFFingerprintAuthListener mAuthListener;
-
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Do not create a new Fragment when the Activity is re-created such as orientation changes.
- setRetainInstance(true);
- setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Material_Light_Dialog);
- }
-
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- getDialog().setTitle(getString(R.string.sign_in_pf));
- View v = inflater.inflate(R.layout.view_pf_fingerprint_dialog_container, container,
- false);
- mCancelButton = v.findViewById(R.id.cancel_button);
- mCancelButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- dismiss();
- }
- });
-
- mFingerprintContent = v.findViewById(R.id.fingerprint_container);
-
-
- FingerprintManagerCompat manager = FingerprintManagerCompat.from(getContext());
- mFingerprintCallback = new PFFingerprintUIHelper(manager,
- (ImageView) v.findViewById(R.id.fingerprint_icon),
- (TextView) v.findViewById(R.id.fingerprint_status),
- mAuthListener);
- updateStage();
- return v;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- if (mStage == Stage.FINGERPRINT) {
- mFingerprintCallback.startListening(mCryptoObject);
- }
- }
-
- public void setStage(Stage stage) {
- mStage = stage;
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mFingerprintCallback.stopListening();
- }
-
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- mContext = context;
- }
-
- /**
- * Sets the crypto object to be passed in when authenticating with fingerprint.
- */
- /*public void setCryptoObject(FingerprintManagerCompat.CryptoObject cryptoObject) {
- mCryptoObject = cryptoObject;
- }*/
-
-
- private void updateStage() {
- switch (mStage) {
- case FINGERPRINT:
- mCancelButton.setText(R.string.cancel_pf);
- mFingerprintContent.setVisibility(View.VISIBLE);
- break;
- }
- }
-
-
- public void setAuthListener(PFFingerprintAuthListener authListener) {
- mAuthListener = authListener;
- }
-
- /**
- * Enumeration to indicate which authentication method the user is trying to authenticate with.
- */
- public enum Stage {
- FINGERPRINT
- }
-}
diff --git a/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/PFFingerprintUIHelper.java b/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/PFFingerprintUIHelper.java
deleted file mode 100644
index 5158682..0000000
--- a/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/PFFingerprintUIHelper.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package com.beautycoder.pflockscreen.fragments;
-
-import android.os.Build;
-import androidx.annotation.RequiresApi;
-import androidx.core.hardware.fingerprint.FingerprintManagerCompat;
-import androidx.core.os.CancellationSignal;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.beautycoder.pflockscreen.R;
-
-
-/**
- * Created by aleksandr on 2018/02/10.
- */
-
-@RequiresApi(api = Build.VERSION_CODES.M)
-public class PFFingerprintUIHelper extends FingerprintManagerCompat.AuthenticationCallback {
-
- private static final long ERROR_TIMEOUT_MILLIS = 1600;
- private static final long SUCCESS_DELAY_MILLIS = 200;
-
- private final FingerprintManagerCompat mFingerprintManager;
- private final ImageView mIcon;
- private final TextView mErrorTextView;
- private final PFFingerprintAuthListener mCallback;
- private CancellationSignal mCancellationSignal;
-
- private boolean mSelfCancelled;
-
- public PFFingerprintUIHelper(FingerprintManagerCompat fingerprintManager,
- ImageView icon, TextView errorTextView,
- PFFingerprintAuthListener callback) {
- super();
- mFingerprintManager = fingerprintManager;
- mIcon = icon;
- mErrorTextView = errorTextView;
- mCallback = callback;
- }
-
- public boolean isFingerprintAuthAvailable() {
- // The line below prevents the false positive inspection from Android Studio
- // noinspection ResourceType
- return mFingerprintManager.isHardwareDetected()
- && mFingerprintManager.hasEnrolledFingerprints();
- }
-
- public void startListening(FingerprintManagerCompat.CryptoObject cryptoObject) {
- if (!isFingerprintAuthAvailable()) {
- return;
- }
- mCancellationSignal = new CancellationSignal();
- mSelfCancelled = false;
- // The line below prevents the false positive inspection from Android Studio
- // noinspection ResourceType
- mFingerprintManager.authenticate(
- cryptoObject, 0, mCancellationSignal, this, null);
- mIcon.setImageResource(R.drawable.ic_fp_40px_pf);
- }
-
- public void stopListening() {
- if (mCancellationSignal != null) {
- mSelfCancelled = true;
- mCancellationSignal.cancel();
- mCancellationSignal = null;
- }
- }
-
- @Override
- public void onAuthenticationError(int errMsgId, CharSequence errString) {
- if (!mSelfCancelled) {
- showError(errString);
- mIcon.postDelayed(new Runnable() {
- @Override
- public void run() {
- mCallback.onError();
- }
- }, ERROR_TIMEOUT_MILLIS);
- }
- }
-
- @Override
- public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
- showError(helpString);
- }
-
- @Override
- public void onAuthenticationFailed() {
- showError(mIcon.getResources().getString(
- R.string.fingerprint_not_recognized_pf));
- }
-
- @Override
- public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
- mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
- mIcon.setImageResource(R.drawable.ic_fingerprint_success_pf);
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(R.color.success_color, null));
- mErrorTextView.setText(
- mErrorTextView.getResources().getString(R.string.fingerprint_success_pf));
- mIcon.postDelayed(new Runnable() {
- @Override
- public void run() {
- mCallback.onAuthenticated();
- }
- }, SUCCESS_DELAY_MILLIS);
- }
-
- private void showError(CharSequence error) {
- mIcon.setImageResource(R.drawable.ic_fingerprint_error_pf);
- mErrorTextView.setText(error);
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(R.color.warning_color, null));
- mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
- mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT_MILLIS);
- }
-
- private Runnable mResetErrorTextRunnable = new Runnable() {
- @Override
- public void run() {
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(R.color.hint_color, null));
- mErrorTextView.setText(
- mErrorTextView.getResources().getString(R.string.fingerprint_hint_pf));
- mIcon.setImageResource(R.drawable.ic_fp_40px_pf);
- }
- };
-
-}
diff --git a/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/PFLockScreenFragment.java b/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/PFLockScreenFragment.java
index 5ef925c..813a62c 100644
--- a/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/PFLockScreenFragment.java
+++ b/pflockscreen/src/main/java/com/beautycoder/pflockscreen/fragments/PFLockScreenFragment.java
@@ -3,6 +3,8 @@
import android.app.AlertDialog;
import androidx.annotation.NonNull;
+import androidx.biometric.BiometricManager;
+import androidx.biometric.BiometricPrompt;
import androidx.lifecycle.Observer;
import android.content.Context;
import android.content.DialogInterface;
@@ -18,9 +20,11 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import com.beautycoder.pflockscreen.PFFLockScreenConfiguration;
@@ -39,20 +43,18 @@ public class PFLockScreenFragment extends Fragment {
private static final String TAG = PFLockScreenFragment.class.getName();
- private static final String FINGERPRINT_DIALOG_FRAGMENT_TAG = "FingerprintDialogFragment";
-
private static final String INSTANCE_STATE_CONFIG
= "com.beautycoder.pflockscreen.instance_state_config";
- private View mFingerprintButton;
+ private View mBiometricAuthButton;
private View mDeleteButton;
private TextView mLeftButton;
private Button mNextButton;
private PFCodeView mCodeView;
private TextView titleView;
- private boolean mUseFingerPrint = true;
- private boolean mFingerprintHardwareDetected = false;
+ private boolean mUseBiometricAuth = true;
+ private boolean mBiometricAuthHardwareDetected = false;
private boolean mIsCreateMode = false;
private OnPFLockScreenCodeCreateListener mCodeCreateListener;
@@ -61,6 +63,9 @@ public class PFLockScreenFragment extends Fragment {
private String mCodeValidation = "";
private String mEncodedPinCode = "";
+ private BiometricUIStarter bioAuth;
+ private View biometricView = null;
+
private PFFLockScreenConfiguration mConfiguration;
private View mRootView;
@@ -78,7 +83,7 @@ public void onSaveInstanceState(@NonNull Bundle outState) {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
- final View view = inflater.inflate(R.layout.fragment_lock_screen_pf, container,
+ View view = inflater.inflate(R.layout.fragment_lock_screen_pf, container,
false);
if (mConfiguration == null) {
@@ -87,7 +92,7 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
);
}
- mFingerprintButton = view.findViewById(R.id.button_finger_print);
+ mBiometricAuthButton = view.findViewById(R.id.button_finger_print);
mDeleteButton = view.findViewById(R.id.button_delete);
mLeftButton = view.findViewById(R.id.button_left);
@@ -95,33 +100,42 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
mDeleteButton.setOnClickListener(mOnDeleteButtonClickListener);
mDeleteButton.setOnLongClickListener(mOnDeleteButtonOnLongClickListener);
- mFingerprintButton.setOnClickListener(mOnFingerprintClickListener);
+ mBiometricAuthButton.setOnClickListener(mOnBiometricAuthClickListener);
mCodeView = view.findViewById(R.id.code_view);
initKeyViews(view);
mCodeView.setListener(mCodeListener);
- if (!mUseFingerPrint) {
- mFingerprintButton.setVisibility(View.GONE);
+ if (!mUseBiometricAuth) {
+ mBiometricAuthButton.setVisibility(View.GONE);
}
- mFingerprintHardwareDetected = isFingerprintApiAvailable(getContext());
mRootView = view;
applyConfiguration(mConfiguration);
+ boolean instantBiometricScan = mConfiguration.isUseBiometric() && mConfiguration.isAutoShowBiometric();
+ boolean createMode = mConfiguration.getMode() == PFFLockScreenConfiguration.MODE_CREATE;
+ BiometricManager bioManager = BiometricManager.from(getContext());
+ BiometricPrompt.AuthenticationCallback callback = createCallback();
+ bioAuth = new BiometricUIStarter(bioManager, getContext(), this, callback);
+ mBiometricAuthHardwareDetected = bioAuth.isBiometricAuthAvailable();
+ bioAuth.setTitle(getString(R.string.sign_in_pf));
+
+ if (mBiometricAuthHardwareDetected && instantBiometricScan && !createMode) {
+ bioAuth.setConfirmationRequired(true);
+ bioAuth.startUI();
+ int backgroundID = mConfiguration.getBiometricBackground();
+ if (backgroundID != -1) { //this will set a new view over the pin fragment which makes it easier to go back from this view
+ biometricView = inflater.inflate(backgroundID, container, false);
+ ((RelativeLayout)view.findViewById(R.id.fragment_pf)).addView(biometricView);
+ }
+ }
+
return view;
}
- @Override
- public void onStart() {
- if (!mIsCreateMode && mUseFingerPrint && mConfiguration.isAutoShowFingerprint() &&
- isFingerprintApiAvailable(getActivity()) && isFingerprintsExists(getActivity())) {
- mOnFingerprintClickListener.onClick(mFingerprintButton);
- }
- super.onStart();
- }
public void setConfiguration(PFFLockScreenConfiguration configuration) {
this.mConfiguration = configuration;
@@ -145,16 +159,16 @@ private void applyConfiguration(PFFLockScreenConfiguration configuration) {
mNextButton.setText(configuration.getNextButton());
}
- mUseFingerPrint = configuration.isUseFingerprint();
- if (!mUseFingerPrint) {
- mFingerprintButton.setVisibility(View.GONE);
+ mUseBiometricAuth = configuration.isUseBiometric();
+ if (!mUseBiometricAuth) {
+ mBiometricAuthButton.setVisibility(View.GONE);
mDeleteButton.setVisibility(View.VISIBLE);
}
mIsCreateMode = mConfiguration.getMode() == PFFLockScreenConfiguration.MODE_CREATE;
if (mIsCreateMode) {
mLeftButton.setVisibility(View.GONE);
- mFingerprintButton.setVisibility(View.GONE);
+ mBiometricAuthButton.setVisibility(View.GONE);
}
if (mIsCreateMode) {
@@ -212,39 +226,18 @@ public boolean onLongClick(View v) {
}
};
- private final View.OnClickListener mOnFingerprintClickListener = new View.OnClickListener() {
+ private final View.OnClickListener mOnBiometricAuthClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
- !isFingerprintApiAvailable(getActivity())) {
+ if (bioAuth.isBiometricAuthAvailable()) {
+ bioAuth.setConfirmationRequired(false);
+ bioAuth.startUI();
return;
}
-
- if (!isFingerprintsExists(getActivity())) {
- showNoFingerprintDialog();
- return;
+ if (bioAuth.isBiometricAuthNotSet()) {
+ showNoBiometricAuthDialog();
}
-
- final PFFingerprintAuthDialogFragment fragment
- = new PFFingerprintAuthDialogFragment();
- fragment.show(getFragmentManager(), FINGERPRINT_DIALOG_FRAGMENT_TAG);
- fragment.setAuthListener(new PFFingerprintAuthListener() {
- @Override
- public void onAuthenticated() {
- if (mLoginListener != null) {
- mLoginListener.onFingerprintSuccessful();
- }
- fragment.dismiss();
- }
-
- @Override
- public void onError() {
- if (mLoginListener != null) {
- mLoginListener.onFingerprintLoginFailed();
- }
- }
- });
}
};
@@ -259,17 +252,17 @@ private void configureRightButton(int codeLength) {
}
if (codeLength > 0) {
- mFingerprintButton.setVisibility(View.GONE);
+ mBiometricAuthButton.setVisibility(View.GONE);
mDeleteButton.setVisibility(View.VISIBLE);
mDeleteButton.setEnabled(true);
return;
}
- if (mUseFingerPrint && mFingerprintHardwareDetected) {
- mFingerprintButton.setVisibility(View.VISIBLE);
+ if (mUseBiometricAuth && mBiometricAuthHardwareDetected) {
+ mBiometricAuthButton.setVisibility(View.VISIBLE);
mDeleteButton.setVisibility(View.GONE);
} else {
- mFingerprintButton.setVisibility(View.GONE);
+ mBiometricAuthButton.setVisibility(View.GONE);
mDeleteButton.setVisibility(View.VISIBLE);
}
@@ -277,16 +270,7 @@ private void configureRightButton(int codeLength) {
}
- private boolean isFingerprintApiAvailable(Context context) {
- return FingerprintManagerCompat.from(context).isHardwareDetected();
- }
-
- private boolean isFingerprintsExists(Context context) {
- return FingerprintManagerCompat.from(context).hasEnrolledFingerprints();
- }
-
-
- private void showNoFingerprintDialog() {
+ private void showNoBiometricAuthDialog() {
new AlertDialog.Builder(getContext())
.setTitle(R.string.no_fingerprints_title_pf)
.setMessage(R.string.no_fingerprints_message_pf)
@@ -432,6 +416,41 @@ public void setOnLeftButtonClickListener(View.OnClickListener onLeftButtonClickL
this.mOnLeftButtonClickListener = onLeftButtonClickListener;
}
+ private BiometricPrompt.AuthenticationCallback createCallback() {
+ return new BiometricPrompt.AuthenticationCallback() {
+ @Override
+ public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
+ super.onAuthenticationError(errorCode, errString);
+ if (errorCode == 13 || errorCode == 10) { //13 for "use pin" button and 10 for clicking above the biometricPrompt
+ if (biometricView != null) {
+ ((ViewManager) biometricView.getParent()).removeView(biometricView);
+ biometricView = null;
+ }
+ return;
+ }
+ if (mLoginListener != null) {
+ mLoginListener.onBiometricAuthLoginFailed();
+ }
+ }
+
+ @Override
+ public void onAuthenticationFailed() {
+ super.onAuthenticationFailed();
+ if (mLoginListener != null) {
+ mLoginListener.onBiometricAuthLoginFailed();
+ }
+ }
+
+ @Override
+ public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
+ super.onAuthenticationSucceeded(result);
+ if (mLoginListener != null) {
+ mLoginListener.onBiometricAuthSuccessful();
+ }
+ }
+ };
+ }
+
/*private void showFingerprintAlertDialog(Context context) {
new AlertDialog.Builder(context).setTitle("Fingerprint").setMessage(
"Would you like to use fingerprint for future login?")
@@ -514,7 +533,7 @@ public interface OnPFLockScreenLoginListener {
/**
* Callback method for successful login attempt with fingerprint.
*/
- void onFingerprintSuccessful();
+ void onBiometricAuthSuccessful();
/**
* Callback method for unsuccessful login attempt with pin code.
@@ -524,7 +543,7 @@ public interface OnPFLockScreenLoginListener {
/**
* Callback method for unsuccessful login attempt with fingerprint.
*/
- void onFingerprintLoginFailed();
+ void onBiometricAuthLoginFailed();
}
diff --git a/pflockscreen/src/main/res/layout/fragment_lock_screen_pf.xml b/pflockscreen/src/main/res/layout/fragment_lock_screen_pf.xml
index 1bc3807..badb3c8 100644
--- a/pflockscreen/src/main/res/layout/fragment_lock_screen_pf.xml
+++ b/pflockscreen/src/main/res/layout/fragment_lock_screen_pf.xml
@@ -2,7 +2,9 @@