diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
old mode 100644
new mode 100755
index 077193be3..4d9507ff7
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,7 @@
+
diff --git a/app/src/main/java/com/hippo/ehviewer/Settings.java b/app/src/main/java/com/hippo/ehviewer/Settings.java
old mode 100644
new mode 100755
index 12f20231e..f41b95bcf
--- a/app/src/main/java/com/hippo/ehviewer/Settings.java
+++ b/app/src/main/java/com/hippo/ehviewer/Settings.java
@@ -911,6 +911,16 @@ public class Settings {
putString(KEY_SECURITY, value);
}
+ public static final String KEY_ENABLE_FINGERPRINT = "enable_fingerprint";
+
+ public static boolean getEnableFingerprint() {
+ return getBoolean(KEY_ENABLE_FINGERPRINT, false);
+ }
+
+ public static void putEnableFingerprint(boolean value) {
+ putBoolean(KEY_ENABLE_FINGERPRINT, value);
+ }
+
public static final String KEY_READ_CACHE_SIZE = "read_cache_size";
public static final int DEFAULT_READ_CACHE_SIZE = 160;
diff --git a/app/src/main/java/com/hippo/ehviewer/ui/SetSecurityActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/SetSecurityActivity.java
old mode 100644
new mode 100755
index ebc9b3954..e17ca11a0
--- a/app/src/main/java/com/hippo/ehviewer/ui/SetSecurityActivity.java
+++ b/app/src/main/java/com/hippo/ehviewer/ui/SetSecurityActivity.java
@@ -16,11 +16,13 @@
package com.hippo.ehviewer.ui;
+import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.MenuItem;
import android.view.View;
+import android.widget.CheckBox;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.Settings;
@@ -36,6 +38,8 @@ public class SetSecurityActivity extends ToolbarActivity implements View.OnClick
private View mCancel;
@Nullable
private View mSet;
+ @Nullable
+ private CheckBox mFingerprint;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -46,6 +50,7 @@ public class SetSecurityActivity extends ToolbarActivity implements View.OnClick
mPatternView = (LockPatternView) ViewUtils.$$(this, R.id.pattern_view);
mCancel = ViewUtils.$$(this, R.id.cancel);
mSet = ViewUtils.$$(this, R.id.set);
+ mFingerprint = (CheckBox) ViewUtils.$$(this, R.id.fingerprint_checkbox);
String pattern = Settings.getSecurity();
if (!TextUtils.isEmpty(pattern)) {
@@ -53,6 +58,16 @@ public class SetSecurityActivity extends ToolbarActivity implements View.OnClick
LockPatternUtils.stringToPattern(pattern));
}
+ 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.hasEnrolledFingerprints()) {
+ mFingerprint.setVisibility(View.VISIBLE);
+ mFingerprint.setChecked(Settings.getEnableFingerprint());
+ }
+ }
+
mCancel.setOnClickListener(this);
mSet.setOnClickListener(this);
}
@@ -79,7 +94,7 @@ public class SetSecurityActivity extends ToolbarActivity implements View.OnClick
if (v == mCancel) {
finish();
} else if (v == mSet) {
- if (null != mPatternView) {
+ if (null != mPatternView && null != mFingerprint) {
String security;
if (mPatternView.getCellSize() <= 1) {
security = "";
@@ -87,6 +102,8 @@ public class SetSecurityActivity extends ToolbarActivity implements View.OnClick
security = mPatternView.getPatternString();
}
Settings.putSecurity(security);
+ Settings.putEnableFingerprint(mFingerprint.getVisibility() == View.VISIBLE &&
+ mFingerprint.isChecked() && !security.isEmpty());
}
finish();
}
diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/SecurityScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/SecurityScene.java
old mode 100644
new mode 100755
index 79736a93e..57ce348cd
--- a/app/src/main/java/com/hippo/ehviewer/ui/scene/SecurityScene.java
+++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/SecurityScene.java
@@ -19,11 +19,15 @@ 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.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ImageView;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.Settings;
@@ -42,15 +46,21 @@ 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;
+ private FingerprintManager mFingerprintManager;
+
+ private CancellationSignal mFingerprintCancellationSignal;
private int mRetryTimes;
@@ -73,6 +83,9 @@ 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;
@@ -97,6 +110,38 @@ public class SecurityScene extends SolidScene implements
if (null != mShakeDetector) {
mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}
+
+ 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);
+ }
+
+ @Override
+ public void onAuthenticationFailed() {
+ fingerprintError(false);
+ }
+
+ @Override
+ public void onAuthenticationSucceeded(
+ FingerprintManager.AuthenticationResult result) {
+ mFingerprintIcon.setImageResource(R.drawable.ic_fingerprint_success);
+ mFingerprintIcon.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ startSceneForCheckStep(CHECK_STEP_SECURITY, getArguments());
+ finish();
+ }
+ }, SUCCESS_DELAY_MILLIS);
+
+ }
+ }, null);
+ }
}
@Override
@@ -106,6 +151,10 @@ public class SecurityScene extends SolidScene implements
if (null != mShakeDetector) {
mSensorManager.unregisterListener(mShakeDetector);
}
+ if (isFingerprintAuthAvailable() && mFingerprintCancellationSignal != null) {
+ mFingerprintCancellationSignal.cancel();
+ mFingerprintCancellationSignal = null;
+ }
}
@Override
@@ -123,6 +172,11 @@ 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;
}
@@ -176,4 +230,38 @@ public class SecurityScene extends SolidScene implements
finish();
}
}
+
+ 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
+ && mFingerprintManager.isHardwareDetected()
+ && mFingerprintManager.hasEnrolledFingerprints();
+ }
+
+ private Runnable mResetFingerprintRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (mFingerprintIcon != null)
+ mFingerprintIcon.setImageResource(R.drawable.ic_fp_40px);
+ }
+ };
+
+ private void fingerprintError(boolean unrecoverable) {
+ // Do not decrease mRetryTimes here since Android system will handle it :)
+ mFingerprintIcon.setImageResource(R.drawable.ic_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);
+ }
+ }
}
diff --git a/app/src/main/res/drawable-hdpi/ic_fp_40px.png b/app/src/main/res/drawable-hdpi/ic_fp_40px.png
new file mode 100755
index 000000000..48ebd8ad7
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_fp_40px.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_fingerprint_error.xml b/app/src/main/res/drawable-mdpi/ic_fingerprint_error.xml
new file mode 100755
index 000000000..be46116da
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_fingerprint_error.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable-mdpi/ic_fingerprint_success.xml b/app/src/main/res/drawable-mdpi/ic_fingerprint_success.xml
new file mode 100755
index 000000000..261f3e7fb
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_fingerprint_success.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable-mdpi/ic_fp_40px.png b/app/src/main/res/drawable-mdpi/ic_fp_40px.png
new file mode 100755
index 000000000..122f44257
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_fp_40px.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_fp_40px.png b/app/src/main/res/drawable-xhdpi/ic_fp_40px.png
new file mode 100755
index 000000000..e1c9590bb
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_fp_40px.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_fp_40px.png b/app/src/main/res/drawable-xxhdpi/ic_fp_40px.png
new file mode 100755
index 000000000..0fb854524
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_fp_40px.png differ
diff --git a/app/src/main/res/layout-land/activity_set_security.xml b/app/src/main/res/layout-land/activity_set_security.xml
old mode 100644
new mode 100755
index 6f4b4e0bb..3ed310944
--- a/app/src/main/res/layout-land/activity_set_security.xml
+++ b/app/src/main/res/layout-land/activity_set_security.xml
@@ -40,6 +40,15 @@
android:layout_height="0dp"
android:layout_weight="1"/>
+
+
+
+
+ app:maxHeight="360dp">
-
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+
+
+
+
+
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
old mode 100644
new mode 100755
index 57e3cdc9d..277101195
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -334,6 +334,7 @@
Establecer Proteccion po Patrón
Dibujar un patrón para establecer la proteccion por patrón. \nDejar en blanco para quitar la proteccion por patrón.
Establecer
+ Permitir desbloquear con huella dactilar
Pagina %d
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
old mode 100644
new mode 100755
index 2f3cc1dae..24a2cc72a
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -341,6 +341,7 @@
设置图案保护
绘制图案来设置图案保护\n留空来取消图案保护
设置
+ 允许使用指纹解锁
第 %d 页
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
old mode 100644
new mode 100755
index cfa29a93f..2d8f9f074
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -341,6 +341,7 @@
設置圖案保護
繪製圖案來設置圖案保護\n留空來取消圖案保護
設置
+ 允許使用指紋解鎖
第 %d 頁
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
old mode 100644
new mode 100755
index ca372446a..a48608cc6
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -341,6 +341,7 @@
設定圖案保護
繪製圖案來設定圖案保護\n留空來取消圖案保護
設定
+ 允許使用指紋解鎖
第 %d 頁
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
old mode 100644
new mode 100755
index 7e4d1e43a..27437f2bb
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -385,6 +385,7 @@
Set pattern protection
Draw a pattern to set pattern protection\nLeave blank to clear pattern protection
Set
+ Also allow unlock with fingerprint
Page %d