Use BiometricPrompt
This commit is contained in:
7 files changed
+58
-153
No files matched your search
@@ -78,6 +78,7 @@ tasks.withType(JavaCompile) {
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0-alpha03'
|
||||
implementation 'androidx.biometric:biometric:1.0.1'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
|
||||
implementation 'com.google.android.material:material:1.1.0'
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.hippo.ehviewer.ui;
|
||||
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MenuItem;
|
||||
@@ -25,7 +23,7 @@ import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.biometric.BiometricManager;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
@@ -44,16 +42,6 @@ public class SetSecurityActivity extends ToolbarActivity implements View.OnClick
|
||||
@Nullable
|
||||
private CheckBox mFingerprint;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
public static boolean hasEnrolledFingerprints(FingerprintManager fingerprintManager) {
|
||||
try {
|
||||
return fingerprintManager.isHardwareDetected()
|
||||
&& fingerprintManager.hasEnrolledFingerprints();
|
||||
} catch (Throwable e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -72,10 +60,7 @@ public class SetSecurityActivity extends ToolbarActivity implements View.OnClick
|
||||
}
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class);
|
||||
// The line below prevents the false positive inspection from Android Studio
|
||||
// noinspection ResourceType
|
||||
if (fingerprintManager != null && hasEnrolledFingerprints(fingerprintManager)) {
|
||||
if (BiometricManager.from(this).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) {
|
||||
mFingerprint.setVisibility(View.VISIBLE);
|
||||
mFingerprint.setChecked(Settings.getEnableFingerprint());
|
||||
}
|
||||
|
||||
@@ -19,59 +19,43 @@ package com.hippo.ehviewer.ui.scene;
|
||||
import android.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.biometric.BiometricManager;
|
||||
import androidx.biometric.BiometricPrompt;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.ehviewer.ui.SetSecurityActivity;
|
||||
import com.hippo.hardware.ShakeDetector;
|
||||
import com.hippo.widget.lockpattern.LockPatternUtils;
|
||||
import com.hippo.widget.lockpattern.LockPatternView;
|
||||
import com.hippo.yorozuya.AssertUtils;
|
||||
import com.hippo.yorozuya.ObjectUtils;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class SecurityScene extends SolidScene implements
|
||||
LockPatternView.OnPatternListener, ShakeDetector.OnShakeListener {
|
||||
|
||||
private static final int MAX_RETRY_TIMES = 5;
|
||||
private static final long ERROR_TIMEOUT_MILLIS = 1200;
|
||||
private static final long SUCCESS_DELAY_MILLIS = 100;
|
||||
|
||||
private static final String KEY_RETRY_TIMES = "retry_times";
|
||||
|
||||
@Nullable
|
||||
private LockPatternView mPatternView;
|
||||
private ImageView mFingerprintIcon;
|
||||
|
||||
private SensorManager mSensorManager;
|
||||
private Sensor mAccelerometer;
|
||||
private ShakeDetector mShakeDetector;
|
||||
@Nullable
|
||||
private FingerprintManager mFingerprintManager;
|
||||
|
||||
private CancellationSignal mFingerprintCancellationSignal;
|
||||
|
||||
private int mRetryTimes;
|
||||
private Runnable mResetFingerprintRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mFingerprintIcon != null)
|
||||
mFingerprintIcon.setImageResource(R.drawable.ic_fp_40px);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean needShowLeftDrawer() {
|
||||
@@ -82,8 +66,7 @@ public class SecurityScene extends SolidScene implements
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Context context = getContext2();
|
||||
AssertUtils.assertNotNull(context);
|
||||
Context context = requireContext();
|
||||
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||
if (null != mSensorManager) {
|
||||
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
@@ -92,9 +75,6 @@ public class SecurityScene extends SolidScene implements
|
||||
mShakeDetector.setOnShakeListener(this);
|
||||
}
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
mFingerprintManager = context.getSystemService(FingerprintManager.class);
|
||||
}
|
||||
|
||||
if (null == savedInstanceState) {
|
||||
mRetryTimes = MAX_RETRY_TIMES;
|
||||
@@ -121,35 +101,29 @@ public class SecurityScene extends SolidScene implements
|
||||
}
|
||||
|
||||
if (isFingerprintAuthAvailable()) {
|
||||
mFingerprintCancellationSignal = new CancellationSignal();
|
||||
// The line below prevents the false positive inspection from Android Studio
|
||||
// noinspection ResourceType
|
||||
mFingerprintManager.authenticate(null, mFingerprintCancellationSignal, 0,
|
||||
new FingerprintManager.AuthenticationCallback() {
|
||||
@Override
|
||||
public void onAuthenticationError(int errMsgId, CharSequence errString) {
|
||||
fingerprintError(true);
|
||||
}
|
||||
BiometricPrompt biometricPrompt = new BiometricPrompt(this, Executors.newSingleThreadExecutor(), new BiometricPrompt.AuthenticationCallback() {
|
||||
@Override
|
||||
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
|
||||
super.onAuthenticationError(errorCode, errString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailed() {
|
||||
fingerprintError(false);
|
||||
}
|
||||
@Override
|
||||
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
|
||||
startSceneForCheckStep(CHECK_STEP_SECURITY, getArguments());
|
||||
finish();
|
||||
super.onAuthenticationSucceeded(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSucceeded(
|
||||
FingerprintManager.AuthenticationResult result) {
|
||||
mFingerprintIcon.setImageResource(R.drawable.fingerprint_success);
|
||||
mFingerprintIcon.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startSceneForCheckStep(CHECK_STEP_SECURITY, getArguments());
|
||||
finish();
|
||||
}
|
||||
}, SUCCESS_DELAY_MILLIS);
|
||||
|
||||
}
|
||||
}, null);
|
||||
@Override
|
||||
public void onAuthenticationFailed() {
|
||||
super.onAuthenticationFailed();
|
||||
}
|
||||
});
|
||||
BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
|
||||
.setTitle(getString(R.string.app_name))
|
||||
.setNegativeButtonText(getString(android.R.string.cancel))
|
||||
.build();
|
||||
biometricPrompt.authenticate(promptInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,10 +134,6 @@ public class SecurityScene extends SolidScene implements
|
||||
if (null != mShakeDetector) {
|
||||
mSensorManager.unregisterListener(mShakeDetector);
|
||||
}
|
||||
if (isFingerprintAuthAvailable() && mFingerprintCancellationSignal != null) {
|
||||
mFingerprintCancellationSignal.cancel();
|
||||
mFingerprintCancellationSignal = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -180,12 +150,6 @@ public class SecurityScene extends SolidScene implements
|
||||
|
||||
mPatternView = (LockPatternView) ViewUtils.$$(view, R.id.pattern_view);
|
||||
mPatternView.setOnPatternListener(this);
|
||||
|
||||
mFingerprintIcon = (ImageView) ViewUtils.$$(view, R.id.fingerprint_icon);
|
||||
if (Settings.getEnableFingerprint() && isFingerprintAuthAvailable()) {
|
||||
mFingerprintIcon.setVisibility(View.VISIBLE);
|
||||
mFingerprintIcon.setImageResource(R.drawable.ic_fp_40px);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -244,27 +208,8 @@ public class SecurityScene extends SolidScene implements
|
||||
}
|
||||
|
||||
private boolean isFingerprintAuthAvailable() {
|
||||
// The line below prevents the false positive inspection from Android Studio
|
||||
// noinspection ResourceType
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||
&& Settings.getEnableFingerprint()
|
||||
&& mFingerprintManager != null
|
||||
&& SetSecurityActivity.hasEnrolledFingerprints(mFingerprintManager);
|
||||
}
|
||||
|
||||
private void fingerprintError(boolean unrecoverable) {
|
||||
// Do not decrease mRetryTimes here since Android system will handle it :)
|
||||
mFingerprintIcon.setImageResource(R.drawable.fingerprint_error);
|
||||
mFingerprintIcon.removeCallbacks(mResetFingerprintRunnable);
|
||||
if (unrecoverable) {
|
||||
mFingerprintIcon.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mFingerprintIcon.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}, ERROR_TIMEOUT_MILLIS);
|
||||
} else {
|
||||
mFingerprintIcon.postDelayed(mResetFingerprintRunnable, ERROR_TIMEOUT_MILLIS);
|
||||
}
|
||||
&& BiometricManager.from(requireContext()).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -50,11 +50,10 @@
|
||||
android:text="@string/enable_fingerprint" />
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/buttonPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingTop="4dp"
|
||||
@@ -62,21 +61,20 @@
|
||||
android:gravity="bottom"
|
||||
style="?attr/buttonBarStyle">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel"
|
||||
style="?attr/buttonBarNegativeButtonStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@android:string/cancel"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/set"
|
||||
style="?attr/buttonBarPositiveButtonStyle"
|
||||
android:layout_width="0dp"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/set"/>
|
||||
android:text="@string/set" />
|
||||
<Button
|
||||
android:id="@+id/cancel"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@android:string/cancel" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -63,29 +63,26 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="bottom"
|
||||
android:orientation="horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel"
|
||||
style="?attr/buttonBarNegativeButtonStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@android:string/cancel"
|
||||
android:textColor="?attr/colorAccent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/set"
|
||||
style="?attr/buttonBarPositiveButtonStyle"
|
||||
android:layout_width="0dp"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/set"
|
||||
android:textColor="?attr/colorPrimary" />
|
||||
android:text="@string/set" />
|
||||
<Button
|
||||
android:id="@+id/cancel"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@android:string/cancel" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -125,25 +125,18 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="bottom"
|
||||
android:orientation="horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/ok"
|
||||
style="?attr/buttonBarPositiveButtonStyle"
|
||||
android:layout_width="0dp"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@android:string/ok"
|
||||
android:textColor="?attr/colorPrimary"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -26,25 +26,11 @@
|
||||
app:maxHeight="360dp"
|
||||
app:maxWidth="320dp">
|
||||
|
||||
<LinearLayout
|
||||
<com.hippo.widget.lockpattern.LockPatternView
|
||||
android:id="@+id/pattern_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.hippo.widget.lockpattern.LockPatternView
|
||||
android:id="@+id/pattern_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/fingerprint_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:src="@drawable/ic_fp_40px"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.hippo.widget.MaxSizeContainer>
|
||||
</FrameLayout>
|
||||
Reference in new issue
Block a user