From fce85eb8420c11d2f0a55d47175f8279a8b74a12 Mon Sep 17 00:00:00 2001 From: wesaphzt Date: Wed, 3 Jul 2019 16:06:51 +0100 Subject: [PATCH] Initial commit --- .gitignore | 13 + .idea/encodings.xml | 4 + .idea/gradle.xml | 15 + .idea/misc.xml | 9 + .idea/runConfigurations.xml | 12 + app/.gitignore | 1 + app/build.gradle | 35 ++ app/proguard-rules.pro | 21 + .../privatelock/ExampleInstrumentedTest.java | 26 + app/src/main/AndroidManifest.xml | 66 +++ app/src/main/ic_launcher-web.png | Bin 0 -> 16562 bytes .../wesaphzt/privatelock/IntroActivity.java | 72 +++ .../wesaphzt/privatelock/MainActivity.java | 453 ++++++++++++++++++ .../privatelock/animation/Circle.java | 56 +++ .../animation/CircleAngleAnimation.java | 26 + .../privatelock/fragments/FragmentAbout.java | 114 +++++ .../privatelock/fragments/FragmentDonate.java | 181 +++++++ .../fragments/FragmentSettings.java | 53 ++ .../privatelock/receivers/BootReceiver.java | 36 ++ .../receivers/DeviceAdminReceiver.java | 13 + .../receivers/NotificationReceiver.java | 60 +++ .../privatelock/receivers/PauseReceiver.java | 67 +++ .../receivers/PresenceReceiver.java | 24 + .../privatelock/service/LockService.java | 251 ++++++++++ .../widget/LockWidgetProvider.java | 186 +++++++ app/src/main/res/anim/enter_from_left.xml | 8 + app/src/main/res/anim/enter_from_right.xml | 8 + app/src/main/res/anim/exit_to_left.xml | 8 + app/src/main/res/anim/exit_to_right.xml | 8 + .../drawable-v24/ic_launcher_foreground.xml | 34 ++ .../ic_about_bug_report_black_24dp.xml | 9 + .../res/drawable/ic_about_code_black_24dp.xml | 9 + .../ic_about_copyright_black_24dp.xml | 9 + .../ic_about_info_outline_black_24dp.xml | 9 + .../drawable/ic_about_person_black_24dp.xml | 9 + .../ic_action_settings_white_24dp.xml | 5 + .../res/drawable/ic_donate_bitcoin_logo.xml | 5 + .../res/drawable/ic_donate_ethereum_logo.xml | 23 + .../res/drawable/ic_donate_litecoin_logo.xml | 6 + .../res/drawable/ic_donate_monero_logo.xml | 5 + app/src/main/res/drawable/ic_intro_iris.xml | 97 ++++ app/src/main/res/drawable/ic_intro_lock.xml | 24 + app/src/main/res/drawable/ic_intro_shield.xml | 17 + .../res/drawable/ic_launcher_background.xml | 170 +++++++ .../res/drawable/ic_launcher_foreground.xml | 30 ++ .../ic_lock_closed_outline_white_24dp.xml | 5 + .../ic_lock_open_outline_white_24dp.xml | 5 + .../main/res/drawable/ic_lock_white_24dp.xml | 5 + app/src/main/res/layout/activity_main.xml | 25 + app/src/main/res/layout/app_widget.xml | 26 + app/src/main/res/layout/content_main.xml | 166 +++++++ app/src/main/res/layout/fragment_about.xml | 324 +++++++++++++ app/src/main/res/layout/fragment_donate.xml | 253 ++++++++++ app/src/main/res/menu/menu_main.xml | 36 ++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1955 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3500 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1428 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2303 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2579 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 4782 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3843 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 7235 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 5293 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 10154 bytes app/src/main/res/values/arrays.xml | 21 + app/src/main/res/values/colors.xml | 16 + app/src/main/res/values/dimens.xml | 21 + .../res/values/ic_launcher_background.xml | 4 + app/src/main/res/values/strings.xml | 88 ++++ app/src/main/res/values/styles.xml | 20 + app/src/main/res/xml/app_widget_info.xml | 10 + app/src/main/res/xml/device_admin.xml | 6 + app/src/main/res/xml/preferences.xml | 21 + .../wesaphzt/privatelock/ExampleUnitTest.java | 17 + build.gradle | 27 ++ gradle.properties | 17 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 +++++++ gradlew.bat | 84 ++++ settings.gradle | 1 + 83 files changed, 3673 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/encodings.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/com/wesaphzt/privatelock/ExampleInstrumentedTest.java create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/ic_launcher-web.png create mode 100644 app/src/main/java/com/wesaphzt/privatelock/IntroActivity.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/MainActivity.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/animation/Circle.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/animation/CircleAngleAnimation.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentAbout.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentDonate.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentSettings.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/receivers/BootReceiver.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/receivers/DeviceAdminReceiver.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/receivers/NotificationReceiver.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/receivers/PauseReceiver.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/receivers/PresenceReceiver.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/service/LockService.java create mode 100644 app/src/main/java/com/wesaphzt/privatelock/widget/LockWidgetProvider.java create mode 100644 app/src/main/res/anim/enter_from_left.xml create mode 100644 app/src/main/res/anim/enter_from_right.xml create mode 100644 app/src/main/res/anim/exit_to_left.xml create mode 100644 app/src/main/res/anim/exit_to_right.xml create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/ic_about_bug_report_black_24dp.xml create mode 100644 app/src/main/res/drawable/ic_about_code_black_24dp.xml create mode 100644 app/src/main/res/drawable/ic_about_copyright_black_24dp.xml create mode 100644 app/src/main/res/drawable/ic_about_info_outline_black_24dp.xml create mode 100644 app/src/main/res/drawable/ic_about_person_black_24dp.xml create mode 100644 app/src/main/res/drawable/ic_action_settings_white_24dp.xml create mode 100644 app/src/main/res/drawable/ic_donate_bitcoin_logo.xml create mode 100644 app/src/main/res/drawable/ic_donate_ethereum_logo.xml create mode 100644 app/src/main/res/drawable/ic_donate_litecoin_logo.xml create mode 100644 app/src/main/res/drawable/ic_donate_monero_logo.xml create mode 100644 app/src/main/res/drawable/ic_intro_iris.xml create mode 100644 app/src/main/res/drawable/ic_intro_lock.xml create mode 100644 app/src/main/res/drawable/ic_intro_shield.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/ic_lock_closed_outline_white_24dp.xml create mode 100644 app/src/main/res/drawable/ic_lock_open_outline_white_24dp.xml create mode 100644 app/src/main/res/drawable/ic_lock_white_24dp.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/app_widget.xml create mode 100644 app/src/main/res/layout/content_main.xml create mode 100644 app/src/main/res/layout/fragment_about.xml create mode 100644 app/src/main/res/layout/fragment_donate.xml create mode 100644 app/src/main/res/menu/menu_main.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values/arrays.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/ic_launcher_background.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 app/src/main/res/xml/app_widget_info.xml create mode 100644 app/src/main/res/xml/device_admin.xml create mode 100644 app/src/main/res/xml/preferences.xml create mode 100644 app/src/test/java/com/wesaphzt/privatelock/ExampleUnitTest.java create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b75303 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..2996d53 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..37a7509 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..951f4aa --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,35 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "com.wesaphzt.privatelock" + minSdkVersion 17 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation 'com.intuit.sdp:sdp-android:1.0.3' + implementation 'androidx.preference:preference:1.0.0' + implementation 'com.github.AppIntro:AppIntro:5.1.0' + + implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.google.android.material:material:1.0.0' + + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/wesaphzt/privatelock/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/wesaphzt/privatelock/ExampleInstrumentedTest.java new file mode 100644 index 0000000..6c405b7 --- /dev/null +++ b/app/src/androidTest/java/com/wesaphzt/privatelock/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.wesaphzt.privatelock; + +import android.content.Context; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.wesaphzt.privatelock", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..02f9247 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000000000000000000000000000000000000..845b06e4e433274a9d8a7c1c80046932bd71534e GIT binary patch literal 16562 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≶4CW9)CF%<$S`oAJ{G#<6U4~OA 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 literal 0 HcmV?d00001 diff --git a/app/src/main/java/com/wesaphzt/privatelock/IntroActivity.java b/app/src/main/java/com/wesaphzt/privatelock/IntroActivity.java new file mode 100644 index 0000000..432e565 --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/IntroActivity.java @@ -0,0 +1,72 @@ +package com.wesaphzt.privatelock; + +import android.os.Bundle; +import android.view.WindowManager; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.github.paolorotolo.appintro.AppIntro; +import com.github.paolorotolo.appintro.AppIntroFragment; +import com.github.paolorotolo.appintro.model.SliderPage; + +import static com.wesaphzt.privatelock.service.LockService.mInitialized; + +public class IntroActivity extends AppIntro { + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + //fullscreen + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + + //slider pages + SliderPage sliderPageOne = new SliderPage(); + sliderPageOne.setTitle(getResources().getString(R.string.slider_page_one_title)); + sliderPageOne.setDescription(getString(R.string.slider_page_one_desc)); + sliderPageOne.setImageDrawable(R.drawable.ic_intro_lock); + sliderPageOne.setBgColor(getResources().getColor(R.color.colorPrimary)); + addSlide(AppIntroFragment.newInstance(sliderPageOne)); + + SliderPage sliderPageTwo = new SliderPage(); + sliderPageTwo.setTitle(getResources().getString(R.string.slider_page_two_title)); + sliderPageTwo.setDescription(getResources().getString(R.string.slider_page_two_desc)); + sliderPageTwo.setImageDrawable(R.drawable.ic_intro_iris); + sliderPageTwo.setBgColor(getResources().getColor(R.color.colorIntroGrey)); + addSlide(AppIntroFragment.newInstance(sliderPageTwo)); + + SliderPage sliderPageThree = new SliderPage(); + sliderPageThree.setTitle(getResources().getString(R.string.slider_page_three_title)); + sliderPageThree.setDescription(getResources().getString(R.string.slider_page_three_desc)); + sliderPageThree.setImageDrawable(R.drawable.ic_intro_shield); + sliderPageThree.setBgColor(getResources().getColor(R.color.colorIntroGreen)); + addSlide(AppIntroFragment.newInstance(sliderPageThree)); + + //options + setFadeAnimation(); + showSkipButton(false); + setProgressButtonEnabled(true); + + //setBarColor(getResources().getColor(R.color.colorPrimary)); + //setSeparatorColor(getResources().getColor(R.color.white)); + } + + @Override + public void onSkipPressed(Fragment currentFragment) { + super.onSkipPressed(currentFragment); + } + + @Override + public void onDonePressed(Fragment currentFragment) { + super.onDonePressed(currentFragment); + mInitialized = false; + finish(); + } + + @Override + public void onSlideChanged(@Nullable Fragment oldFragment, @Nullable Fragment newFragment) { + super.onSlideChanged(oldFragment, newFragment); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/wesaphzt/privatelock/MainActivity.java b/app/src/main/java/com/wesaphzt/privatelock/MainActivity.java new file mode 100644 index 0000000..a6e5b97 --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/MainActivity.java @@ -0,0 +1,453 @@ +package com.wesaphzt.privatelock; + +import android.app.Activity; +import android.app.NotificationManager; +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Build; +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +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.widget.SeekBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.wesaphzt.privatelock.animation.Circle; +import com.wesaphzt.privatelock.animation.CircleAngleAnimation; +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 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; +import static com.wesaphzt.privatelock.service.LockService.disabled; + +public class MainActivity extends AppCompatActivity { + + private Context context; + + private int mSensitivity; + private float mLastX, mLastY, mLastZ; + private boolean mInitialized; + private static SensorManager mSensorManager; + private Sensor mAccelerometer; + private final float NOISE = (float) 2.0; + + private SensorEventListener mActiveListener; + + //DevicePolicyManager + private DevicePolicyManager mDPM; + private ComponentName mDeviceAdmin; + + private static final int REQUEST_CODE_ENABLE_ADMIN = 1; + + private TextView tvSensitivityActualValue; + + private SharedPreferences prefs; + public static final String PREFS_THRESHOLD = "THRESHOLD"; + + private CountDownTimer cdTimer; + private final int cdTimerLength = 2000; + private boolean isRunning = false; + + 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; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + context = getApplicationContext(); + this.prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); + + getFirstRun(); + + setContentView(R.layout.activity_main); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + getSupportFragmentManager().addOnBackStackChangedListener( + new FragmentManager.OnBackStackChangedListener() { + public void onBackStackChanged() { + //toggle back arrow on back stack change + if (getSupportActionBar() != null) { + if (getSupportFragmentManager().getBackStackEntryCount() > 0) { + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } else { + getSupportActionBar().setDisplayHomeAsUpEnabled(false); + //set title + MainActivity.this.setTitle(R.string.app_name); + } + } + } + }); + + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(getSupportFragmentManager().getBackStackEntryCount() > 0){ + getSupportFragmentManager().popBackStack(); + } + } + }); + + //https://stackoverflow.com/questions/29381474/how-to-draw-a-circle-with-animation-in-android-with-circle-size-based-on-a-value + circle = findViewById(R.id.circle); + circle_bg = findViewById(R.id.circle_bg); + + 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.startAnimation(animation); + + //shared prefs + try { + mSensitivity = prefs.getInt(PREFS_THRESHOLD, DEFAULT_SENSITIVITY); + } catch (Exception e) { + Toast.makeText(context, "Unable to retrieve threshold", Toast.LENGTH_LONG).show(); + } + + //timer when lock hit + cdTimer = new CountDownTimer(cdTimerLength, 1000) { + public void onTick(long millisUntilFinished) { + isRunning = true; + } + public void onFinish() { + isRunning = false; + circle.setColor(circleDefaultR, circleDefaultG, circleDefaultB); + } + }; + + //prevent lock animation artifacts + mInitialized = false; + + mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); + mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + + //sensor listener + setSensorListener(); + mSensorManager.registerListener(mActiveListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); + + //dpm + mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); + mDeviceAdmin = new ComponentName(this, DeviceAdminReceiver.class); + + tvSensitivityActualValue = findViewById(R.id.tvSensitivityActualValue); + tvSensitivityActualValue.setText(getString(R.string.sensitivity_value, Integer.toString(mSensitivity))); + + //seek bar + SeekBar sbSensitivity = findViewById(R.id.sbSensitivity); + sbSensitivity.setProgress(mSensitivity); + sbSensitivity.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + mSensitivity = progress; + tvSensitivityActualValue.setText(getString(R.string.sensitivity_value, Integer.toString(mSensitivity))); + + //submit to shared prefs + SharedPreferences.Editor editor = prefs.edit(); + editor.putInt(PREFS_THRESHOLD, progress).apply(); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { } + }); + } + + private void startLockService(Intent intent) { + //check android api + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(intent); + minimizeApp(); + } else { + context.startService(intent); + minimizeApp(); + } + } + + public void minimizeApp() { + Intent startMain = new Intent(Intent.ACTION_MAIN); + startMain.addCategory(Intent.CATEGORY_HOME); + startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(startMain); + } + + public void requestDeviceAdmin() { + Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mDeviceAdmin); + startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + //launch service if permission granted + if (requestCode == REQUEST_CODE_ENABLE_ADMIN) { + if(resultCode == Activity.RESULT_OK) { + startServicePrep(); + } + } + } + + //determine if we are an active admin + private boolean isActiveAdmin() { + return mDPM.isAdminActive(mDeviceAdmin); + } + + protected void onResume() { + super.onResume(); + mSensorManager.registerListener(mActiveListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); + //recreate menu to set start/stop again + invalidateOptionsMenu(); + } + + protected void onPause() { + super.onPause(); + mSensorManager.unregisterListener(mActiveListener); + } + + private void setSensorListener() { + mActiveListener = new SensorEventListener() { + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { } + + @Override + public void onSensorChanged(SensorEvent event) { + sensorCalc(event); + } + }; + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + //inflate actionbar menu + getMenuInflater().inflate(R.menu.menu_main, menu); + + return true; + } + + 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); + + //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); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + + Fragment fragment = null; + + if (id == R.id.action_start) { + if (isActiveAdmin()) { + startServicePrep(); + } else { + requestDeviceAdmin(); + } + } else if (id == R.id.action_stop) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationManager notificationManager = + (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.deleteNotificationChannel(CHANNEL_ID); + + disabled = true; + mSensorManager.unregisterListener(activeListener); + + LockWidgetProvider lockWidgetProvider = new LockWidgetProvider(); + lockWidgetProvider.setWidgetStop(context); + + invalidateOptionsMenu(); + } else { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(LockService.NOTIFICATION_ID); + + disabled = true; + mSensorManager.unregisterListener(activeListener); + + LockWidgetProvider lockWidgetProvider = new LockWidgetProvider(); + lockWidgetProvider.setWidgetStop(context); + } + } else if (id == R.id.action_settings) { + fragment = new FragmentSettings(); + } else if (id == R.id.action_donate) { + fragment = new FragmentDonate(); + } else if (id == R.id.action_show_intro) { + Intent myIntent = new Intent(this, IntroActivity.class); + this.startActivity(myIntent); + } else if (id == R.id.action_about) { + fragment = new FragmentAbout(); + } + + //add fragment + if (fragment != null) { + FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); + fragmentTransaction.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left); + fragmentTransaction.add(R.id.content_main, fragment); + fragmentTransaction.addToBackStack(null); + fragmentTransaction.commit(); + } + + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + MenuItem action_start = menu.findItem(R.id.action_start); + MenuItem action_stop = menu.findItem(R.id.action_stop); + + setMenuStatus(action_start, action_stop); + + return true; + } + + public void setMenuStatus(MenuItem action_start, MenuItem action_stop) { + if (disabled) { + action_start.setEnabled(true); + action_stop.setEnabled(false); + } else { + //enabled + action_start.setEnabled(false); + action_stop.setEnabled(true); + } + } + + private void getFirstRun() { + //get current version code + int currentVersionCode = BuildConfig.VERSION_CODE; + //get saved version code + int savedVersionCode = DOESNT_EXIST; + try { + savedVersionCode = this.prefs.getInt(PREF_VERSION_CODE_KEY, DOESNT_EXIST); + } catch (Exception e) { + e.printStackTrace(); + } + //check first run + //noinspection StatementWithEmptyBody + if (currentVersionCode == savedVersionCode) { + //normal run + } else if (savedVersionCode == DOESNT_EXIST) { + //first run + Intent myIntent = new Intent(this, IntroActivity.class); + this.startActivity(myIntent); + } + //update shared prefs with current version code + this.prefs.edit().putInt(PREF_VERSION_CODE_KEY, currentVersionCode).apply(); + } + + private void sensorCalc(SensorEvent event) { + float x = event.values[0]; + float y = event.values[1]; + float z = event.values[2]; + + if (!mInitialized) { + mLastX = x; + mLastY = y; + mLastZ = z; + + mInitialized = true; + } else { + float deltaX = Math.abs(mLastX - x); + float deltaY = Math.abs(mLastY - y); + float deltaZ = Math.abs(mLastZ - z); + + if (deltaX < NOISE) deltaX = (float) 0.0; + if (deltaY < NOISE) deltaY = (float) 0.0; + if (deltaZ < NOISE) deltaZ = (float) 0.0; + + mLastX = x; + mLastY = y; + mLastZ = z; + + float total = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ); + + int calculatedAngleInt; + + if (total <= mSensitivity) { + //do nothing if timer currently running + if(isRunning) + return; + + calculatedAngleInt = Math.round((total / mSensitivity) * 360); + + CircleAngleAnimation 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(); + } + } + } + +} diff --git a/app/src/main/java/com/wesaphzt/privatelock/animation/Circle.java b/app/src/main/java/com/wesaphzt/privatelock/animation/Circle.java new file mode 100644 index 0000000..fc914ef --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/animation/Circle.java @@ -0,0 +1,56 @@ +package com.wesaphzt.privatelock.animation; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.View; + +public class Circle extends View { + + private static final int START_ANGLE_POINT = 90; + + private final Paint paint; + private final RectF rect; + + private float angle; + + public Circle(Context context, AttributeSet attrs) { + super(context, attrs); + + final int strokeWidth = 10; + + paint = new Paint(); + paint.setAntiAlias(true); + paint.setStyle(Paint.Style.FILL); + paint.setStrokeWidth(strokeWidth); + //circle color (currently set upon instance) + //paint.setColor(Color.BLUE); + + //size + rect = new RectF(strokeWidth, strokeWidth, 600 + strokeWidth, 600 + strokeWidth); + + //initial angle (optional) + angle = 0; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawArc(rect, START_ANGLE_POINT, angle, true, paint); + } + + public float getAngle() { + return angle; + } + + public void setColor(int r, int g, int b) { + paint.setColor(Color.rgb(r, g, b)); + } + + public void setAngle(float angle) { + this.angle = angle; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/wesaphzt/privatelock/animation/CircleAngleAnimation.java b/app/src/main/java/com/wesaphzt/privatelock/animation/CircleAngleAnimation.java new file mode 100644 index 0000000..6a61c9a --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/animation/CircleAngleAnimation.java @@ -0,0 +1,26 @@ +package com.wesaphzt.privatelock.animation; + +import android.view.animation.Animation; +import android.view.animation.Transformation; + +public class CircleAngleAnimation extends Animation { + + private Circle circle; + + private float oldAngle; + private float newAngle; + + public CircleAngleAnimation(Circle circle, int newAngle) { + this.oldAngle = circle.getAngle(); + this.newAngle = newAngle; + this.circle = circle; + } + + @Override + protected void applyTransformation(float interpolatedTime, Transformation transformation) { + float angle = oldAngle + ((newAngle - oldAngle) * interpolatedTime); + + circle.setAngle(angle); + circle.requestLayout(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentAbout.java b/app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentAbout.java new file mode 100644 index 0000000..67d8a44 --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentAbout.java @@ -0,0 +1,114 @@ +package com.wesaphzt.privatelock.fragments; + +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Bundle; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; + +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 AUTHOR_GITHUB; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_about, container, false); + + GITHUB_URI = getString(R.string.app_github); + AUTHOR_GITHUB = getString(R.string.app_github_dev); + + String versionName = ""; + try { + PackageInfo packageInfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0); + versionName = packageInfo.versionName; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + + TextView version = v.findViewById(R.id.about_text_version); + version.setText(versionName); + + LinearLayout license = v.findViewById(R.id.about_layout_license); + LinearLayout source = v.findViewById(R.id.about_layout_source); + + license.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + openURI(LICENSE_URI); + } + }); + source.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + openURI(GITHUB_URI); + } + }); + + LinearLayout authorLayout = v.findViewById(R.id.aboutLayoutAuthor); + authorLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + openURI(AUTHOR_GITHUB); + } + }); + + LinearLayout bugReport = v.findViewById(R.id.about_layout_bugs); + bugReport.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + openURI(BUG_REPORT_URI); + } + }); + + return v; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + setHasOptionsMenu(true); + + super.onCreate(savedInstanceState); + } + + private void openURI(String uri) { + try { + Intent openURI = new Intent(Intent.ACTION_VIEW); + openURI.setData(Uri.parse(uri)); + startActivity(openURI); + } catch (Exception e) { + Log.d("app-error", "error opening uri"); + } + } + + @Override + public void onPrepareOptionsMenu(Menu menu) { + //hide action bar menu + menu.setGroupVisible(R.id.menu_main, false); + + super.onPrepareOptionsMenu(menu); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + //set title + getActivity().setTitle(getString(R.string.fragment_about_title)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentDonate.java b/app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentDonate.java new file mode 100644 index 0000000..ab1416f --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentDonate.java @@ -0,0 +1,181 @@ +package com.wesaphzt.privatelock.fragments; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; + +import com.wesaphzt.privatelock.R; + +public class FragmentDonate extends Fragment { + + private Context context; + + private static final String BITCOIN_PREFIX = "bitcoin:"; + private static final String LITECOIN_PREFIX = "litecoin:"; + private static final String ETHEREUM_PREFIX = "ethereum:"; + private static final String MONERO_PREFIX = "monero:"; + + private static String BITCOIN_ADDRESS; + private static String BITCOIN_FULL; + + private static String LITECOIN_ADDRESS; + private static String LITECOIN_FULL; + + private static String ETHEREUM_ADDRESS; + private static String ETHEREUM_FULL; + + private static String MONERO_ADDRESS; + private static String MONERO_FULL; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_donate, container, false); + + setHasOptionsMenu(true); + + context = getContext(); + + final TextView tvAddressBtc = view.findViewById(R.id.donate_bitcoin_address); + final TextView tvAddressLtc = view.findViewById(R.id.donate_litecoin_address); + final TextView tvAddressEth = view.findViewById(R.id.donate_ethereum_address); + final TextView tvAddressXmr = view.findViewById(R.id.donate_monero_address); + + BITCOIN_ADDRESS = getString(R.string.donate_bitcoin_address); + BITCOIN_FULL = BITCOIN_PREFIX + BITCOIN_ADDRESS; + tvAddressBtc.setText(BITCOIN_ADDRESS); + + LITECOIN_ADDRESS = getString(R.string.donate_litecoin_address); + LITECOIN_FULL = LITECOIN_PREFIX + LITECOIN_ADDRESS; + tvAddressLtc.setText(LITECOIN_ADDRESS); + + ETHEREUM_ADDRESS = getString(R.string.donate_ethereum_address); + ETHEREUM_FULL = ETHEREUM_PREFIX + ETHEREUM_ADDRESS; + tvAddressEth.setText(ETHEREUM_ADDRESS); + + MONERO_ADDRESS = getString(R.string.donate_monero_address); + MONERO_FULL = MONERO_PREFIX + MONERO_ADDRESS; + tvAddressXmr.setText(MONERO_ADDRESS); + + tvAddressBtc.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + //attempt to open bitcoin app, else copy to clipboard + try { + openURI(BITCOIN_FULL); + } catch(Exception ignored) { + copyToClipboard(BITCOIN_ADDRESS); + } + } + }); + tvAddressBtc.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(BITCOIN_ADDRESS); + return true; + } + }); + + //litecoin + tvAddressLtc.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + //attempt to open litecoin app, else copy to clipboard + try { + openURI(LITECOIN_FULL); + } catch(Exception ignored) { + copyToClipboard(LITECOIN_ADDRESS); + } + } + }); + tvAddressLtc.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(LITECOIN_ADDRESS); + return true; + } + }); + + //ethereum + tvAddressEth.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + //attempt to open ethereum app, else copy to clipboard + try { + openURI(ETHEREUM_FULL); + } catch(Exception ignored) { + copyToClipboard(ETHEREUM_ADDRESS); + } + } + }); + tvAddressEth.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(ETHEREUM_ADDRESS); + return true; + } + }); + + //monero + tvAddressXmr.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + //attempt to open ethereum app, else copy to clipboard + try { + openURI(MONERO_FULL); + } catch(Exception ignored) { + copyToClipboard(MONERO_ADDRESS); + } + } + }); + tvAddressXmr.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(MONERO_ADDRESS); + return true; + } + }); + + return view; + } + + private void copyToClipboard(String AUTHOR_EXTRA) { + ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText(getString(R.string.fragment_donate_clipboard_label), AUTHOR_EXTRA); + clipboard.setPrimaryClip(clip); + + Toast.makeText(context, R.string.fragment_donate_clipboard_message, Toast.LENGTH_SHORT).show(); + } + + private void openURI(String uri) { + Intent openURI = new Intent(Intent.ACTION_VIEW); + openURI.setData(Uri.parse(uri)); + startActivity(openURI); + } + + @Override + public void onPrepareOptionsMenu(Menu menu) { + //hide action bar menu + menu.setGroupVisible(R.id.menu_main, false); + + super.onPrepareOptionsMenu(menu); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + //set title + getActivity().setTitle(getString(R.string.fragment_donate_title)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentSettings.java b/app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentSettings.java new file mode 100644 index 0000000..5456de0 --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/fragments/FragmentSettings.java @@ -0,0 +1,53 @@ +package com.wesaphzt.privatelock.fragments; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import androidx.annotation.Nullable; + +import android.view.Menu; +import android.view.View; + +import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceManager; + +import com.wesaphzt.privatelock.R; + +public class FragmentSettings extends PreferenceFragmentCompat { + + private SharedPreferences prefs; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.preferences); + + setHasOptionsMenu(true); + Context context = getContext(); + + //this static call will reset default values only on the first read + PreferenceManager.setDefaultValues(context, R.xml.preferences, false); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + //set title + getActivity().setTitle("Settings"); + + //bg color + view.setBackgroundColor(getResources().getColor(R.color.white)); + } + + @Override + public void onPrepareOptionsMenu(Menu menu) { + //hide action bar menu + menu.setGroupVisible(R.id.menu_main, false); + + super.onPrepareOptionsMenu(menu); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/wesaphzt/privatelock/receivers/BootReceiver.java b/app/src/main/java/com/wesaphzt/privatelock/receivers/BootReceiver.java new file mode 100644 index 0000000..7c27e60 --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/receivers/BootReceiver.java @@ -0,0 +1,36 @@ +package com.wesaphzt.privatelock.receivers; + +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; + +public class BootReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + + if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);; + if(prefs.getBoolean("START_ON_BOOT", false)) { + Intent i = new Intent(context, LockService.class); + + //check android api + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context.startForegroundService(i); + LockWidgetProvider lockWidgetProvider = new LockWidgetProvider(); + lockWidgetProvider.setWidgetStart(context); + } else { + context.startService(i); + LockWidgetProvider lockWidgetProvider = new LockWidgetProvider(); + lockWidgetProvider.setWidgetStart(context); + } + } + } + } +} diff --git a/app/src/main/java/com/wesaphzt/privatelock/receivers/DeviceAdminReceiver.java b/app/src/main/java/com/wesaphzt/privatelock/receivers/DeviceAdminReceiver.java new file mode 100644 index 0000000..59ced95 --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/receivers/DeviceAdminReceiver.java @@ -0,0 +1,13 @@ +package com.wesaphzt.privatelock.receivers; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class DeviceAdminReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + + } +} diff --git a/app/src/main/java/com/wesaphzt/privatelock/receivers/NotificationReceiver.java b/app/src/main/java/com/wesaphzt/privatelock/receivers/NotificationReceiver.java new file mode 100644 index 0000000..cb57455 --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/receivers/NotificationReceiver.java @@ -0,0 +1,60 @@ +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 { + + @Override + public void onReceive(Context context, Intent intent) { + 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(); + + 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); + } + + } 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); + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/wesaphzt/privatelock/receivers/PauseReceiver.java b/app/src/main/java/com/wesaphzt/privatelock/receivers/PauseReceiver.java new file mode 100644 index 0000000..69a6fb4 --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/receivers/PauseReceiver.java @@ -0,0 +1,67 @@ +package com.wesaphzt.privatelock.receivers; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.CountDownTimer; +import android.preference.PreferenceManager; +import android.widget.Toast; + +import com.wesaphzt.privatelock.widget.LockWidgetProvider; + +import static com.wesaphzt.privatelock.service.LockService.disabled; +import static com.wesaphzt.privatelock.service.LockService.mInitialized; + +public class PauseReceiver extends BroadcastReceiver { + + public static CountDownTimer mCountdown; + public static boolean isRunning = false; + + @Override + public void onReceive(final Context context, Intent intent) { + String action = intent.getStringExtra("pause_service"); + + if (action.equals("pause_service_time")) { + //close notification tray + Intent i = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); + context.sendBroadcast(i); + + if(disabled) { + Toast.makeText(context, "Service is already paused", Toast.LENGTH_SHORT).show(); + return; + } else { + disabled = true; + LockWidgetProvider lockWidgetProvider = new LockWidgetProvider(); + lockWidgetProvider.setWidgetPause(context); + } + + //shared prefs + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + int pauseMinuteTime = Integer.parseInt(prefs.getString("PAUSE_TIME", String.valueOf(1))); + int milliPauseTime = pauseMinuteTime * 60 * 1000; + + String plural; + if(pauseMinuteTime == 1) { plural = "minute"; } else { plural = "minutes"; } + + Toast.makeText(context, "Service paused for " + pauseMinuteTime + " " + plural, Toast.LENGTH_LONG).show(); + + mCountdown = new CountDownTimer(milliPauseTime, 1000) { + public void onTick(long millisUntilFinished) { + isRunning = true; + } + public void onFinish() { + //prevent lock animation artifacts + mInitialized = false; + //init + disabled = false; + isRunning = false; + LockWidgetProvider lockWidgetProvider = new LockWidgetProvider(); + lockWidgetProvider.setWidgetStart(context); + + Toast.makeText(context, "Service resumed", Toast.LENGTH_LONG).show(); + } + }.start(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/wesaphzt/privatelock/receivers/PresenceReceiver.java b/app/src/main/java/com/wesaphzt/privatelock/receivers/PresenceReceiver.java new file mode 100644 index 0000000..0aad1e3 --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/receivers/PresenceReceiver.java @@ -0,0 +1,24 @@ +package com.wesaphzt.privatelock.receivers; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import static com.wesaphzt.privatelock.service.LockService.disabled; +import static com.wesaphzt.privatelock.service.LockService.mInitialized; + +public class PresenceReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) { + //prevent lock animation artifacts + mInitialized = false; + + disabled = false; + + } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { + disabled = true; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/wesaphzt/privatelock/service/LockService.java b/app/src/main/java/com/wesaphzt/privatelock/service/LockService.java new file mode 100644 index 0000000..1fbc0f9 --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/service/LockService.java @@ -0,0 +1,251 @@ +package com.wesaphzt.privatelock.service; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Build; +import android.os.IBinder; + +import androidx.annotation.NonNull; +import androidx.core.app.JobIntentService; +import androidx.core.app.NotificationCompat; + +import android.preference.PreferenceManager; +import android.widget.Toast; + +import com.wesaphzt.privatelock.MainActivity; +import com.wesaphzt.privatelock.R; +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 static androidx.core.app.NotificationCompat.PRIORITY_MIN; + +public class LockService extends JobIntentService { + + private Context context; + + 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; + public static boolean disabled = true; + + //DevicePolicyManager + DevicePolicyManager mDPM; + ComponentName mDeviceAdmin; + + //notifications + Notification notification; + NotificationManager notificationManager; + //ids + public static String CHANNEL_ID; + public static String CHANNEL_NAME; + public static final int NOTIFICATION_ID = 1000; + //intents + public static PendingIntent pendingIntent; + public static PendingIntent pendingCloseIntent; + public static PendingIntent pendingPauseIntent; + + //sensitivity + public static final int DEFAULT_SENSITIVITY = 10; + public static int SENSITIVITY; + + @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(); + + 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(); + + } + //------------------------------------------------------------------------------------------ + notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + //dpm + mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); + mDeviceAdmin = new ComponentName(this, DeviceAdminReceiver.class); + + //prevent lock animation artifacts + mInitialized = false; + + mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); + mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + + 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); + disabled = false; + + } else { + notificationManager.notify(NOTIFICATION_ID, notification); + disabled = false; + } + //------------------------------------------------------------------------------------------ + + return LockService.START_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + protected void onHandleWork(@NonNull Intent intent) { } + + private void setSensorListener() { + activeListener = new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent event) { + if(LockService.disabled) + return; + + sensorCalc(event); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { } + }; + } + + private void sensorCalc(SensorEvent event) { + float x = event.values[0]; + float y = event.values[1]; + float z = event.values[2]; + + if (!mInitialized) { + mLastX = x; + mLastY = y; + mLastZ = z; + + mInitialized = true; + } else { + float deltaX = Math.abs(mLastX - x); + float deltaY = Math.abs(mLastY - y); + float deltaZ = Math.abs(mLastZ - z); + + if (deltaX < NOISE) deltaX = (float) 0.0; + if (deltaY < NOISE) deltaY = (float) 0.0; + if (deltaZ < NOISE) deltaZ = (float) 0.0; + + mLastX = x; + mLastY = y; + mLastZ = z; + + float total = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ); + + if (total > SENSITIVITY) { + try { + mDPM.lockNow(); + } catch (Exception e) { + Toast.makeText(context, "Error locking, does app have device admin permissions?", Toast.LENGTH_SHORT).show(); + } + } + } + } + + private void setNotification() { + //notification + pendingIntent = PendingIntent.getActivity(context, 0, + new Intent(context, MainActivity.class) + .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP), + 0); + + //notification stop button + Intent intentStopAction = new Intent(context, NotificationReceiver.class); + intentStopAction.putExtra("lock_service","lock_service_notification"); + pendingCloseIntent = PendingIntent.getBroadcast(context,0, intentStopAction, PendingIntent.FLAG_UPDATE_CURRENT); + + //notification pause button + Intent intentPauseAction = new Intent(context, PauseReceiver.class); + intentPauseAction.putExtra("pause_service","pause_service_time"); + pendingPauseIntent = PendingIntent.getBroadcast(context,0, intentPauseAction, PendingIntent.FLAG_UPDATE_CURRENT); + + NotificationCompat.Builder notificationBuilder; + + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) { + notificationBuilder = new NotificationCompat.Builder(this); + notification = notificationBuilder + .setSmallIcon(R.drawable.ic_lock_white_24dp) + .setContentTitle(getString(R.string.app_name) + " is running") + .setCategory(NotificationCompat.CATEGORY_SERVICE) + .setContentIntent(pendingIntent) + .setWhen(System.currentTimeMillis()) + .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) + .setOngoing(true) + .build(); + + } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N| Build.VERSION.SDK_INT == Build.VERSION_CODES.N_MR1) { + notificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID); + notification = notificationBuilder + .setSmallIcon(R.drawable.ic_lock_white_24dp) + .setContentTitle(getString(R.string.app_name) + " is running") + .setCategory(NotificationCompat.CATEGORY_SERVICE) + .setColor(getColor(R.color.colorPrimary)) + .setContentIntent(pendingIntent) + .setWhen(System.currentTimeMillis()) + .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) + .setOngoing(true) + .build(); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW); + channel.setImportance(NotificationManager.IMPORTANCE_LOW); + channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); + notificationManager.createNotificationChannel(channel); + + notificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID); + notification = notificationBuilder + .setSmallIcon(R.drawable.ic_lock_white_24dp) + .setContentTitle(getString(R.string.app_name) + " is running") + .setPriority(PRIORITY_MIN) + .setVisibility(NotificationCompat.VISIBILITY_SECRET) + .setCategory(NotificationCompat.CATEGORY_SERVICE) + .setColor(getColor(R.color.colorPrimary)) + .setContentIntent(pendingIntent) + .setWhen(System.currentTimeMillis()) + .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) + .setOngoing(true) + .build(); + } + } +} diff --git a/app/src/main/java/com/wesaphzt/privatelock/widget/LockWidgetProvider.java b/app/src/main/java/com/wesaphzt/privatelock/widget/LockWidgetProvider.java new file mode 100644 index 0000000..0f973a6 --- /dev/null +++ b/app/src/main/java/com/wesaphzt/privatelock/widget/LockWidgetProvider.java @@ -0,0 +1,186 @@ +package com.wesaphzt.privatelock.widget; + +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Build; +import android.preference.PreferenceManager; +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 { + + private static final String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget"; + public boolean SERVICE_STATUS; + + public void onUpdate(Context context, AppWidgetManager appWidgetManager, + int[] appWidgetIds) { + + for (int appWidgetId : appWidgetIds) { + RemoteViews remoteViews = new RemoteViews(context.getPackageName(), + R.layout.app_widget); + + //default status + remoteViews.setTextViewText(R.id.tvWidgetToggle, context.getResources().getString(R.string.widget_start_text)); + + Intent intent = new Intent(context, LockWidgetProvider.class); + intent.setAction(ACTION_WIDGET_RECEIVER); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, + 0, intent, 0); + + remoteViews.setOnClickPendingIntent(R.id.llWidget, pendingIntent); + + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context); + boolean value = prefs.getBoolean(context.getString(R.string.widget_prefs_service_id), false); + + if (value) { + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(context.getString(R.string.widget_prefs_service_id), false); + editor.apply(); + } + + appWidgetManager.updateAppWidget(appWidgetId, remoteViews); + } + } + + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(ACTION_WIDGET_RECEIVER)) { + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context); + boolean value = prefs.getBoolean(context.getString(R.string.widget_prefs_service_id), false); + SharedPreferences.Editor editor = prefs.edit(); + + SERVICE_STATUS = value; + + //if service is running + if (SERVICE_STATUS) { + editor.putBoolean(context.getString(R.string.widget_prefs_service_id), false); + editor.apply(); + + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_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); + } + } 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); + } + } + + //if service is not running + } else { + editor.putBoolean(context.getString(R.string.widget_prefs_service_id), true); + editor.commit(); + + Intent i = new Intent(context, LockService.class); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + disabled = false; + context.startForegroundService(i); + setWidgetStart(context); + } else { + disabled = false; + context.startService(i); + setWidgetStart(context); + } + } + } + super.onReceive(context, intent); + } + + @Override + public void onDeleted(Context context, int[] appWidgetIds) { + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context); + boolean value = prefs.getBoolean(context.getString(R.string.widget_prefs_service_id), false); + + if (value) { + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(context.getString(R.string.widget_prefs_service_id), false); + editor.apply(); + } + + super.onDeleted(context, appWidgetIds); + } + + //update widget methods + public void setWidgetStart(Context context) { + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context); + prefs.edit().putBoolean(context.getString(R.string.widget_prefs_service_id), true).apply(); + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); + ComponentName thisWidget = new ComponentName(context, LockWidgetProvider.class); + RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.app_widget); + + remoteViews.setTextViewText(R.id.tvWidgetToggle, context.getResources().getString(R.string.widget_stop_text)); + remoteViews.setImageViewResource(R.id.ivWidgetLock, R.drawable.ic_lock_closed_outline_white_24dp); + remoteViews.setInt(R.id.llWidget, "setBackgroundResource", R.color.colorWidgetStart); + + appWidgetManager.updateAppWidget(thisWidget, remoteViews); + } + + public void setWidgetStop(Context context) { + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context); + prefs.edit().putBoolean(context.getString(R.string.widget_prefs_service_id), false).apply(); + + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); + ComponentName thisWidget = new ComponentName(context, LockWidgetProvider.class); + RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.app_widget); + + remoteViews.setTextViewText(R.id.tvWidgetToggle, context.getResources().getString(R.string.widget_start_text)); + remoteViews.setImageViewResource(R.id.ivWidgetLock, R.drawable.ic_lock_open_outline_white_24dp); + remoteViews.setInt(R.id.llWidget, "setBackgroundResource", R.color.colorWidgetStop); + + appWidgetManager.updateAppWidget(thisWidget, remoteViews); + } + + public void setWidgetPause(Context context) { + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context); + prefs.edit().putBoolean(context.getString(R.string.widget_prefs_service_id), true).apply(); + + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); + ComponentName thisWidget = new ComponentName(context, LockWidgetProvider.class); + RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.app_widget); + + remoteViews.setTextViewText(R.id.tvWidgetToggle, context.getResources().getString(R.string.widget_stop_text)); + remoteViews.setImageViewResource(R.id.ivWidgetLock, R.drawable.ic_lock_open_outline_white_24dp); + remoteViews.setInt(R.id.llWidget, "setBackgroundResource", R.color.colorWidgetPause); + + appWidgetManager.updateAppWidget(thisWidget, remoteViews); + } +} \ No newline at end of file diff --git a/app/src/main/res/anim/enter_from_left.xml b/app/src/main/res/anim/enter_from_left.xml new file mode 100644 index 0000000..d89d3a5 --- /dev/null +++ b/app/src/main/res/anim/enter_from_left.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/enter_from_right.xml b/app/src/main/res/anim/enter_from_right.xml new file mode 100644 index 0000000..3a49719 --- /dev/null +++ b/app/src/main/res/anim/enter_from_right.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/exit_to_left.xml b/app/src/main/res/anim/exit_to_left.xml new file mode 100644 index 0000000..e683a04 --- /dev/null +++ b/app/src/main/res/anim/exit_to_left.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/exit_to_right.xml b/app/src/main/res/anim/exit_to_right.xml new file mode 100644 index 0000000..e8aecaf --- /dev/null +++ b/app/src/main/res/anim/exit_to_right.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_about_bug_report_black_24dp.xml b/app/src/main/res/drawable/ic_about_bug_report_black_24dp.xml new file mode 100644 index 0000000..4d83902 --- /dev/null +++ b/app/src/main/res/drawable/ic_about_bug_report_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_about_code_black_24dp.xml b/app/src/main/res/drawable/ic_about_code_black_24dp.xml new file mode 100644 index 0000000..6f1ccb6 --- /dev/null +++ b/app/src/main/res/drawable/ic_about_code_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_about_copyright_black_24dp.xml b/app/src/main/res/drawable/ic_about_copyright_black_24dp.xml new file mode 100644 index 0000000..fad6892 --- /dev/null +++ b/app/src/main/res/drawable/ic_about_copyright_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_about_info_outline_black_24dp.xml b/app/src/main/res/drawable/ic_about_info_outline_black_24dp.xml new file mode 100644 index 0000000..cf53e14 --- /dev/null +++ b/app/src/main/res/drawable/ic_about_info_outline_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_about_person_black_24dp.xml b/app/src/main/res/drawable/ic_about_person_black_24dp.xml new file mode 100644 index 0000000..b2cb337 --- /dev/null +++ b/app/src/main/res/drawable/ic_about_person_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_settings_white_24dp.xml b/app/src/main/res/drawable/ic_action_settings_white_24dp.xml new file mode 100644 index 0000000..1397d37 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_settings_white_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_donate_bitcoin_logo.xml b/app/src/main/res/drawable/ic_donate_bitcoin_logo.xml new file mode 100644 index 0000000..4314c27 --- /dev/null +++ b/app/src/main/res/drawable/ic_donate_bitcoin_logo.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/ic_donate_ethereum_logo.xml b/app/src/main/res/drawable/ic_donate_ethereum_logo.xml new file mode 100644 index 0000000..9c27d75 --- /dev/null +++ b/app/src/main/res/drawable/ic_donate_ethereum_logo.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_donate_litecoin_logo.xml b/app/src/main/res/drawable/ic_donate_litecoin_logo.xml new file mode 100644 index 0000000..48356f0 --- /dev/null +++ b/app/src/main/res/drawable/ic_donate_litecoin_logo.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_donate_monero_logo.xml b/app/src/main/res/drawable/ic_donate_monero_logo.xml new file mode 100644 index 0000000..55be9fe --- /dev/null +++ b/app/src/main/res/drawable/ic_donate_monero_logo.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/ic_intro_iris.xml b/app/src/main/res/drawable/ic_intro_iris.xml new file mode 100644 index 0000000..2ee6851 --- /dev/null +++ b/app/src/main/res/drawable/ic_intro_iris.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_intro_lock.xml b/app/src/main/res/drawable/ic_intro_lock.xml new file mode 100644 index 0000000..6cf40c7 --- /dev/null +++ b/app/src/main/res/drawable/ic_intro_lock.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_intro_shield.xml b/app/src/main/res/drawable/ic_intro_shield.xml new file mode 100644 index 0000000..5b9255e --- /dev/null +++ b/app/src/main/res/drawable/ic_intro_shield.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..8036715 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_lock_closed_outline_white_24dp.xml b/app/src/main/res/drawable/ic_lock_closed_outline_white_24dp.xml new file mode 100644 index 0000000..3d9f543 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock_closed_outline_white_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock_open_outline_white_24dp.xml b/app/src/main/res/drawable/ic_lock_open_outline_white_24dp.xml new file mode 100644 index 0000000..6c09b2a --- /dev/null +++ b/app/src/main/res/drawable/ic_lock_open_outline_white_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock_white_24dp.xml b/app/src/main/res/drawable/ic_lock_white_24dp.xml new file mode 100644 index 0000000..146c066 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock_white_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..9c96440 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/app_widget.xml b/app/src/main/res/layout/app_widget.xml new file mode 100644 index 0000000..d263d1b --- /dev/null +++ b/app/src/main/res/layout/app_widget.xml @@ -0,0 +1,26 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml new file mode 100644 index 0000000..87ea85d --- /dev/null +++ b/app/src/main/res/layout/content_main.xml @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml new file mode 100644 index 0000000..7254b0e --- /dev/null +++ b/app/src/main/res/layout/fragment_about.xml @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_donate.xml b/app/src/main/res/layout/fragment_donate.xml new file mode 100644 index 0000000..87dbb4d --- /dev/null +++ b/app/src/main/res/layout/fragment_donate.xml @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml new file mode 100644 index 0000000..e3a5d3c --- /dev/null +++ b/app/src/main/res/menu/menu_main.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..8c922d61a3141d7c13e60fd17982df8d38d8ebb6 GIT binary patch literal 1955 zcmV;U2VD4xP)3v28~;Dbp0Lkimc zqab=9xQd90`PiO+R3w2&P?`M^rSjYJJd$z5;)4gA5oY@6i*^XARVPE1U!V2_uXeq*ZiG2uO5 zHrtSG%SNG5US7`sV>I|Tu@bK_z ztpLrKF@u&ZTSjx|&ZWr6NX-C+g@x6@R;K_lx;35zGSs&ZO0=SJSp_+o+_Z!~#YMkfb$h)=*kn8YLtoP;_)OvDMZ00l^4BnKNe& zty;B;^78VixVZQ~P@v<-kJH7A7pb%kHg4QV>FMbS2+O>U3D`uqFo z(xpp$ezN6N@-SSqXb}en4;7f;Jr8Kwv}v?;>sH#mdp8|8aDcsd5L|rw_U)>GSnKA^n-(}dJw5z6!tCV9 zllPgQ;pRwQ2ZVWM%a$#|a4uZ9z@Y$6XJ;o5rNf60TPA71C@n3e zckkYDNPtyXSSSpLRqo!OgVwEECkzN40XWZ|J)^3sD#cX{;J$tPMx&#nR9{~&3~2iF z>D~vlWXTd?Kut|e91tewGiS~y0>a9N$r@e+PZNQI)eb3v*8w3D76sJa-p&EFwzl#m zUJ1~K4IAj`)2AHJt5>gt0AVF{u%c-L2rC&369LrG(ZK<=w6xH%W5*N$tzW;Mo;-QN z0lj_uRtOMsB?k$mHh|#9YF9E$#E={iJV<&SsRAZwNm*H0;{Zvos{w=(MHh)8KBb(T z9J^qS963T)u3X`H&%Jy1xX}RA*Vjk)@89RIK@T20;Lnl!KzL1B?uUnm`D=IX+~M<9 zMn;BRKqyOelSyMjwC6Pq4GrTGLM2%zib_ImR9#(d*P9Ufx&Z`tRswYD)G13yxeJgK za>&7yRxlMcns$KDjzD5(3lPGgx3|~rfIfZt#M1yd)!_^vd{DYxn(uNU2XX}H+O=yG92`ve(@;oA2t9oG&@Q0QpFi_H6#Ck7 ztz5ZMza2$%_pCqB+}vDx{P?jV93+h>DI_?O;2o&sl>mMD@`cWyKR?b};lX$hx&^dw z;X+|R$fogo)_{rJLV0oa>{)KSJ>k#;;OyPIm!BT-+4DhI(QvLu?N$vEJ+)g$=wQM_ zT{tVGj{{Wb%~)sG?f`^ZO)&4#?+G)60s1uV0<>et4z*1&-vER#KpWJ$kaY$SdO$cR zWwmE2WtzSUW zp$D`l)6wEh7}lQ+7MOP4Mk2MFZ@jsfHL1PxBw>lctD3xT##ya%>0oBm<8Wx~et z^75bnC&!OWu}nX+?DrQ|l{d0d;jj4k_*+bW%EkU|+|Sm})&7nru4#U}h4&5{U<+(A z+ZOD~H!qmd($aonkI_sCOi4`1KCUFQEm0{cDIu`YYZU+h002ovPDHLkV1i?1qF(?2 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..031c178dfbabe7feed4852fec29325850f192429 GIT binary patch literal 3500 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..af807fb9c4f83e2f77140c3e5dc9b735b4b8925a GIT binary patch literal 4782 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..73a2efa6c90db8dda1823d9a65f73fa4ae27af17 GIT binary patch literal 7235 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 RkAwgK002ovPDHLkV1jtt!$|-D literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..f90e58dd0e36ffe4546ea2a52b7a44a90f411f30 GIT binary patch literal 5293 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..338a2d3dc0355d7b0f8ea520b5b1112fbb9f066c GIT binary patch literal 10154 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 L25Jo|b`k#%nW7$> literal 0 HcmV?d00001 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml new file mode 100644 index 0000000..515084c --- /dev/null +++ b/app/src/main/res/values/arrays.xml @@ -0,0 +1,21 @@ + + + + + 1 minute + 2 minutes + 3 minutes + 5 minutes + 10 minutes + 15 minutes + + + + 1 + 2 + 3 + 5 + 10 + 15 + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..ef9f303 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,16 @@ + + + #0081dc + #0065ac + #D81B60 + + #FFFFFF + #f3f3f3 + + @color/colorPrimary + #222222 + #ff9600 + + #7e7e7e + #4caf50 + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..70d6fed --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,21 @@ + + + 16dp + 16dp + 8dp + 176dp + 16dp + + + 4dp + 8dp + 16dp + 24dp + 32dp + 40dp + + 14dp + 46dp + + 64dp + diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..6ad2fa3 --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #F3F3F3 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..3372656 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,88 @@ + + Private Lock + Open-Source Lock Privacy + + https://github.com/wesaphzt + https://github.com/wesaphzt/PrivateLock + + + Set the lock sensitivity + High + Low + 0 + 40 + Test the lock sensitivity + → + Value: %1$s + + + Private Lock + Private Lock, the perfect companion to help protect your phone privacy and security. + Protect against theft + If someone takes your phone while you\'re using it, your phone is unlocked and all your private data is up for grabs. + Always running + Should something happen, your phone will be quickly locked, dependent on the sensitivity you\'ve set. + + + Start + Stop + Settings + Donate + Show Intro + About + + + Donate + Copied address + Address copied to clipboard + About + + + About overview app logo + + Contribute + Report Bugs + Report bugs or request new features + + Author image + wesaphzt + Developer + Developer + + Version + Version image + + License + GPL v3.0 + License image + + Source code + Source code image + + Bug report image + + + Bitcoin image + Litecoin image + Ethereum image + Monero image + + 1GCkvAg9oG79niQTbh6EH9rPALQDXKyHKK + LV687s3wVdhmLZyJMFxomJHdHFXeFAKT5R + 0x785a8804c85b88683a5cce5e53f60878831e5d03 + 43Vijzdt3y42mmT954rSYPjXYabDsjYEV2KyhxfC46JibR2ny9VmRS1fjdJTHxxPVPFE8ajgArwjWfyaRgjh9vcNAwmkfJj + + If you find these apps useful, consider supporting me in some way in my mission to create simple, useful, privacy-oriented, open-source apps. + Text emoji image + + + Start + Stop + + SERVICE_STATUS + Widget padlock image + + + lock_notification_channel_id + Lock Notification Service + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..545b9c6 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,20 @@ + + + + + + + +