Compare commits

..

24 commits
1.0 ... master

Author SHA1 Message Date
wesaphzt
0cfce130fd add lock stats 2019-09-22 16:12:49 +01:00
wesaphzt
1b0d587a8d minor code clean up 2019-09-22 16:12:21 +01:00
wesaphzt
995403a129 formatting 2019-09-22 13:38:19 +01:00
wesaphzt
0aa22e93e3 add changelog 2019-09-22 13:34:05 +01:00
wesaphzt
36bb398fd4 release 1.2 2019-09-20 13:06:13 +01:00
wesaphzt
6b560beac8 fix background service for < 8.0 2019-09-20 13:04:11 +01:00
wesaphzt
248a8eeb0b haptic feedback 2019-09-17 13:26:58 +01:00
wesaphzt
000eb550a2 fix links 2019-09-15 14:53:47 +01:00
wesaphzt
e51a510645 reworked animation logic 2019-09-14 16:39:18 +01:00
wesaphzt
18018360d3 check for admin 2019-09-11 22:45:25 +01:00
wesaphzt
1cc68f0fff add onActivityResult super 2019-09-11 22:43:45 +01:00
wesaphzt
063beba464 adjust constant run option slightly to prevent annoying artifact 2019-09-09 20:21:24 +01:00
wesaphzt
10db550988 boot update 2019-09-09 16:13:21 +01:00
wesaphzt
1b2a5139b9 version increase 2019-09-09 13:48:09 +01:00
wesaphzt
813b948f19 option to run locking functionality while phone is locked to force pin 2019-09-09 13:33:04 +01:00
wesaphzt
53828ddc3f fix to stop service correctly preventing mem leak & code cleanup 2019-09-08 20:00:33 +01:00
wesaphzt
4d67f4dd47 notification priority for nougat & < changed to low 2019-09-07 19:54:36 +01:00
wesaphzt
0a0079db37 intro slide changes 2019-09-07 16:09:45 +01:00
wesaphzt
87e349d02a animation scaling issues fixed 2019-09-07 16:00:32 +01:00
wesaphzt
cd8226cddc gradle update 2019-09-07 15:58:27 +01:00
wesaphzt
c2b6299102 Merge remote-tracking branch 'origin/master' 2019-07-04 10:16:51 +01:00
wesaphzt
480907063b Update gradle.properties 2019-07-04 10:16:15 +01:00
wesaphzt
785f8d3eac
Update README.md 2019-07-03 16:02:07 +00:00
wesaphzt
4fe08078e0
Update README.md 2019-07-03 15:52:27 +00:00
24 changed files with 631 additions and 237 deletions

116
.idea/codeStyles/Project.xml generated Normal file
View file

@ -0,0 +1,116 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>

21
CHANGELOG.md Normal file
View file

@ -0,0 +1,21 @@
Changelog
==========
Release 1.2 *(2019-09-21)*
----------------------------
* Fix for background service < Android 8.0/Oreo
* Add option for haptic feedback (vibration) on lock trigger
* Reworked animation logic
* Fix 'License' and 'Bug report' links on about page
Release 1.1 *(2019-06-25)*
----------------------------
* Animation scaling issues fixed
* Stop service correctly to fix memory leak & reduce code
* Notification priority changed to low for Nougat and lower
* Option added to run service when screen is off to be able to force PIN entry
* Gradle & library updates
Release 1.0 *(2019-06-01)*
----------------------------
* Initial release

View file

@ -1,10 +1,9 @@
# Private Lock # Private Lock
<a href="https://github.com/wesaphzt/privatelock/releases/latest" alt="GitHub Release"><img src="https://img.shields.io/github/release/wesaphzt/privatelock.svg?logo=github"></a> <a href="https://github.com/wesaphzt/privatelock/releases/latest" alt="GitHub Release"><img src="https://img.shields.io/github/release/wesaphzt/privatelock.svg?logo=github"></a>
[![License](https://img.shields.io/github/license/wesaphzt/privatelock.svg)](LICENSE) [![License](https://img.shields.io/github/license/wesaphzt/privatelock.svg?color=green)](LICENSE)
[<img alt="Get it on F-Droid" height="75" src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png">](https://f-droid.org/packages/com.wesaphzt.privatelock/) [<img alt="Get it on F-Droid" height="75" src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png">](https://f-droid.org/packages/com.wesaphzt.privatelock/)
[description]
A simple app to automatically lock your phone based on movement force, or the acceleration to be more accurate. A simple app to automatically lock your phone based on movement force, or the acceleration to be more accurate.
Private Lock can help protect your privacy and security by monitoring the accelerometer in the background and if the threshold is breached, lock the screen. Private Lock can help protect your privacy and security by monitoring the accelerometer in the background and if the threshold is breached, lock the screen.

View file

@ -1,13 +1,13 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 28 compileSdkVersion 29
defaultConfig { defaultConfig {
applicationId "com.wesaphzt.privatelock" applicationId "com.wesaphzt.privatelock"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 28 targetSdkVersion 29
versionCode 1 versionCode 3
versionName "1.0" versionName "1.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {
@ -22,10 +22,10 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.intuit.sdp:sdp-android:1.0.3' implementation 'com.intuit.sdp:sdp-android:1.0.3'
implementation 'androidx.preference:preference:1.0.0' implementation 'androidx.preference:preference:1.1.0'
implementation 'com.github.AppIntro:AppIntro:5.1.0' implementation 'com.github.AppIntro:AppIntro:5.1.0'
implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.0.0' implementation 'com.google.android.material:material:1.0.0'

View file

@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.VIBRATE" />
<!--pre-oreo--> <!--pre-oreo-->
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />

View file

@ -22,10 +22,11 @@ import androidx.fragment.app.FragmentTransaction;
import android.os.CountDownTimer; import android.os.CountDownTimer;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View; import android.view.View;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.ViewTreeObserver;
import android.widget.RelativeLayout;
import android.widget.SeekBar; import android.widget.SeekBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
@ -36,10 +37,11 @@ import com.wesaphzt.privatelock.fragments.FragmentAbout;
import com.wesaphzt.privatelock.fragments.FragmentDonate; import com.wesaphzt.privatelock.fragments.FragmentDonate;
import com.wesaphzt.privatelock.fragments.FragmentSettings; import com.wesaphzt.privatelock.fragments.FragmentSettings;
import com.wesaphzt.privatelock.receivers.DeviceAdminReceiver; import com.wesaphzt.privatelock.receivers.DeviceAdminReceiver;
import com.wesaphzt.privatelock.receivers.PauseReceiver;
import com.wesaphzt.privatelock.service.LockService; import com.wesaphzt.privatelock.service.LockService;
import com.wesaphzt.privatelock.widget.LockWidgetProvider; import com.wesaphzt.privatelock.widget.LockWidgetProvider;
import java.util.Locale;
import static com.wesaphzt.privatelock.service.LockService.CHANNEL_ID; import static com.wesaphzt.privatelock.service.LockService.CHANNEL_ID;
import static com.wesaphzt.privatelock.service.LockService.DEFAULT_SENSITIVITY; import static com.wesaphzt.privatelock.service.LockService.DEFAULT_SENSITIVITY;
import static com.wesaphzt.privatelock.service.LockService.activeListener; import static com.wesaphzt.privatelock.service.LockService.activeListener;
@ -54,7 +56,6 @@ public class MainActivity extends AppCompatActivity {
private boolean mInitialized; private boolean mInitialized;
private static SensorManager mSensorManager; private static SensorManager mSensorManager;
private Sensor mAccelerometer; private Sensor mAccelerometer;
private final float NOISE = (float) 2.0;
private SensorEventListener mActiveListener; private SensorEventListener mActiveListener;
@ -70,22 +71,26 @@ public class MainActivity extends AppCompatActivity {
public static final String PREFS_THRESHOLD = "THRESHOLD"; public static final String PREFS_THRESHOLD = "THRESHOLD";
private CountDownTimer cdTimer; private CountDownTimer cdTimer;
private final int cdTimerLength = 2000; private final int cdTimerLength = 1500;
private boolean isRunning = false; private boolean isRunning = false;
private boolean isHit = false;
//stats
private TextView tvLastBreachValue;
private TextView tvAvgBreachValue;
private TextView tvHighestBreachValue;
private int triggerCount = 0;
private float avgBreachValueTotal = 0;
private double highestBreach = 0;
private Circle circle; private Circle circle;
private Circle circle_bg; private Circle circle_bg;
//circle bg color
private int circleBgR = 240; private int circleBgG = 240; private int circleBgB = 240;
//circle color //circle color
private int circleDefaultR = 88; private int circleDefaultG = 186; private int circleDefaultB = 255; private int circleDefaultR = 88; private int circleDefaultG = 186; private int circleDefaultB = 255;
//circle lock color
private int circleLockR = 88; private int circleLockG = 255; private int circleLockB = 135;
int animationDuration = 220; int animationDuration = 220;
//first run CircleAngleAnimation animation;
final private String PREF_VERSION_CODE_KEY = "VERSION_CODE";
final private int DOESNT_EXIST = -1;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -126,19 +131,49 @@ public class MainActivity extends AppCompatActivity {
} }
}); });
//https://stackoverflow.com/questions/29381474/how-to-draw-a-circle-with-animation-in-android-with-circle-size-based-on-a-value //animation
circle = findViewById(R.id.circle); circle = findViewById(R.id.circle);
circle_bg = findViewById(R.id.circle_bg); circle_bg = findViewById(R.id.circle_bg);
final RelativeLayout relativeLayout = findViewById(R.id.content_main);
final RelativeLayout rlCircle = findViewById(R.id.rlCircle);
//scale height/width of animation
relativeLayout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//only want to do this once
relativeLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
circle.setRect((circle.getHeight() / 2), (circle.getHeight()) / 2);
circle_bg.setRect((circle_bg.getHeight() / 2), (circle_bg.getHeight()) / 2);
circle.setX((rlCircle.getWidth() - circle.getRect()) / 2);
circle_bg.setX((rlCircle.getWidth() - circle.getRect()) / 2);
}
});
circle.setColor(circleDefaultR, circleDefaultG, circleDefaultB); circle.setColor(circleDefaultR, circleDefaultG, circleDefaultB);
//set background circle //set background circle
CircleAngleAnimation animation = new CircleAngleAnimation(circle_bg, 360); CircleAngleAnimation animation = new CircleAngleAnimation(circle_bg, 360);
//initial animation //initial animation
animation.setDuration(500); animation.setDuration(500);
circle_bg.setColor(circleBgR,circleBgG,circleBgB); //circle bg color
int circleBgR = 240;
int circleBgG = 240;
int circleBgB = 240;
circle_bg.setColor(circleBgR, circleBgG, circleBgB);
circle_bg.startAnimation(animation); circle_bg.startAnimation(animation);
//stats
tvLastBreachValue = findViewById(R.id.tvLastBreachValue);
tvAvgBreachValue = findViewById(R.id.tvAvgBreachValue);
tvHighestBreachValue = findViewById(R.id.tvHighestBreachValue);
//shared prefs //shared prefs
try { try {
mSensitivity = prefs.getInt(PREFS_THRESHOLD, DEFAULT_SENSITIVITY); mSensitivity = prefs.getInt(PREFS_THRESHOLD, DEFAULT_SENSITIVITY);
@ -148,12 +183,19 @@ public class MainActivity extends AppCompatActivity {
//timer when lock hit //timer when lock hit
cdTimer = new CountDownTimer(cdTimerLength, 1000) { cdTimer = new CountDownTimer(cdTimerLength, 1000) {
public void onTick(long millisUntilFinished) { public void onTick(long millisUntilFinished) {
isRunning = true; isRunning = true;
isHit = true;
} }
public void onFinish() { public void onFinish() {
isRunning = false; isRunning = false;
isHit = false;
circle.setColor(circleDefaultR, circleDefaultG, circleDefaultB); circle.setColor(circleDefaultR, circleDefaultG, circleDefaultB);
//reset stat variables
triggerCount = 0;
avgBreachValueTotal = 0;
highestBreach = 0;
} }
}; };
@ -222,6 +264,7 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//launch service if permission granted //launch service if permission granted
if (requestCode == REQUEST_CODE_ENABLE_ADMIN) { if (requestCode == REQUEST_CODE_ENABLE_ADMIN) {
if(resultCode == Activity.RESULT_OK) { if(resultCode == Activity.RESULT_OK) {
@ -270,27 +313,12 @@ public class MainActivity extends AppCompatActivity {
private void startServicePrep() { private void startServicePrep() {
//stop this listener //stop this listener
mSensorManager.unregisterListener(mActiveListener); mSensorManager.unregisterListener(mActiveListener);
Intent intent = new Intent(context, LockService.class);
try { //start service intent
//stop any already running service Intent startIntent = new Intent(context, LockService.class);
LockService.mSensorManager.unregisterListener(LockService.activeListener); startIntent.setAction(LockService.ACTION_START_FOREGROUND_SERVICE);
startLockService(intent);
LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
lockWidgetProvider.setWidgetStart(context);
//cancel any pause timer that might be running startLockService(startIntent);
try {
PauseReceiver.mCountdown.cancel();
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
startLockService(intent);
LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
lockWidgetProvider.setWidgetStart(context);
}
} }
@Override @Override
@ -376,7 +404,10 @@ public class MainActivity extends AppCompatActivity {
//get current version code //get current version code
int currentVersionCode = BuildConfig.VERSION_CODE; int currentVersionCode = BuildConfig.VERSION_CODE;
//get saved version code //get saved version code
int DOESNT_EXIST = -1;
int savedVersionCode = DOESNT_EXIST; int savedVersionCode = DOESNT_EXIST;
//first run
String PREF_VERSION_CODE_KEY = "VERSION_CODE";
try { try {
savedVersionCode = this.prefs.getInt(PREF_VERSION_CODE_KEY, DOESNT_EXIST); savedVersionCode = this.prefs.getInt(PREF_VERSION_CODE_KEY, DOESNT_EXIST);
} catch (Exception e) { } catch (Exception e) {
@ -411,6 +442,7 @@ public class MainActivity extends AppCompatActivity {
float deltaY = Math.abs(mLastY - y); float deltaY = Math.abs(mLastY - y);
float deltaZ = Math.abs(mLastZ - z); float deltaZ = Math.abs(mLastZ - z);
float NOISE = (float) 2.0;
if (deltaX < NOISE) deltaX = (float) 0.0; if (deltaX < NOISE) deltaX = (float) 0.0;
if (deltaY < NOISE) deltaY = (float) 0.0; if (deltaY < NOISE) deltaY = (float) 0.0;
if (deltaZ < NOISE) deltaZ = (float) 0.0; if (deltaZ < NOISE) deltaZ = (float) 0.0;
@ -419,35 +451,59 @@ public class MainActivity extends AppCompatActivity {
mLastY = y; mLastY = y;
mLastZ = z; mLastZ = z;
float total = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ); float total = (float) Math.sqrt((deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ));
int calculatedAngleInt; int calculatedAngleInt = 0;
if (total <= mSensitivity) { if (total >= mSensitivity) {
//do nothing if timer currently running //lock screen threshold hit
stats(total);
if(!isHit) {
CircleAngleAnimation anim = new CircleAngleAnimation(circle, 360);
//circle lock color
int circleLockR = 88;
int circleLockG = 255;
int circleLockB = 135;
circle.setColor(circleLockR, circleLockG, circleLockB);
anim.setDuration(animationDuration);
//set lock color
circle.startAnimation(anim);
isHit = true;
cdTimer.start();
} else {
if(!isRunning) {
isRunning = true;
}
}
} else {
if(isRunning) if(isRunning)
return; return;
if(isHit)
return;
calculatedAngleInt = Math.round((total / mSensitivity) * 360); calculatedAngleInt = Math.round((total / mSensitivity) * 360);
CircleAngleAnimation animation = new CircleAngleAnimation(circle, calculatedAngleInt); animation = new CircleAngleAnimation(circle, calculatedAngleInt);
animation.setDuration(animationDuration); animation.setDuration(animationDuration);
circle.startAnimation(animation); circle.startAnimation(animation);
} else if (total > mSensitivity) {
//lock screen threshold hit
if(isRunning)
//do nothing if timer currently running
return;
CircleAngleAnimation animation = new CircleAngleAnimation(circle, 360);
animation.setDuration(animationDuration);
//set lock color
circle.setColor(circleLockR, circleLockG, circleLockB);
circle.startAnimation(animation);
cdTimer.start();
} }
} }
} }
private void stats(float total) {
tvLastBreachValue.setText(String.format(Locale.ENGLISH, "%.1f", (double) total));
if(total == 0 || total > highestBreach) {
highestBreach = total;
}
tvHighestBreachValue.setText(String.format(Locale.ENGLISH, "%.1f", highestBreach));
triggerCount += 1;
avgBreachValueTotal += total;
tvAvgBreachValue.setText(String.format(Locale.ENGLISH, "%.1f", avgBreachValueTotal / triggerCount));
}
} }

View file

@ -13,15 +13,14 @@ public class Circle extends View {
private static final int START_ANGLE_POINT = 90; private static final int START_ANGLE_POINT = 90;
private final Paint paint; private final Paint paint;
private final RectF rect; private RectF rect;
private float angle; private float angle;
private final int strokeWidth = 10;
public Circle(Context context, AttributeSet attrs) { public Circle(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
final int strokeWidth = 10;
paint = new Paint(); paint = new Paint();
paint.setAntiAlias(true); paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL); paint.setStyle(Paint.Style.FILL);
@ -29,8 +28,8 @@ public class Circle extends View {
//circle color (currently set upon instance) //circle color (currently set upon instance)
//paint.setColor(Color.BLUE); //paint.setColor(Color.BLUE);
//size //size (currently set upon instance)
rect = new RectF(strokeWidth, strokeWidth, 600 + strokeWidth, 600 + strokeWidth); //rect = new RectF(strokeWidth, strokeWidth, 230 + strokeWidth, 230 + strokeWidth);
//initial angle (optional) //initial angle (optional)
angle = 0; angle = 0;
@ -53,4 +52,12 @@ public class Circle extends View {
public void setAngle(float angle) { public void setAngle(float angle) {
this.angle = angle; this.angle = angle;
} }
public void setRect(int right, int bottom) {
this.rect = new RectF(strokeWidth, strokeWidth, right, bottom);
}
public float getRect() {
return rect.right;
}
} }

View file

@ -21,9 +21,8 @@ import com.wesaphzt.privatelock.R;
public class FragmentAbout extends Fragment { public class FragmentAbout extends Fragment {
private static String GITHUB_URI; private static String GITHUB_URI;
private static final String LICENSE_URI = GITHUB_URI + "/blob/master/LICENSE.txt"; private static String LICENSE_URI;
private static final String BUG_REPORT_URI = GITHUB_URI + "/issues"; private static String BUG_REPORT_URI;
private static String AUTHOR_GITHUB; private static String AUTHOR_GITHUB;
@Nullable @Nullable
@ -32,6 +31,8 @@ public class FragmentAbout extends Fragment {
View v = inflater.inflate(R.layout.fragment_about, container, false); View v = inflater.inflate(R.layout.fragment_about, container, false);
GITHUB_URI = getString(R.string.app_github); GITHUB_URI = getString(R.string.app_github);
LICENSE_URI = GITHUB_URI + "/blob/master/LICENSE";
BUG_REPORT_URI = GITHUB_URI + "/issues";
AUTHOR_GITHUB = getString(R.string.app_github_dev); AUTHOR_GITHUB = getString(R.string.app_github_dev);
String versionName = ""; String versionName = "";

View file

@ -7,7 +7,9 @@ import androidx.annotation.Nullable;
import android.view.Menu; import android.view.Menu;
import android.view.View; import android.view.View;
import android.widget.Toast;
import androidx.preference.CheckBoxPreference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
@ -15,17 +17,26 @@ import com.wesaphzt.privatelock.R;
public class FragmentSettings extends PreferenceFragmentCompat { public class FragmentSettings extends PreferenceFragmentCompat {
private SharedPreferences prefs; private Context context;
private CheckBoxPreference cbRunConstant;
private SharedPreferences sharedPreferences;
private SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener;
@Override @Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
setHasOptionsMenu(true); setHasOptionsMenu(true);
Context context = getContext(); context = getContext();
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
//this static call will reset default values only on the first read //this static call will reset default values only on the first read
PreferenceManager.setDefaultValues(context, R.xml.preferences, false); PreferenceManager.setDefaultValues(context, R.xml.preferences, false);
cbRunConstant = (CheckBoxPreference) findPreference("RUN_CONSTANT");
} }
@Override @Override
@ -33,6 +44,24 @@ public class FragmentSettings extends PreferenceFragmentCompat {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
@Override
public void onResume() {
super.onResume();
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
}
@Override
public void onDestroy() {
super.onDestroy();
sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
}
@Override
public void onPause() {
super.onPause();
sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
}
@Override @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
@ -41,6 +70,16 @@ public class FragmentSettings extends PreferenceFragmentCompat {
//bg color //bg color
view.setBackgroundColor(getResources().getColor(R.color.white)); view.setBackgroundColor(getResources().getColor(R.color.white));
sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if(key.equals("RUN_CONSTANT") && cbRunConstant.isChecked()) {
Toast.makeText(context, getString(R.string.settings_restart_service_toast), Toast.LENGTH_LONG).show();
}
}
};
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
} }
@Override @Override

View file

@ -8,7 +8,6 @@ import android.os.Build;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import com.wesaphzt.privatelock.service.LockService; import com.wesaphzt.privatelock.service.LockService;
import com.wesaphzt.privatelock.widget.LockWidgetProvider;
public class BootReceiver extends BroadcastReceiver { public class BootReceiver extends BroadcastReceiver {
@ -16,19 +15,16 @@ public class BootReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if(prefs.getBoolean("START_ON_BOOT", false)) { if(prefs.getBoolean("START_ON_BOOT", false)) {
Intent i = new Intent(context, LockService.class); Intent startIntent = new Intent(context, LockService.class);
startIntent.setAction(LockService.ACTION_START_FOREGROUND_SERVICE);
//check android api //check android api
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(i); context.startForegroundService(startIntent);
LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
lockWidgetProvider.setWidgetStart(context);
} else { } else {
context.startService(i); context.startService(startIntent);
LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
lockWidgetProvider.setWidgetStart(context);
} }
} }
} }

View file

@ -1,20 +1,11 @@
package com.wesaphzt.privatelock.receivers; package com.wesaphzt.privatelock.receivers;
import android.app.NotificationManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build; import android.os.Build;
import android.preference.PreferenceManager;
import com.wesaphzt.privatelock.service.LockService; import com.wesaphzt.privatelock.service.LockService;
import com.wesaphzt.privatelock.widget.LockWidgetProvider;
import com.wesaphzt.privatelock.R;
import static com.wesaphzt.privatelock.service.LockService.activeListener;
import static com.wesaphzt.privatelock.service.LockService.mSensorManager;
import static com.wesaphzt.privatelock.service.LockService.disabled;
public class NotificationReceiver extends BroadcastReceiver { public class NotificationReceiver extends BroadcastReceiver {
@ -23,37 +14,13 @@ public class NotificationReceiver extends BroadcastReceiver {
String action = intent.getStringExtra("lock_service"); String action = intent.getStringExtra("lock_service");
if (action.equals("lock_service_notification")) { if (action.equals("lock_service_notification")) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); Intent stopIntent = new Intent(context, LockService.class);
NotificationManager notificationManager = stopIntent.setAction(LockService.ACTION_STOP_FOREGROUND_SERVICE);
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String id = context.getString(R.string.notification_main_channel_id); context.startForegroundService(stopIntent);
notificationManager.deleteNotificationChannel(id);
if(PauseReceiver.isRunning) {
PauseReceiver.mCountdown.cancel(); PauseReceiver.isRunning = false;
disabled = true;
mSensorManager.unregisterListener(activeListener);
lockWidgetProvider.setWidgetStop(context);
} else {
disabled = true;
mSensorManager.unregisterListener(activeListener);
lockWidgetProvider.setWidgetStop(context);
}
} else { } else {
notificationManager.cancel(LockService.NOTIFICATION_ID); context.startService(stopIntent);
if(PauseReceiver.isRunning) {
PauseReceiver.mCountdown.cancel(); PauseReceiver.isRunning = false;
disabled = true;
mSensorManager.unregisterListener(activeListener);
lockWidgetProvider.setWidgetStop(context);
} else {
disabled = true;
mSensorManager.unregisterListener(activeListener);
lockWidgetProvider.setWidgetStop(context);
}
} }
} }
} }

View file

@ -3,6 +3,8 @@ package com.wesaphzt.privatelock.receivers;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import static com.wesaphzt.privatelock.service.LockService.disabled; import static com.wesaphzt.privatelock.service.LockService.disabled;
import static com.wesaphzt.privatelock.service.LockService.mInitialized; import static com.wesaphzt.privatelock.service.LockService.mInitialized;
@ -11,6 +13,8 @@ public class PresenceReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) { if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
//prevent lock animation artifacts //prevent lock animation artifacts
mInitialized = false; mInitialized = false;
@ -18,7 +22,9 @@ public class PresenceReceiver extends BroadcastReceiver {
disabled = false; disabled = false;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
disabled = true; if(! prefs.getBoolean("RUN_CONSTANT", false)) {
disabled = true;
}
} }
} }
} }

View file

@ -15,12 +15,15 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener; import android.hardware.SensorEventListener;
import android.hardware.SensorManager; import android.hardware.SensorManager;
import android.os.Build; import android.os.Build;
import android.os.CountDownTimer;
import android.os.IBinder; import android.os.IBinder;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.app.JobIntentService; import androidx.core.app.JobIntentService;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.widget.Toast; import android.widget.Toast;
@ -30,7 +33,11 @@ import com.wesaphzt.privatelock.receivers.DeviceAdminReceiver;
import com.wesaphzt.privatelock.receivers.NotificationReceiver; import com.wesaphzt.privatelock.receivers.NotificationReceiver;
import com.wesaphzt.privatelock.receivers.PauseReceiver; import com.wesaphzt.privatelock.receivers.PauseReceiver;
import com.wesaphzt.privatelock.receivers.PresenceReceiver; import com.wesaphzt.privatelock.receivers.PresenceReceiver;
import com.wesaphzt.privatelock.widget.LockWidgetProvider;
import java.util.Objects;
import static androidx.core.app.NotificationCompat.PRIORITY_LOW;
import static androidx.core.app.NotificationCompat.PRIORITY_MIN; import static androidx.core.app.NotificationCompat.PRIORITY_MIN;
public class LockService extends JobIntentService { public class LockService extends JobIntentService {
@ -40,7 +47,6 @@ public class LockService extends JobIntentService {
private float mLastX, mLastY, mLastZ; private float mLastX, mLastY, mLastZ;
public static boolean mInitialized; public static boolean mInitialized;
public static SensorManager mSensorManager; public static SensorManager mSensorManager;
private final float NOISE = (float) 2.0;
public static Sensor mAccelerometer; public static Sensor mAccelerometer;
public static SensorEventListener activeListener; public static SensorEventListener activeListener;
@ -66,55 +72,115 @@ public class LockService extends JobIntentService {
public static final int DEFAULT_SENSITIVITY = 10; public static final int DEFAULT_SENSITIVITY = 10;
public static int SENSITIVITY; public static int SENSITIVITY;
public static final String ACTION_STOP_FOREGROUND_SERVICE = "ACTION_STOP_FOREGROUND_SERVICE";
public static final String ACTION_START_FOREGROUND_SERVICE = "ACTION_START_FOREGROUND_SERVICE";
PresenceReceiver presenceReceiver;
//check to stop multiple triggers
boolean isHit = false;
//vibrate
boolean isHaptic = false;
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
context = getApplicationContext(); context = getApplicationContext();
CHANNEL_ID = getString(R.string.notification_main_channel_id); CHANNEL_ID = getString(R.string.notification_main_channel_id);
CHANNEL_NAME = getString(R.string.notification_main_channel_name); CHANNEL_NAME = getString(R.string.notification_main_channel_name);
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
PresenceReceiver presenceReceiver = new PresenceReceiver(); if (intent != null) {
String action = intent.getAction();
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_USER_PRESENT); LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
intentFilter.addAction(Intent.ACTION_SCREEN_OFF); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
registerReceiver(presenceReceiver, intentFilter);
//------------------------------------------------------------------------------------------
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
try {
SENSITIVITY = prefs.getInt(MainActivity.PREFS_THRESHOLD, DEFAULT_SENSITIVITY);
} catch (Exception e) {
Toast.makeText(context, "Unable to retrieve threshold", Toast.LENGTH_LONG).show();
} assert action != null;
//------------------------------------------------------------------------------------------ switch (action) {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); case ACTION_START_FOREGROUND_SERVICE:
presenceReceiver = new PresenceReceiver();
//dpm IntentFilter intentFilter = new IntentFilter(Intent.ACTION_USER_PRESENT);
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
mDeviceAdmin = new ComponentName(this, DeviceAdminReceiver.class); registerReceiver(presenceReceiver, intentFilter);
//------------------------------------------------------------------------------------------
try {
SENSITIVITY = prefs.getInt(MainActivity.PREFS_THRESHOLD, DEFAULT_SENSITIVITY);
} catch (Exception e) {
Toast.makeText(context, "Unable to retrieve threshold", Toast.LENGTH_LONG).show();
}
//------------------------------------------------------------------------------------------
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//prevent lock animation artifacts //dpm
mInitialized = false; mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mDeviceAdmin = new ComponentName(this, DeviceAdminReceiver.class);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); //prevent lock animation artifacts
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mInitialized = false;
setSensorListener(); mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensorManager.registerListener(activeListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
setNotification(); setSensorListener();
//------------------------------------------------------------------------------------------ mSensorManager.registerListener(activeListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//create foreground service
startForeground(NOTIFICATION_ID, notification);
disabled = false;
setNotification();
//------------------------------------------------------------------------------------------
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//create foreground service
startForeground(NOTIFICATION_ID, notification);
lockWidgetProvider.setWidgetStart(context);
disabled = false;
} else {
notificationManager.notify(NOTIFICATION_ID, notification);
lockWidgetProvider.setWidgetStart(context);
disabled = false;
}
break;
case ACTION_STOP_FOREGROUND_SERVICE:
try {
mSensorManager.unregisterListener(activeListener);
} catch (Exception e) {
e.printStackTrace();
}
unregisterReceiver(presenceReceiver);
disabled = true;
mInitialized = false;
if (PauseReceiver.isRunning) {
PauseReceiver.mCountdown.cancel();
PauseReceiver.isRunning = false;
}
try {
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String id = context.getString(R.string.notification_main_channel_id);
notificationManager.deleteNotificationChannel(id);
} else {
notificationManager.cancel(LockService.NOTIFICATION_ID);
}
} catch (Exception e) {
e.printStackTrace();
}
lockWidgetProvider.setWidgetStop(context);
stopService(intent);
break;
}
} else { } else {
notificationManager.notify(NOTIFICATION_ID, notification); return LockService.START_REDELIVER_INTENT;
disabled = false;
} }
//------------------------------------------------------------------------------------------
return LockService.START_STICKY; return LockService.START_REDELIVER_INTENT;
} }
@Override @Override
@ -125,6 +191,11 @@ public class LockService extends JobIntentService {
@Override @Override
protected void onHandleWork(@NonNull Intent intent) { } protected void onHandleWork(@NonNull Intent intent) { }
@Override
public void onDestroy() {
super.onDestroy();
}
private void setSensorListener() { private void setSensorListener() {
activeListener = new SensorEventListener() { activeListener = new SensorEventListener() {
@Override @Override
@ -132,6 +203,11 @@ public class LockService extends JobIntentService {
if(LockService.disabled) if(LockService.disabled)
return; return;
//check prefs here so options can be changed without service restart
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
isHaptic = prefs.getBoolean("HAPTIC_FEEDBACK", false);
sensorCalc(event); sensorCalc(event);
} }
@ -156,6 +232,7 @@ public class LockService extends JobIntentService {
float deltaY = Math.abs(mLastY - y); float deltaY = Math.abs(mLastY - y);
float deltaZ = Math.abs(mLastZ - z); float deltaZ = Math.abs(mLastZ - z);
float NOISE = (float) 2.0;
if (deltaX < NOISE) deltaX = (float) 0.0; if (deltaX < NOISE) deltaX = (float) 0.0;
if (deltaY < NOISE) deltaY = (float) 0.0; if (deltaY < NOISE) deltaY = (float) 0.0;
if (deltaZ < NOISE) deltaZ = (float) 0.0; if (deltaZ < NOISE) deltaZ = (float) 0.0;
@ -164,18 +241,56 @@ public class LockService extends JobIntentService {
mLastY = y; mLastY = y;
mLastZ = z; mLastZ = z;
float total = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ); float total = (float) Math.sqrt((deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ));
if (total > SENSITIVITY) { if (total > SENSITIVITY) {
try { try {
mDPM.lockNow(); if (isActiveAdmin()) {
if(!isHaptic) {
mDPM.lockNow();
} else { //if haptic
if(!isHit) { //run if not triggered yet
isHit = true;
mDPM.lockNow();
vibrateItBaby();
//stop multiple haptic triggers in a row
new CountDownTimer(1000, 1000) {
public void onTick(long millisUntilFinished) {
isHit = true;
}
public void onFinish() {
isHit = false;
}
}.start();
}
}
} else {
Toast.makeText(context, "Device admin not enabled", Toast.LENGTH_LONG).show();
}
} catch (Exception e) { } catch (Exception e) {
Toast.makeText(context, "Error locking, does app have device admin permissions?", Toast.LENGTH_SHORT).show(); Toast.makeText(context, "Unknown locking error", Toast.LENGTH_SHORT).show();
} }
} }
} }
} }
private void vibrateItBaby() {
int vibrateTime = 100;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
((Vibrator) Objects.requireNonNull(getSystemService(VIBRATOR_SERVICE))).vibrate(VibrationEffect.createOneShot(vibrateTime, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(vibrateTime);
}
}
private boolean isActiveAdmin() {
return mDPM.isAdminActive(mDeviceAdmin);
}
private void setNotification() { private void setNotification() {
//notification //notification
pendingIntent = PendingIntent.getActivity(context, 0, pendingIntent = PendingIntent.getActivity(context, 0,
@ -206,6 +321,7 @@ public class LockService extends JobIntentService {
.setTicker(getString(R.string.app_name) + " is running") .setTicker(getString(R.string.app_name) + " is running")
.addAction(android.R.drawable.ic_menu_close_clear_cancel, "STOP", pendingCloseIntent) .addAction(android.R.drawable.ic_menu_close_clear_cancel, "STOP", pendingCloseIntent)
.addAction(android.R.drawable.ic_menu_close_clear_cancel, "PAUSE", pendingPauseIntent) .addAction(android.R.drawable.ic_menu_close_clear_cancel, "PAUSE", pendingPauseIntent)
.setPriority(PRIORITY_LOW)
.setOngoing(true) .setOngoing(true)
.build(); .build();
@ -221,6 +337,7 @@ public class LockService extends JobIntentService {
.setTicker(getString(R.string.app_name) + " is running") .setTicker(getString(R.string.app_name) + " is running")
.addAction(android.R.drawable.ic_menu_close_clear_cancel, "STOP", pendingCloseIntent) .addAction(android.R.drawable.ic_menu_close_clear_cancel, "STOP", pendingCloseIntent)
.addAction(android.R.drawable.ic_menu_close_clear_cancel, "PAUSE", pendingPauseIntent) .addAction(android.R.drawable.ic_menu_close_clear_cancel, "PAUSE", pendingPauseIntent)
.setPriority(PRIORITY_LOW)
.setOngoing(true) .setOngoing(true)
.build(); .build();
} }

View file

@ -1,6 +1,5 @@
package com.wesaphzt.privatelock.widget; package com.wesaphzt.privatelock.widget;
import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider; import android.appwidget.AppWidgetProvider;
@ -14,12 +13,6 @@ import android.widget.RemoteViews;
import com.wesaphzt.privatelock.service.LockService; import com.wesaphzt.privatelock.service.LockService;
import com.wesaphzt.privatelock.R; import com.wesaphzt.privatelock.R;
import com.wesaphzt.privatelock.receivers.PauseReceiver;
import static com.wesaphzt.privatelock.service.LockService.CHANNEL_ID;
import static com.wesaphzt.privatelock.service.LockService.activeListener;
import static com.wesaphzt.privatelock.service.LockService.disabled;
import static com.wesaphzt.privatelock.service.LockService.mSensorManager;
public class LockWidgetProvider extends AppWidgetProvider { public class LockWidgetProvider extends AppWidgetProvider {
@ -72,33 +65,14 @@ public class LockWidgetProvider extends AppWidgetProvider {
editor.putBoolean(context.getString(R.string.widget_prefs_service_id), false); editor.putBoolean(context.getString(R.string.widget_prefs_service_id), false);
editor.apply(); editor.apply();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); Intent stopIntent = new Intent(context, LockService.class);
stopIntent.setAction(LockService.ACTION_STOP_FOREGROUND_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager.deleteNotificationChannel(CHANNEL_ID); context.startForegroundService(stopIntent);
//if countdown timer is running (pause), cancel
if(PauseReceiver.isRunning) {
PauseReceiver.mCountdown.cancel(); PauseReceiver.isRunning = false;
disabled = true;
mSensorManager.unregisterListener(activeListener);
setWidgetStop(context);
} else {
disabled = true;
mSensorManager.unregisterListener(activeListener);
setWidgetStop(context);
}
} else { } else {
notificationManager.cancel(LockService.NOTIFICATION_ID); context.startService(stopIntent);
if(PauseReceiver.isRunning) {
PauseReceiver.mCountdown.cancel(); PauseReceiver.isRunning = false;
disabled = true;
mSensorManager.unregisterListener(activeListener);
setWidgetStop(context);
} else {
disabled = true;
mSensorManager.unregisterListener(activeListener);
setWidgetStop(context);
}
} }
//if service is not running //if service is not running
@ -106,15 +80,13 @@ public class LockWidgetProvider extends AppWidgetProvider {
editor.putBoolean(context.getString(R.string.widget_prefs_service_id), true); editor.putBoolean(context.getString(R.string.widget_prefs_service_id), true);
editor.commit(); editor.commit();
Intent i = new Intent(context, LockService.class); Intent startIntent = new Intent(context, LockService.class);
startIntent.setAction(LockService.ACTION_START_FOREGROUND_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
disabled = false; context.startForegroundService(startIntent);
context.startForegroundService(i);
setWidgetStart(context);
} else { } else {
disabled = false; context.startService(startIntent);
context.startService(i);
setWidgetStart(context);
} }
} }
} }

View file

@ -1,24 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector android:height="200dp" android:viewportHeight="79.375"
android:width="200dp" android:viewportWidth="79.375" android:width="200dp" xmlns:android="http://schemas.android.com/apk/res/android">
android:height="200dp" <path android:fillColor="#131313" android:pathData="M-0,0l79.375,0l0,79.375l-79.375,0z"/>
android:viewportWidth="300" <path android:fillColor="#6F6F6F" android:fillType="evenOdd" android:pathData="M39.4592,8.6879C30.4924,13.067 20.4094,16.6195 12.1658,16.6777C17.2289,47.9896 20.134,60.0895 39.4592,69.9947C58.7851,60.09 61.6902,47.9896 66.7528,16.6777C58.5092,16.6195 48.4262,13.067 39.4592,8.6879Z"/>
android:viewportHeight="300"> <path android:fillAlpha="0.44" android:fillColor="#FF000000"
<path android:fillType="evenOdd" android:pathData="M39.4592,8.6863L39.4592,39.3406L62.4726,39.3406C64.0157,33.1047 65.2957,25.6905 66.7533,16.6764C58.5099,16.6182 48.4269,13.0659 39.4599,8.6868ZM39.4592,39.3406L16.446,39.3406C20.2631,54.7669 25.6966,62.9399 39.4592,69.9931Z"/>
android:pathData="M150,150m-150,0a150,150 0,1 1,300 0a150,150 0,1 1,-300 0" <path android:fillColor="#DADADA" android:pathData="M39.9082,14.3248C34.5972,14.3248 30.2874,18.6351 30.2874,23.9461L30.2874,27.7945L28.3628,27.7945C26.2461,27.7945 24.5144,29.5264 24.5144,31.6431L24.5144,50.8855C24.5144,53.0021 26.2461,54.7338 28.3628,54.7338L39.9082,54.7338L39.9082,45.1128C37.7918,45.1128 36.0598,43.3808 36.0598,41.2642C36.0598,39.1477 37.7918,37.4158 39.9082,37.4158L39.9082,27.7945L33.9431,27.7945L33.9431,23.9461C33.9431,20.6558 36.6181,17.9811 39.9082,17.9811Z"/>
android:fillColor="#80e5ff"/> <path android:fillColor="#FFFFFF" android:pathData="M39.4697,14.3365C44.7805,14.3365 49.0908,18.6468 49.0908,23.9578L49.0908,27.8064L51.0151,27.8064C53.1318,27.8064 54.8635,29.5381 54.8635,31.6548L54.8635,50.8968C54.8635,53.0138 53.1318,54.7455 51.0151,54.7455L39.4697,54.7455L39.4697,45.1242C41.5864,45.1242 43.3181,43.3925 43.3181,41.2758C43.3181,39.1591 41.5864,37.4274 39.4697,37.4274L39.4697,27.8064L45.4348,27.8064L45.4348,23.9578C45.4348,20.6671 42.7601,17.9927 39.4697,17.9927Z"/>
<path <path android:fillColor="#131313" android:pathData="M39.6663,41.2731m-3.8293,0a3.8293,3.8293 0,1 1,7.6586 0a3.8293,3.8293 0,1 1,-7.6586 0"/>
android:pathData="M150.56,0.01V300c82.587,-0.3 149.44,-67.335 149.44,-149.99 0,-82.657 -66.858,-149.69 -149.44,-149.99z"
android:fillColor="#aaeeff"/>
<path
android:pathData="m281.15,222.37c-33.736,-8.65 -75.566,-13.771 -120.88,-13.771 -54.476,0 -103.92,7.404 -140.32,19.445 26.154,43.955 74.127,73.412 128.99,73.412 57.19,0 106.9,-32.009 132.2,-79.086z"
android:fillColor="#57bd84"/>
<path
android:pathData="m160.28,208.6c-3.615,0 -7.205,0.035 -10.774,0.1v92.748c1.396,-0.005 2.786,-0.03 4.173,-0.073 0.654,-0.02 1.305,-0.052 1.957,-0.081 0.92,-0.04 1.84,-0.088 2.756,-0.145 0.674,-0.042 1.348,-0.084 2.018,-0.135 1.092,-0.082 2.178,-0.18 3.26,-0.285 0.789,-0.077 1.576,-0.16 2.361,-0.25 1.053,-0.119 2.104,-0.245 3.148,-0.387 0.658,-0.089 1.314,-0.185 1.971,-0.282 0.906,-0.134 1.809,-0.278 2.709,-0.429 0.613,-0.103 1.227,-0.2 1.838,-0.311 1.369,-0.246 2.732,-0.51 4.09,-0.793 0.568,-0.119 1.131,-0.25 1.697,-0.375 0.922,-0.204 1.842,-0.414 2.756,-0.635 0.621,-0.149 1.24,-0.302 1.857,-0.459 0.98,-0.25 1.955,-0.513 2.93,-0.781 0.498,-0.138 0.998,-0.269 1.494,-0.412 1.313,-0.378 2.617,-0.776 3.914,-1.189 0.564,-0.179 1.123,-0.366 1.684,-0.552 0.902,-0.299 1.801,-0.605 2.695,-0.921 0.541,-0.19 1.084,-0.379 1.621,-0.576 1.316,-0.48 2.627,-0.975 3.924,-1.491 0.387,-0.153 0.768,-0.317 1.154,-0.475 1.004,-0.409 2.006,-0.828 2.998,-1.259 0.512,-0.221 1.021,-0.446 1.529,-0.673 0.961,-0.43 1.916,-0.869 2.867,-1.318 0.4,-0.188 0.803,-0.372 1.199,-0.563 1.283,-0.62 2.555,-1.259 3.818,-1.914 0.406,-0.21 0.807,-0.428 1.211,-0.643 0.943,-0.501 1.883,-1.011 2.814,-1.531 0.426,-0.237 0.852,-0.475 1.273,-0.716 1.205,-0.688 2.402,-1.388 3.586,-2.107 0.111,-0.068 0.225,-0.136 0.336,-0.204 1.219,-0.747 2.424,-1.516 3.621,-2.296 0.365,-0.237 0.729,-0.479 1.092,-0.721 0.963,-0.641 1.92,-1.292 2.867,-1.954 0.295,-0.207 0.594,-0.41 0.889,-0.618 1.213,-0.861 2.414,-1.737 3.602,-2.634 0.199,-0.15 0.396,-0.307 0.596,-0.458 1.012,-0.771 2.012,-1.555 3.002,-2.352 0.295,-0.236 0.59,-0.474 0.883,-0.713 1.088,-0.888 2.166,-1.787 3.229,-2.705 0.07,-0.061 0.143,-0.118 0.211,-0.179 1.16,-1.006 2.303,-2.032 3.434,-3.073 0.211,-0.194 0.418,-0.393 0.629,-0.588 0.949,-0.886 1.889,-1.783 2.814,-2.693 0.195,-0.19 0.391,-0.381 0.586,-0.572 2.191,-2.176 4.316,-4.419 6.371,-6.726 0.178,-0.199 0.354,-0.4 0.531,-0.601 0.963,-1.092 1.912,-2.195 2.842,-3.315 0.051,-0.061 0.104,-0.121 0.154,-0.182 1.021,-1.232 2.023,-2.483 3.006,-3.749 0.074,-0.095 0.146,-0.191 0.219,-0.287 0.889,-1.15 1.76,-2.314 2.615,-3.491 0.123,-0.17 0.248,-0.339 0.371,-0.51 1.848,-2.563 3.615,-5.187 5.303,-7.867 0.094,-0.15 0.186,-0.301 0.279,-0.451 0.793,-1.27 1.568,-2.551 2.322,-3.845 0.047,-0.08 0.096,-0.159 0.143,-0.24 0.822,-1.416 1.623,-2.847 2.4,-4.292 -33.736,-8.65 -75.566,-13.771 -120.88,-13.771z"
android:fillColor="#67c18c"/>
<path
android:pathData="M151.859,35.355C124.259,35.355 101.859,57.755 101.859,85.355L101.859,105.355L91.859,105.355C80.859,105.355 71.859,114.355 71.859,125.355L71.859,225.355C71.859,236.355 80.859,245.355 91.859,245.355L151.859,245.355L151.859,195.355C140.859,195.355 131.859,186.355 131.859,175.355C131.859,164.355 140.859,155.355 151.859,155.355L151.859,105.355L120.859,105.355L120.859,85.355C120.859,68.255 134.759,54.355 151.859,54.355Z"
android:fillColor="#0066ff"/>
<path
android:pathData="M150.58,35.415C178.18,35.415 200.58,57.815 200.58,85.415L200.58,105.415L210.58,105.415C221.58,105.415 230.58,114.415 230.58,125.415L230.58,225.415C230.58,236.415 221.58,245.415 210.58,245.415L150.58,245.415L150.58,195.415C161.58,195.415 170.58,186.415 170.58,175.415C170.58,164.415 161.58,155.415 150.58,155.415L150.58,105.415L181.58,105.415L181.58,85.415C181.58,68.315 167.68,54.415 150.58,54.415Z"
android:fillColor="#2A7FFF"/>
</vector> </vector>

View file

@ -141,23 +141,98 @@
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:id="@+id/rlStatTitles"
android:layout_height="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_margin"
android:layout_marginTop="@dimen/activity_margin_small"
android:layout_marginEnd="@dimen/activity_margin">
<TextView
android:id="@+id/tvLastBreachValueTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/stats_last_breach_value_title"
android:textSize="@dimen/_10sdp" />
<TextView
android:id="@+id/tvAvgBreachValueTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tvLastBreachValueTitle"
android:text="@string/stats_avg_breach_value_title"
android:textSize="@dimen/_10sdp" />
<TextView
android:id="@+id/tvHighestBreachValueTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tvAvgBreachValueTitle"
android:text="@string/stats_highest_breach_value_title"
android:textSize="@dimen/_10sdp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/rlStatValues"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_margin"
android:layout_marginTop="@dimen/activity_margin_small"
android:layout_marginEnd="@dimen/activity_margin"
android:layout_toEndOf="@id/rlStatTitles">
<TextView
android:id="@+id/tvLastBreachValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/stats_zero"
android:textSize="@dimen/_10sdp" />
<TextView
android:id="@+id/tvAvgBreachValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tvLastBreachValue"
android:text="@string/stats_zero"
android:textSize="@dimen/_10sdp" />
<TextView
android:id="@+id/tvHighestBreachValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tvAvgBreachValue"
android:text="@string/stats_zero"
android:textSize="@dimen/_10sdp" />
</RelativeLayout>
</RelativeLayout>
<RelativeLayout
android:id="@+id/rlCircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_margin_large" android:layout_marginTop="@dimen/activity_margin_large"
android:layout_gravity="center_horizontal"> android:layout_gravity="center_horizontal">
<com.wesaphzt.privatelock.animation.Circle <com.wesaphzt.privatelock.animation.Circle
android:id="@+id/circle_bg" android:id="@+id/circle_bg"
android:layout_width="240dp" android:layout_width="wrap_content"
android:layout_height="240dp" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" /> android:layout_centerHorizontal="true"
android:gravity="center_horizontal" />
<com.wesaphzt.privatelock.animation.Circle <com.wesaphzt.privatelock.animation.Circle
android:id="@+id/circle" android:id="@+id/circle"
android:layout_width="240dp" android:layout_width="wrap_content"
android:layout_height="240dp" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:layout_centerInParent="true"
android:gravity="center_horizontal" /> android:gravity="center_horizontal" />
</RelativeLayout> </RelativeLayout>

View file

@ -15,13 +15,20 @@
<string name="main_lock_sensitivity_title_arrow"></string> <string name="main_lock_sensitivity_title_arrow"></string>
<string name="sensitivity_value">Value: %1$s</string> <string name="sensitivity_value">Value: %1$s</string>
<!--stats-->
<string name="stats_last_breach_value_title">Last Breach Value:</string>
<string name="stats_avg_breach_value_title">Avg. Breach Value:</string>
<string name="stats_highest_breach_value_title">Highest Breach Value:</string>
<string name="stats_zero">0</string>
<!--intro--> <!--intro-->
<string name="slider_page_one_title">Private Lock</string> <string name="slider_page_one_title">@string/app_name</string>
<string name="slider_page_one_desc">Private Lock, the perfect companion to help protect your phone privacy and security.</string> <string name="slider_page_one_desc">Private Lock, the perfect companion to help protect your phone privacy and security.</string>
<string name="slider_page_two_title">Protect against theft</string> <string name="slider_page_two_title">Protect Against Theft</string>
<string name="slider_page_two_desc">If someone takes your phone while you\'re using it, your phone is unlocked and all your private data is up for grabs.</string> <string name="slider_page_two_desc">If someone takes your phone while you\'re using it, your phone is unlocked and all your private data is up for grabs.</string>
<string name="slider_page_three_title">Always running</string> <string name="slider_page_three_title">Always Running</string>
<string name="slider_page_three_desc">Should something happen, your phone will be quickly locked, dependent on the sensitivity you\'ve set.</string> <string name="slider_page_three_desc">Should something happen, your phone will be quickly locked, dependent on the sensitivity you\'ve set.
\n\nDon\'t forget to disable battery optimization!</string>
<!--actionbar--> <!--actionbar-->
<string name="action_start">Start</string> <string name="action_start">Start</string>
@ -61,6 +68,9 @@
<string name="about_bug_report_image_desc">Bug report image</string> <string name="about_bug_report_image_desc">Bug report image</string>
<!--message-->
<string name="settings_restart_service_toast">If service is running, restart for setting to take effect.</string>
<!--donate--> <!--donate-->
<string name="donate_bitcoin_image_desc">Bitcoin image</string> <string name="donate_bitcoin_image_desc">Bitcoin image</string>
<string name="donate_litecoin_image_desc">Litecoin image</string> <string name="donate_litecoin_image_desc">Litecoin image</string>

View file

@ -2,20 +2,31 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory <PreferenceCategory
android:title="Lock Service"> android:title="Lock Service">
<CheckBoxPreference
android:defaultValue="false"
android:key="START_ON_BOOT"
android:title="System start" />
<CheckBoxPreference
android:defaultValue="false"
android:key="HAPTIC_FEEDBACK"
android:title="Haptic feedback"
android:summary="Enable haptic feedback (vibration) on lock." />
<CheckBoxPreference
android:defaultValue="false"
android:key="RUN_CONSTANT"
android:title="Run service when locked"
android:summary="Run service all the time, even when the screen is off, to be able to force PIN entry at any time."/>
<ListPreference <ListPreference
android:defaultValue="1" android:defaultValue="1"
android:entries="@array/array_pause_minutes" android:entries="@array/array_pause_minutes"
android:entryValues="@array/array_pause_minutes_vals" android:entryValues="@array/array_pause_minutes_vals"
android:key="PAUSE_TIME" android:key="PAUSE_TIME"
android:summary="%s" android:summary="%s"
android:title="Pause time" /> android:title="Pause length" />
</PreferenceCategory>
<PreferenceCategory
android:title="Application">
<CheckBoxPreference
android:defaultValue="false"
android:key="START_ON_BOOT"
android:title="System start" />
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View file

@ -7,7 +7,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.4.1' classpath 'com.android.tools.build:gradle:3.5.0'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files

View file

@ -1 +1 @@
Initial release. * Initial release.

View file

@ -0,0 +1,5 @@
* Animation scaling issues fixed
* Stop service correctly to fix memory leak & reduce code
* Notification priority changed to low for Nougat and lower
* Option added to run service when screen is off to be able to force PIN entry
* Gradle & library updates

View file

@ -0,0 +1,4 @@
* Fix for background service < Android 8.0/Oreo
* Add option for haptic feedback (vibration) on lock trigger
* Reworked animation logic
* Fix 'License' and 'Bug report' links on about page

View file

@ -14,4 +14,9 @@ org.gradle.jvmargs=-Xmx1536m
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true # org.gradle.parallel=true
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
distributionSha256Sum=53b71812f18cdb2777e9f1b2a0f2038683907c90bdc406bc64d8b400e1fb2c3b

View file

@ -1,6 +1,6 @@
#Sun May 26 22:24:42 BST 2019 #Fri Sep 06 22:42:44 BST 2019
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip