Skip to content

Commit

Permalink
[Lib] Migrate passcodelock directly into simplenote as a library module.
Browse files Browse the repository at this point in the history
  • Loading branch information
notandyvee committed Aug 12, 2024
1 parent dcd5451 commit b812d10
Show file tree
Hide file tree
Showing 42 changed files with 1,616 additions and 1 deletion.
1 change: 1 addition & 0 deletions PasscodeLock/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
46 changes: 46 additions & 0 deletions PasscodeLock/build.gradle
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 added PasscodeLock/consumer-rules.pro
Empty file.
13 changes: 13 additions & 0 deletions PasscodeLock/gradle.properties
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
21 changes: 21 additions & 0 deletions PasscodeLock/proguard-rules.pro
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
4 changes: 4 additions & 0 deletions PasscodeLock/src/main/AndroidManifest.xml
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>
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);
}
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 "";
}
}
};
}
Loading

0 comments on commit b812d10

Please sign in to comment.