Use BiometricPrompt

This commit is contained in:
NekoInverter committed 2020-03-23 20:49:07 +08:00
1 parent 5979103f51
commit f84e944181
7 files changed
+58 -153

No files matched your search

@@ -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;
}
}