mirror of
https://github.com/wesaphzt/privatelock.git
synced 2025-06-30 04:49:51 +00:00
Compare commits
24 commits
Author | SHA1 | Date | |
---|---|---|---|
|
0cfce130fd | ||
|
1b0d587a8d | ||
|
995403a129 | ||
|
0aa22e93e3 | ||
|
36bb398fd4 | ||
|
6b560beac8 | ||
|
248a8eeb0b | ||
|
000eb550a2 | ||
|
e51a510645 | ||
|
18018360d3 | ||
|
1cc68f0fff | ||
|
063beba464 | ||
|
10db550988 | ||
|
1b2a5139b9 | ||
|
813b948f19 | ||
|
53828ddc3f | ||
|
4d67f4dd47 | ||
|
0a0079db37 | ||
|
87e349d02a | ||
|
cd8226cddc | ||
|
c2b6299102 | ||
|
480907063b | ||
|
785f8d3eac | ||
|
4fe08078e0 |
24 changed files with 631 additions and 237 deletions
116
.idea/codeStyles/Project.xml
generated
Normal file
116
.idea/codeStyles/Project.xml
generated
Normal 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
21
CHANGELOG.md
Normal 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
|
|
@ -1,10 +1,9 @@
|
|||
# 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>
|
||||
[](LICENSE)
|
||||
[](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/)
|
||||
|
||||
[description]
|
||||
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.
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
compileSdkVersion 29
|
||||
defaultConfig {
|
||||
applicationId "com.wesaphzt.privatelock"
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
targetSdkVersion 29
|
||||
versionCode 3
|
||||
versionName "1.2"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
|
@ -22,10 +22,10 @@ dependencies {
|
|||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
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 'androidx.appcompat:appcompat:1.0.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<!--pre-oreo-->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
|
|
|
@ -22,10 +22,11 @@ import androidx.fragment.app.FragmentTransaction;
|
|||
|
||||
import android.os.CountDownTimer;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
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.FragmentSettings;
|
||||
import com.wesaphzt.privatelock.receivers.DeviceAdminReceiver;
|
||||
import com.wesaphzt.privatelock.receivers.PauseReceiver;
|
||||
import com.wesaphzt.privatelock.service.LockService;
|
||||
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.DEFAULT_SENSITIVITY;
|
||||
import static com.wesaphzt.privatelock.service.LockService.activeListener;
|
||||
|
@ -54,7 +56,6 @@ public class MainActivity extends AppCompatActivity {
|
|||
private boolean mInitialized;
|
||||
private static SensorManager mSensorManager;
|
||||
private Sensor mAccelerometer;
|
||||
private final float NOISE = (float) 2.0;
|
||||
|
||||
private SensorEventListener mActiveListener;
|
||||
|
||||
|
@ -70,22 +71,26 @@ public class MainActivity extends AppCompatActivity {
|
|||
public static final String PREFS_THRESHOLD = "THRESHOLD";
|
||||
|
||||
private CountDownTimer cdTimer;
|
||||
private final int cdTimerLength = 2000;
|
||||
private final int cdTimerLength = 1500;
|
||||
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_bg;
|
||||
//circle bg color
|
||||
private int circleBgR = 240; private int circleBgG = 240; private int circleBgB = 240;
|
||||
//circle color
|
||||
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;
|
||||
|
||||
//first run
|
||||
final private String PREF_VERSION_CODE_KEY = "VERSION_CODE";
|
||||
final private int DOESNT_EXIST = -1;
|
||||
CircleAngleAnimation animation;
|
||||
|
||||
@Override
|
||||
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_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);
|
||||
//set background circle
|
||||
CircleAngleAnimation animation = new CircleAngleAnimation(circle_bg, 360);
|
||||
//initial animation
|
||||
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);
|
||||
|
||||
//stats
|
||||
tvLastBreachValue = findViewById(R.id.tvLastBreachValue);
|
||||
tvAvgBreachValue = findViewById(R.id.tvAvgBreachValue);
|
||||
tvHighestBreachValue = findViewById(R.id.tvHighestBreachValue);
|
||||
|
||||
//shared prefs
|
||||
try {
|
||||
mSensitivity = prefs.getInt(PREFS_THRESHOLD, DEFAULT_SENSITIVITY);
|
||||
|
@ -148,12 +183,19 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
//timer when lock hit
|
||||
cdTimer = new CountDownTimer(cdTimerLength, 1000) {
|
||||
|
||||
public void onTick(long millisUntilFinished) {
|
||||
isRunning = true;
|
||||
isHit = true;
|
||||
}
|
||||
public void onFinish() {
|
||||
isRunning = false;
|
||||
isHit = false;
|
||||
circle.setColor(circleDefaultR, circleDefaultG, circleDefaultB);
|
||||
//reset stat variables
|
||||
triggerCount = 0;
|
||||
avgBreachValueTotal = 0;
|
||||
highestBreach = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -222,6 +264,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
//launch service if permission granted
|
||||
if (requestCode == REQUEST_CODE_ENABLE_ADMIN) {
|
||||
if(resultCode == Activity.RESULT_OK) {
|
||||
|
@ -270,27 +313,12 @@ public class MainActivity extends AppCompatActivity {
|
|||
private void startServicePrep() {
|
||||
//stop this listener
|
||||
mSensorManager.unregisterListener(mActiveListener);
|
||||
Intent intent = new Intent(context, LockService.class);
|
||||
|
||||
try {
|
||||
//stop any already running service
|
||||
LockService.mSensorManager.unregisterListener(LockService.activeListener);
|
||||
startLockService(intent);
|
||||
LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
|
||||
lockWidgetProvider.setWidgetStart(context);
|
||||
//start service intent
|
||||
Intent startIntent = new Intent(context, LockService.class);
|
||||
startIntent.setAction(LockService.ACTION_START_FOREGROUND_SERVICE);
|
||||
|
||||
//cancel any pause timer that might be running
|
||||
try {
|
||||
PauseReceiver.mCountdown.cancel();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
startLockService(intent);
|
||||
LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
|
||||
lockWidgetProvider.setWidgetStart(context);
|
||||
}
|
||||
startLockService(startIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -376,7 +404,10 @@ public class MainActivity extends AppCompatActivity {
|
|||
//get current version code
|
||||
int currentVersionCode = BuildConfig.VERSION_CODE;
|
||||
//get saved version code
|
||||
int DOESNT_EXIST = -1;
|
||||
int savedVersionCode = DOESNT_EXIST;
|
||||
//first run
|
||||
String PREF_VERSION_CODE_KEY = "VERSION_CODE";
|
||||
try {
|
||||
savedVersionCode = this.prefs.getInt(PREF_VERSION_CODE_KEY, DOESNT_EXIST);
|
||||
} catch (Exception e) {
|
||||
|
@ -411,6 +442,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
float deltaY = Math.abs(mLastY - y);
|
||||
float deltaZ = Math.abs(mLastZ - z);
|
||||
|
||||
float NOISE = (float) 2.0;
|
||||
if (deltaX < NOISE) deltaX = (float) 0.0;
|
||||
if (deltaY < NOISE) deltaY = (float) 0.0;
|
||||
if (deltaZ < NOISE) deltaZ = (float) 0.0;
|
||||
|
@ -419,35 +451,59 @@ public class MainActivity extends AppCompatActivity {
|
|||
mLastY = y;
|
||||
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) {
|
||||
//do nothing if timer currently running
|
||||
if (total >= mSensitivity) {
|
||||
//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)
|
||||
return;
|
||||
|
||||
if(isHit)
|
||||
return;
|
||||
|
||||
calculatedAngleInt = Math.round((total / mSensitivity) * 360);
|
||||
|
||||
CircleAngleAnimation animation = new CircleAngleAnimation(circle, calculatedAngleInt);
|
||||
animation = new CircleAngleAnimation(circle, calculatedAngleInt);
|
||||
animation.setDuration(animationDuration);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,15 +13,14 @@ public class Circle extends View {
|
|||
private static final int START_ANGLE_POINT = 90;
|
||||
|
||||
private final Paint paint;
|
||||
private final RectF rect;
|
||||
private RectF rect;
|
||||
|
||||
private float angle;
|
||||
private final int strokeWidth = 10;
|
||||
|
||||
public Circle(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
final int strokeWidth = 10;
|
||||
|
||||
paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
|
@ -29,8 +28,8 @@ public class Circle extends View {
|
|||
//circle color (currently set upon instance)
|
||||
//paint.setColor(Color.BLUE);
|
||||
|
||||
//size
|
||||
rect = new RectF(strokeWidth, strokeWidth, 600 + strokeWidth, 600 + strokeWidth);
|
||||
//size (currently set upon instance)
|
||||
//rect = new RectF(strokeWidth, strokeWidth, 230 + strokeWidth, 230 + strokeWidth);
|
||||
|
||||
//initial angle (optional)
|
||||
angle = 0;
|
||||
|
@ -53,4 +52,12 @@ public class Circle extends View {
|
|||
public void setAngle(float 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;
|
||||
}
|
||||
}
|
|
@ -21,9 +21,8 @@ import com.wesaphzt.privatelock.R;
|
|||
public class FragmentAbout extends Fragment {
|
||||
|
||||
private static String GITHUB_URI;
|
||||
private static final String LICENSE_URI = GITHUB_URI + "/blob/master/LICENSE.txt";
|
||||
private static final String BUG_REPORT_URI = GITHUB_URI + "/issues";
|
||||
|
||||
private static String LICENSE_URI;
|
||||
private static String BUG_REPORT_URI;
|
||||
private static String AUTHOR_GITHUB;
|
||||
|
||||
@Nullable
|
||||
|
@ -32,6 +31,8 @@ public class FragmentAbout extends Fragment {
|
|||
View v = inflater.inflate(R.layout.fragment_about, container, false);
|
||||
|
||||
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);
|
||||
|
||||
String versionName = "";
|
||||
|
|
|
@ -7,7 +7,9 @@ import androidx.annotation.Nullable;
|
|||
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.preference.CheckBoxPreference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
|
@ -15,17 +17,26 @@ import com.wesaphzt.privatelock.R;
|
|||
|
||||
public class FragmentSettings extends PreferenceFragmentCompat {
|
||||
|
||||
private SharedPreferences prefs;
|
||||
private Context context;
|
||||
|
||||
private CheckBoxPreference cbRunConstant;
|
||||
|
||||
private SharedPreferences sharedPreferences;
|
||||
private SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener;
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
Context context = getContext();
|
||||
context = getContext();
|
||||
|
||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
//this static call will reset default values only on the first read
|
||||
PreferenceManager.setDefaultValues(context, R.xml.preferences, false);
|
||||
|
||||
cbRunConstant = (CheckBoxPreference) findPreference("RUN_CONSTANT");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -33,6 +44,24 @@ public class FragmentSettings extends PreferenceFragmentCompat {
|
|||
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
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
@ -41,6 +70,16 @@ public class FragmentSettings extends PreferenceFragmentCompat {
|
|||
|
||||
//bg color
|
||||
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
|
||||
|
|
|
@ -8,7 +8,6 @@ import android.os.Build;
|
|||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.wesaphzt.privatelock.service.LockService;
|
||||
import com.wesaphzt.privatelock.widget.LockWidgetProvider;
|
||||
|
||||
public class BootReceiver extends BroadcastReceiver {
|
||||
|
||||
|
@ -16,19 +15,16 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
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)) {
|
||||
Intent i = new Intent(context, LockService.class);
|
||||
Intent startIntent = new Intent(context, LockService.class);
|
||||
startIntent.setAction(LockService.ACTION_START_FOREGROUND_SERVICE);
|
||||
|
||||
//check android api
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(i);
|
||||
LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
|
||||
lockWidgetProvider.setWidgetStart(context);
|
||||
context.startForegroundService(startIntent);
|
||||
} else {
|
||||
context.startService(i);
|
||||
LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
|
||||
lockWidgetProvider.setWidgetStart(context);
|
||||
context.startService(startIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,11 @@
|
|||
package com.wesaphzt.privatelock.receivers;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
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 {
|
||||
|
||||
|
@ -23,37 +14,13 @@ public class NotificationReceiver extends BroadcastReceiver {
|
|||
String action = intent.getStringExtra("lock_service");
|
||||
|
||||
if (action.equals("lock_service_notification")) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
|
||||
Intent stopIntent = new Intent(context, LockService.class);
|
||||
stopIntent.setAction(LockService.ACTION_STOP_FOREGROUND_SERVICE);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
String id = context.getString(R.string.notification_main_channel_id);
|
||||
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);
|
||||
}
|
||||
|
||||
context.startForegroundService(stopIntent);
|
||||
} else {
|
||||
notificationManager.cancel(LockService.NOTIFICATION_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);
|
||||
}
|
||||
context.startService(stopIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.wesaphzt.privatelock.receivers;
|
|||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
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.mInitialized;
|
||||
|
@ -11,6 +13,8 @@ public class PresenceReceiver extends BroadcastReceiver {
|
|||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
|
||||
//prevent lock animation artifacts
|
||||
mInitialized = false;
|
||||
|
@ -18,7 +22,9 @@ public class PresenceReceiver extends BroadcastReceiver {
|
|||
disabled = false;
|
||||
|
||||
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
|
||||
disabled = true;
|
||||
if(! prefs.getBoolean("RUN_CONSTANT", false)) {
|
||||
disabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,12 +15,15 @@ import android.hardware.SensorEvent;
|
|||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Build;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.JobIntentService;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.preference.PreferenceManager;
|
||||
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.PauseReceiver;
|
||||
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;
|
||||
|
||||
public class LockService extends JobIntentService {
|
||||
|
@ -40,7 +47,6 @@ public class LockService extends JobIntentService {
|
|||
private float mLastX, mLastY, mLastZ;
|
||||
public static boolean mInitialized;
|
||||
public static SensorManager mSensorManager;
|
||||
private final float NOISE = (float) 2.0;
|
||||
public static Sensor mAccelerometer;
|
||||
|
||||
public static SensorEventListener activeListener;
|
||||
|
@ -66,55 +72,115 @@ public class LockService extends JobIntentService {
|
|||
public static final int DEFAULT_SENSITIVITY = 10;
|
||||
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
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
context = getApplicationContext();
|
||||
CHANNEL_ID = getString(R.string.notification_main_channel_id);
|
||||
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);
|
||||
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||
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();
|
||||
LockWidgetProvider lockWidgetProvider = new LockWidgetProvider();
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
assert action != null;
|
||||
switch (action) {
|
||||
case ACTION_START_FOREGROUND_SERVICE:
|
||||
presenceReceiver = new PresenceReceiver();
|
||||
|
||||
//dpm
|
||||
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
mDeviceAdmin = new ComponentName(this, DeviceAdminReceiver.class);
|
||||
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_USER_PRESENT);
|
||||
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||
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
|
||||
mInitialized = false;
|
||||
//dpm
|
||||
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
mDeviceAdmin = new ComponentName(this, DeviceAdminReceiver.class);
|
||||
|
||||
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
|
||||
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
//prevent lock animation artifacts
|
||||
mInitialized = false;
|
||||
|
||||
setSensorListener();
|
||||
mSensorManager.registerListener(activeListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
|
||||
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
|
||||
setNotification();
|
||||
//------------------------------------------------------------------------------------------
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
//create foreground service
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
disabled = false;
|
||||
setSensorListener();
|
||||
mSensorManager.registerListener(activeListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
|
||||
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 {
|
||||
notificationManager.notify(NOTIFICATION_ID, notification);
|
||||
disabled = false;
|
||||
return LockService.START_REDELIVER_INTENT;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
return LockService.START_STICKY;
|
||||
return LockService.START_REDELIVER_INTENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -125,6 +191,11 @@ public class LockService extends JobIntentService {
|
|||
@Override
|
||||
protected void onHandleWork(@NonNull Intent intent) { }
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void setSensorListener() {
|
||||
activeListener = new SensorEventListener() {
|
||||
@Override
|
||||
|
@ -132,6 +203,11 @@ public class LockService extends JobIntentService {
|
|||
if(LockService.disabled)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -156,6 +232,7 @@ public class LockService extends JobIntentService {
|
|||
float deltaY = Math.abs(mLastY - y);
|
||||
float deltaZ = Math.abs(mLastZ - z);
|
||||
|
||||
float NOISE = (float) 2.0;
|
||||
if (deltaX < NOISE) deltaX = (float) 0.0;
|
||||
if (deltaY < NOISE) deltaY = (float) 0.0;
|
||||
if (deltaZ < NOISE) deltaZ = (float) 0.0;
|
||||
|
@ -164,18 +241,56 @@ public class LockService extends JobIntentService {
|
|||
mLastY = y;
|
||||
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) {
|
||||
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) {
|
||||
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() {
|
||||
//notification
|
||||
pendingIntent = PendingIntent.getActivity(context, 0,
|
||||
|
@ -206,6 +321,7 @@ public class LockService extends JobIntentService {
|
|||
.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, "PAUSE", pendingPauseIntent)
|
||||
.setPriority(PRIORITY_LOW)
|
||||
.setOngoing(true)
|
||||
.build();
|
||||
|
||||
|
@ -221,6 +337,7 @@ public class LockService extends JobIntentService {
|
|||
.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, "PAUSE", pendingPauseIntent)
|
||||
.setPriority(PRIORITY_LOW)
|
||||
.setOngoing(true)
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.wesaphzt.privatelock.widget;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
|
@ -14,12 +13,6 @@ import android.widget.RemoteViews;
|
|||
|
||||
import com.wesaphzt.privatelock.service.LockService;
|
||||
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 {
|
||||
|
||||
|
@ -72,33 +65,14 @@ public class LockWidgetProvider extends AppWidgetProvider {
|
|||
editor.putBoolean(context.getString(R.string.widget_prefs_service_id), false);
|
||||
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) {
|
||||
notificationManager.deleteNotificationChannel(CHANNEL_ID);
|
||||
//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);
|
||||
}
|
||||
context.startForegroundService(stopIntent);
|
||||
|
||||
} else {
|
||||
notificationManager.cancel(LockService.NOTIFICATION_ID);
|
||||
if(PauseReceiver.isRunning) {
|
||||
PauseReceiver.mCountdown.cancel(); PauseReceiver.isRunning = false;
|
||||
disabled = true;
|
||||
mSensorManager.unregisterListener(activeListener);
|
||||
setWidgetStop(context);
|
||||
} else {
|
||||
disabled = true;
|
||||
mSensorManager.unregisterListener(activeListener);
|
||||
setWidgetStop(context);
|
||||
}
|
||||
context.startService(stopIntent);
|
||||
}
|
||||
|
||||
//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.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) {
|
||||
disabled = false;
|
||||
context.startForegroundService(i);
|
||||
setWidgetStart(context);
|
||||
context.startForegroundService(startIntent);
|
||||
} else {
|
||||
disabled = false;
|
||||
context.startService(i);
|
||||
setWidgetStart(context);
|
||||
context.startService(startIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="200dp"
|
||||
android:height="200dp"
|
||||
android:viewportWidth="300"
|
||||
android:viewportHeight="300">
|
||||
<path
|
||||
android:pathData="M150,150m-150,0a150,150 0,1 1,300 0a150,150 0,1 1,-300 0"
|
||||
android:fillColor="#80e5ff"/>
|
||||
<path
|
||||
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 android:height="200dp" android:viewportHeight="79.375"
|
||||
android:viewportWidth="79.375" android:width="200dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#131313" android:pathData="M-0,0l79.375,0l0,79.375l-79.375,0z"/>
|
||||
<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"/>
|
||||
<path android:fillAlpha="0.44" android:fillColor="#FF000000"
|
||||
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"/>
|
||||
<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"/>
|
||||
<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 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"/>
|
||||
</vector>
|
||||
|
|
|
@ -141,23 +141,98 @@
|
|||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/rlStatTitles"
|
||||
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_gravity="center_horizontal">
|
||||
|
||||
<com.wesaphzt.privatelock.animation.Circle
|
||||
android:id="@+id/circle_bg"
|
||||
android:layout_width="240dp"
|
||||
android:layout_height="240dp"
|
||||
android:layout_centerHorizontal="true" />
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:gravity="center_horizontal" />
|
||||
|
||||
<com.wesaphzt.privatelock.animation.Circle
|
||||
android:id="@+id/circle"
|
||||
android:layout_width="240dp"
|
||||
android:layout_height="240dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center_horizontal" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -15,13 +15,20 @@
|
|||
<string name="main_lock_sensitivity_title_arrow">→</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-->
|
||||
<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_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_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_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.
|
||||
\n\nDon\'t forget to disable battery optimization!</string>
|
||||
|
||||
<!--actionbar-->
|
||||
<string name="action_start">Start</string>
|
||||
|
@ -61,6 +68,9 @@
|
|||
|
||||
<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-->
|
||||
<string name="donate_bitcoin_image_desc">Bitcoin image</string>
|
||||
<string name="donate_litecoin_image_desc">Litecoin image</string>
|
||||
|
|
|
@ -2,20 +2,31 @@
|
|||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceCategory
|
||||
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
|
||||
android:defaultValue="1"
|
||||
android:entries="@array/array_pause_minutes"
|
||||
android:entryValues="@array/array_pause_minutes_vals"
|
||||
android:key="PAUSE_TIME"
|
||||
android:summary="%s"
|
||||
android:title="Pause time" />
|
||||
</PreferenceCategory>
|
||||
android:title="Pause length" />
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="Application">
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="START_ON_BOOT"
|
||||
android:title="System start" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
|
@ -7,7 +7,7 @@ buildscript {
|
|||
|
||||
}
|
||||
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
|
||||
// in the individual module build.gradle files
|
||||
|
|
|
@ -1 +1 @@
|
|||
Initial release.
|
||||
* Initial release.
|
||||
|
|
5
fastlane/metadata/android/en-US/changelogs/2.txt
Normal file
5
fastlane/metadata/android/en-US/changelogs/2.txt
Normal 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
|
4
fastlane/metadata/android/en-US/changelogs/3.txt
Normal file
4
fastlane/metadata/android/en-US/changelogs/3.txt
Normal 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
|
|
@ -14,4 +14,9 @@ org.gradle.jvmargs=-Xmx1536m
|
|||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# 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
|
||||
|
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
#Sun May 26 22:24:42 BST 2019
|
||||
#Fri Sep 06 22:42:44 BST 2019
|
||||
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
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue