-
Notifications
You must be signed in to change notification settings - Fork 304
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Lib] Migrate passcodelock directly into simplenote as a library module.
- Loading branch information
1 parent
dcd5451
commit b812d10
Showing
42 changed files
with
1,616 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
buildscript { | ||
repositories { | ||
google() | ||
mavenCentral() | ||
} | ||
|
||
} | ||
|
||
plugins { | ||
id 'com.android.library' | ||
} | ||
|
||
android { | ||
namespace 'org.wordpress.passcodelock' | ||
compileSdk 34 | ||
|
||
defaultConfig { | ||
minSdk 23 | ||
|
||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | ||
} | ||
|
||
buildTypes { | ||
release { | ||
minifyEnabled true | ||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | ||
} | ||
} | ||
compileOptions { | ||
sourceCompatibility JavaVersion.VERSION_1_8 | ||
targetCompatibility JavaVersion.VERSION_1_8 | ||
} | ||
} | ||
|
||
dependencies { | ||
implementation 'androidx.appcompat:appcompat:1.0.2' | ||
implementation 'androidx.preference:preference:1.0.0' | ||
} | ||
|
||
android.buildTypes.all { buildType -> | ||
project.properties.any { property -> | ||
if (property.key.toLowerCase().startsWith("passcodelock.")) { | ||
buildType.buildConfigField "String", property.key.replace("passcodelock.", "").replace(".", "_").toUpperCase(), "\"${property.value}\"" | ||
} | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
android.enableJetifier=true | ||
android.useAndroidX=true | ||
|
||
passcodelock.password_preference_key=passcode_lock_prefs_password_key | ||
passcodelock.password_enc_secret=5-maggio-2002-Karel-Poborsky | ||
passcodelock.fingerprint_enabled_key=passcode_lock_prefs_fingerprint_enabled_key | ||
|
||
ossrhUsername=hello | ||
ossrhPassword=world | ||
|
||
signing.keyId=byebye | ||
signing.password=secret | ||
signing.secretKeyRingFile=/home/user/secret.gpg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Add project specific ProGuard rules here. | ||
# You can control the set of applied configuration files using the | ||
# proguardFiles setting in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
||
</manifest> |
86 changes: 86 additions & 0 deletions
86
PasscodeLock/src/main/java/org/wordpress/passcodelock/AbstractAppLock.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package org.wordpress.passcodelock; | ||
|
||
import android.annotation.TargetApi; | ||
import android.app.Application; | ||
import android.os.Build; | ||
|
||
/** | ||
* Interface for AppLock implementations. | ||
* | ||
* There are situations where the AppLock should not be required within an app. Methods for tracking | ||
* exempt {@link android.app.Activity}'s are provided and sub-class implementations are expected to | ||
* comply with requested exemptions. | ||
* @see #isExemptActivity(String) | ||
* @see #setExemptActivities(String[]) | ||
* @see #getExemptActivities() | ||
* | ||
* Applications can request a one-time delay in locking the app. This can be useful for activities | ||
* that launch external applications with the expectation that the user will return to the calling | ||
* application shortly. | ||
*/ | ||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) | ||
public abstract class AbstractAppLock implements Application.ActivityLifecycleCallbacks { | ||
public static final String FINGERPRINT_VERIFICATION_BYPASS = "fingerprint-bypass__"; | ||
public static final int DEFAULT_TIMEOUT_S = 2; | ||
public static final int EXTENDED_TIMEOUT_S = 60; | ||
|
||
private int mLockTimeout = DEFAULT_TIMEOUT_S; | ||
private String[] mExemptActivities; | ||
|
||
public boolean isExemptActivity(String name) { | ||
if (name == null) return false; | ||
for (String activityName : getExemptActivities()) { | ||
if (name.equals(activityName)) return true; | ||
} | ||
return false; | ||
} | ||
|
||
public void setExemptActivities(String[] exemptActivities) { | ||
mExemptActivities = exemptActivities; | ||
} | ||
|
||
public String[] getExemptActivities() { | ||
if (mExemptActivities == null) setExemptActivities(new String[0]); | ||
return mExemptActivities; | ||
} | ||
|
||
public void setOneTimeTimeout(int timeout) { | ||
mLockTimeout = timeout; | ||
} | ||
|
||
public int getTimeout() { | ||
return mLockTimeout; | ||
} | ||
|
||
protected boolean isFingerprintPassword(String password) { | ||
return FINGERPRINT_VERIFICATION_BYPASS.equals(password); | ||
} | ||
|
||
/** | ||
* Whether the fingerprint unlocking should be available as option in the unlock screen. | ||
* Default is true, but implementation can override this and make their choice. | ||
* | ||
* Note that this doesn't affect system setting, the device must already have fingerprint unlock | ||
* available and correctly working. | ||
* | ||
* @return true if fingerprint unlock should be enabled on the lock screen | ||
*/ | ||
public boolean isFingerprintEnabled() { | ||
return true; | ||
} | ||
|
||
// Stub methods to avoid sub-classes to override to many unused methods. | ||
public boolean enableFingerprint() { | ||
return true; | ||
} | ||
public boolean disableFingerprint() { | ||
return false; | ||
} | ||
|
||
public abstract void enable(); | ||
public abstract void disable(); | ||
public abstract void forcePasswordLock(); | ||
public abstract boolean verifyPassword(String password); | ||
public abstract boolean isPasswordLocked(); | ||
public abstract boolean setPassword(String password); | ||
} |
188 changes: 188 additions & 0 deletions
188
PasscodeLock/src/main/java/org/wordpress/passcodelock/AbstractPasscodeKeyboardActivity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
package org.wordpress.passcodelock; | ||
|
||
import android.app.Activity; | ||
import android.content.pm.ActivityInfo; | ||
import android.os.Bundle; | ||
import android.text.InputFilter; | ||
import android.text.Spanned; | ||
import android.view.HapticFeedbackConstants; | ||
import android.view.View; | ||
import android.view.View.OnClickListener; | ||
import android.view.animation.Animation; | ||
import android.view.animation.AnimationUtils; | ||
import android.widget.EditText; | ||
import android.widget.TextView; | ||
import android.widget.Toast; | ||
|
||
import androidx.core.hardware.fingerprint.FingerprintManagerCompat; | ||
import androidx.core.os.CancellationSignal; | ||
|
||
public abstract class AbstractPasscodeKeyboardActivity extends Activity { | ||
public static final String KEY_MESSAGE = "message"; | ||
|
||
protected EditText mPinCodeField; | ||
protected InputFilter[] filters = null; | ||
protected TextView topMessage = null; | ||
|
||
protected FingerprintManagerCompat mFingerprintManager; | ||
protected CancellationSignal mCancel; | ||
|
||
@Override | ||
protected void onCreate(Bundle savedInstanceState) { | ||
super.onCreate(savedInstanceState); | ||
|
||
if (!getResources().getBoolean(R.bool.allow_rotation)) { | ||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); | ||
} | ||
|
||
setContentView(R.layout.app_passcode_keyboard); | ||
|
||
topMessage = (TextView) findViewById(R.id.passcodelock_prompt); | ||
|
||
Bundle extras = getIntent().getExtras(); | ||
if (extras != null) { | ||
String message = extras.getString(KEY_MESSAGE); | ||
if (message != null) { | ||
topMessage.setText(message); | ||
} | ||
} | ||
|
||
filters = new InputFilter[2]; | ||
filters[0]= new InputFilter.LengthFilter(1); | ||
filters[1] = onlyNumber; | ||
|
||
mPinCodeField = (EditText)findViewById(R.id.pin_field); | ||
|
||
//setup the keyboard | ||
findViewById(R.id.button0).setOnClickListener(defaultButtonListener); | ||
findViewById(R.id.button1).setOnClickListener(defaultButtonListener); | ||
findViewById(R.id.button2).setOnClickListener(defaultButtonListener); | ||
findViewById(R.id.button3).setOnClickListener(defaultButtonListener); | ||
findViewById(R.id.button4).setOnClickListener(defaultButtonListener); | ||
findViewById(R.id.button5).setOnClickListener(defaultButtonListener); | ||
findViewById(R.id.button6).setOnClickListener(defaultButtonListener); | ||
findViewById(R.id.button7).setOnClickListener(defaultButtonListener); | ||
findViewById(R.id.button8).setOnClickListener(defaultButtonListener); | ||
findViewById(R.id.button9).setOnClickListener(defaultButtonListener); | ||
findViewById(R.id.button_erase).setOnClickListener( | ||
new OnClickListener() { | ||
@Override | ||
public void onClick(View arg0) { | ||
if (arg0.isHapticFeedbackEnabled()) { | ||
arg0.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); | ||
} | ||
|
||
String curText = mPinCodeField.getText().toString(); | ||
|
||
if (curText.length() > 0) { | ||
mPinCodeField.setText(curText.substring(0, curText.length() - 1)); | ||
mPinCodeField.setSelection(mPinCodeField.length()); | ||
} | ||
} | ||
}); | ||
|
||
mFingerprintManager = FingerprintManagerCompat.from(this); | ||
} | ||
|
||
@Override | ||
public void onPause() { | ||
super.onPause(); | ||
|
||
if (mCancel != null) { | ||
mCancel.cancel(); | ||
} | ||
} | ||
|
||
protected AbstractAppLock getAppLock() { | ||
return AppLockManager.getInstance().getAppLock(); | ||
} | ||
|
||
private OnClickListener defaultButtonListener = new OnClickListener() { | ||
@Override | ||
public void onClick(View arg0) { | ||
int currentValue = -1; | ||
int id = arg0.getId(); | ||
if (id == R.id.button0) { | ||
currentValue = 0; | ||
} else if (id == R.id.button1) { | ||
currentValue = 1; | ||
} else if (id == R.id.button2) { | ||
currentValue = 2; | ||
} else if (id == R.id.button3) { | ||
currentValue = 3; | ||
} else if (id == R.id.button4) { | ||
currentValue = 4; | ||
} else if (id == R.id.button5) { | ||
currentValue = 5; | ||
} else if (id == R.id.button6) { | ||
currentValue = 6; | ||
} else if (id == R.id.button7) { | ||
currentValue = 7; | ||
} else if (id == R.id.button8) { | ||
currentValue = 8; | ||
} else if (id == R.id.button9) { | ||
currentValue = 9; | ||
} | ||
|
||
if (arg0.isHapticFeedbackEnabled()) { | ||
arg0.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); | ||
} | ||
|
||
// Add value and move focus. | ||
mPinCodeField.append(String.valueOf(currentValue)); | ||
mPinCodeField.setSelection(mPinCodeField.length()); | ||
|
||
if (mPinCodeField.length() >= 4) { | ||
onPinLockInserted(); | ||
} | ||
} | ||
}; | ||
|
||
protected void authenticationSucceeded() { | ||
setResult(RESULT_OK); | ||
finish(); | ||
} | ||
|
||
protected void authenticationFailed() { | ||
Thread shake = new Thread() { | ||
public void run() { | ||
Animation shake = AnimationUtils.loadAnimation(AbstractPasscodeKeyboardActivity.this, R.anim.shake); | ||
findViewById(R.id.AppUnlockLinearLayout1).startAnimation(shake); | ||
showPasswordError(); | ||
mPinCodeField.setText(""); | ||
} | ||
}; | ||
runOnUiThread(shake); | ||
} | ||
|
||
protected void showPasswordError(){ | ||
Toast.makeText(AbstractPasscodeKeyboardActivity.this, R.string.passcode_wrong_passcode, Toast.LENGTH_SHORT).show(); | ||
} | ||
|
||
protected abstract void onPinLockInserted(); | ||
protected abstract FingerprintManagerCompat.AuthenticationCallback getFingerprintCallback(); | ||
|
||
private InputFilter onlyNumber = new InputFilter() { | ||
@Override | ||
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { | ||
if (source.length() > 1) { | ||
return ""; | ||
} | ||
|
||
if (source.length() == 0) { | ||
return null; | ||
} | ||
|
||
try { | ||
int number = Integer.parseInt(source.toString()); | ||
if (number >= 0 && number <= 9) { | ||
return String.valueOf(number); | ||
} | ||
|
||
return ""; | ||
} catch (NumberFormatException e) { | ||
return ""; | ||
} | ||
} | ||
}; | ||
} |
Oops, something went wrong.