summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorTyler Nijmeh <tylernij@gmail.com>2021-03-30 19:43:10 -0700
committerTyler Nijmeh <tylernij@gmail.com>2021-03-30 19:43:10 -0700
commit3636c8c51cc9221db8ef4ade6c4231b68bd553ba (patch)
treef0fc5675e508a13bcae5414b7ce70311449a8dd4 /app
parent00acb7483a1c207670062d15991a82266b91735c (diff)
Add permission validation
Signed-off-by: Tyler Nijmeh <tylernij@gmail.com>
Diffstat (limited to 'app')
-rw-r--r--app/build.gradle16
-rw-r--r--app/src/main/AndroidManifest.xml11
-rw-r--r--app/src/main/java/com/draco/buoy/MainActivity.kt11
-rw-r--r--app/src/main/java/com/draco/buoy/utils/PermissionUtils.kt11
-rw-r--r--app/src/main/java/com/draco/buoy/viewmodels/MainActivityViewModel.kt7
-rw-r--r--app/src/main/java/com/draco/buoy/viewmodels/PermissionActivityViewModel.kt48
-rw-r--r--app/src/main/java/com/draco/buoy/views/MainActivity.kt28
-rw-r--r--app/src/main/java/com/draco/buoy/views/PermissionActivity.kt41
-rw-r--r--app/src/main/res/layout/activity_main.xml18
-rw-r--r--app/src/main/res/layout/activity_permission.xml50
-rw-r--r--app/src/main/res/values/strings.xml11
11 files changed, 221 insertions, 31 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 73089a1..7ab5e86 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -9,7 +9,7 @@ android {
defaultConfig {
applicationId "com.draco.buoy"
- minSdk 21
+ minSdk 23
targetSdk 30
versionCode 1
versionName "1.0"
@@ -19,7 +19,8 @@ android {
buildTypes {
release {
- minifyEnabled false
+ minifyEnabled true
+ shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
@@ -37,7 +38,16 @@ dependencies {
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
+
+ implementation 'androidx.preference:preference-ktx:1.1.1'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
+
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
+
+ implementation 'com.google.android.gms:play-services-oss-licenses:17.0.0'
+
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7cbf35d..1f0e401 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,23 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
package="com.draco.buoy">
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"
+ tools:ignore="ProtectedPermissions" />
+
<application
android:allowBackup="true"
+ android:fullBackupContent="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Buoy">
<activity
- android:name=".MainActivity"
+ android:name=".views.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
-
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+
+ <activity android:name=".views.PermissionActivity"
+ android:label="@string/title_permission"/>
</application>
</manifest> \ No newline at end of file
diff --git a/app/src/main/java/com/draco/buoy/MainActivity.kt b/app/src/main/java/com/draco/buoy/MainActivity.kt
deleted file mode 100644
index 18eb9db..0000000
--- a/app/src/main/java/com/draco/buoy/MainActivity.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.draco.buoy
-
-import androidx.appcompat.app.AppCompatActivity
-import android.os.Bundle
-
-class MainActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- }
-} \ No newline at end of file
diff --git a/app/src/main/java/com/draco/buoy/utils/PermissionUtils.kt b/app/src/main/java/com/draco/buoy/utils/PermissionUtils.kt
new file mode 100644
index 0000000..13dc385
--- /dev/null
+++ b/app/src/main/java/com/draco/buoy/utils/PermissionUtils.kt
@@ -0,0 +1,11 @@
+package com.draco.buoy.utils
+
+import android.content.Context
+import android.content.pm.PackageManager
+
+class PermissionUtils {
+ companion object {
+ fun isPermissionsGranted(context: Context, permission: String): Boolean =
+ context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/com/draco/buoy/viewmodels/MainActivityViewModel.kt b/app/src/main/java/com/draco/buoy/viewmodels/MainActivityViewModel.kt
new file mode 100644
index 0000000..443b494
--- /dev/null
+++ b/app/src/main/java/com/draco/buoy/viewmodels/MainActivityViewModel.kt
@@ -0,0 +1,7 @@
+package com.draco.buoy.viewmodels
+
+import android.app.Application
+import androidx.lifecycle.AndroidViewModel
+
+class MainActivityViewModel(application: Application) : AndroidViewModel(application) {
+} \ No newline at end of file
diff --git a/app/src/main/java/com/draco/buoy/viewmodels/PermissionActivityViewModel.kt b/app/src/main/java/com/draco/buoy/viewmodels/PermissionActivityViewModel.kt
new file mode 100644
index 0000000..7ee2e58
--- /dev/null
+++ b/app/src/main/java/com/draco/buoy/viewmodels/PermissionActivityViewModel.kt
@@ -0,0 +1,48 @@
+package com.draco.buoy.viewmodels
+
+import android.app.Application
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.viewModelScope
+import com.draco.buoy.utils.PermissionUtils
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+class PermissionActivityViewModel(application: Application) : AndroidViewModel(application) {
+ private val _permissionGranted = MutableLiveData(false)
+ val permissionGranted: LiveData<Boolean> = _permissionGranted
+
+ private fun askRootPermission() {
+ try {
+ ProcessBuilder(
+ "su",
+ "-c",
+ "pm grant com.draco.purr android.permission.WRITE_SECURE_SETTINGS"
+ ).start()
+ } catch (_: Exception) {}
+ }
+
+ private fun isWriteSecureSettingsPermissionGranted(): Boolean {
+ val context = getApplication<Application>().applicationContext
+ return PermissionUtils.isPermissionsGranted(context, android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ }
+
+ private fun startPermissionCheckLoop() {
+ viewModelScope.launch(Dispatchers.IO) {
+ while (!isWriteSecureSettingsPermissionGranted())
+ delay(100)
+ _permissionGranted.postValue(true)
+ }
+ }
+
+ init {
+ if (!isWriteSecureSettingsPermissionGranted()) {
+ viewModelScope.launch(Dispatchers.IO) {
+ askRootPermission()
+ }
+ startPermissionCheckLoop()
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/com/draco/buoy/views/MainActivity.kt b/app/src/main/java/com/draco/buoy/views/MainActivity.kt
new file mode 100644
index 0000000..10a56b9
--- /dev/null
+++ b/app/src/main/java/com/draco/buoy/views/MainActivity.kt
@@ -0,0 +1,28 @@
+package com.draco.buoy.views
+
+import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import androidx.activity.viewModels
+import com.draco.buoy.R
+import com.draco.buoy.utils.PermissionUtils
+import com.draco.buoy.viewmodels.MainActivityViewModel
+
+class MainActivity : AppCompatActivity() {
+ private val viewModel: MainActivityViewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ if (!PermissionUtils.isPermissionsGranted(this, android.Manifest.permission.WRITE_SECURE_SETTINGS)) {
+ goToPermissionActivity()
+ return
+ }
+ }
+
+ private fun goToPermissionActivity() {
+ val intent = Intent(this, PermissionActivity::class.java)
+ startActivity(intent)
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/com/draco/buoy/views/PermissionActivity.kt b/app/src/main/java/com/draco/buoy/views/PermissionActivity.kt
new file mode 100644
index 0000000..d3b8b62
--- /dev/null
+++ b/app/src/main/java/com/draco/buoy/views/PermissionActivity.kt
@@ -0,0 +1,41 @@
+package com.draco.buoy.views
+
+import android.content.ClipData
+import android.content.ClipboardManager
+import android.content.Context
+import android.os.Bundle
+import android.widget.TextView
+import androidx.activity.viewModels
+import androidx.appcompat.app.AppCompatActivity
+import com.draco.buoy.R
+import com.draco.buoy.viewmodels.PermissionActivityViewModel
+import com.google.android.material.snackbar.Snackbar
+
+class PermissionActivity : AppCompatActivity() {
+ private val viewModel: PermissionActivityViewModel by viewModels()
+
+ private lateinit var command: TextView
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_permission)
+
+ command = findViewById(R.id.command)
+
+ command.setOnClickListener {
+ val clipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
+ val clip = ClipData.newPlainText("ADB Command", command.text.toString())
+ clipboardManager.setPrimaryClip(clip)
+
+ Snackbar.make(command, R.string.copied, Snackbar.LENGTH_SHORT).show()
+ }
+
+ viewModel.permissionGranted.observe(this) {
+ if (it == true)
+ finish()
+ }
+ }
+
+ /* Disallow exit */
+ override fun onBackPressed() {}
+} \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 4fc2444..24f3d6b 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,18 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".MainActivity">
+ android:layout_height="match_parent">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Hello World!"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintLeft_toLeftOf="parent"
- app:layout_constraintRight_toRightOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
-
-</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file
+</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_permission.xml b/app/src/main/res/layout/activity_permission.xml
new file mode 100644
index 0000000..48d4702
--- /dev/null
+++ b/app/src/main/res/layout/activity_permission.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="24dp"
+ android:orientation="vertical">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/TextAppearance.MaterialComponents.Headline2"
+ android:text="@string/permission_title" />
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="32dp"
+ style="@style/TextAppearance.MaterialComponents.Headline5"
+ android:text="@string/permission_message" />
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="32dp"
+ android:id="@+id/command"
+ android:fontFamily="monospace"
+ android:text="@string/permission_command" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="24dp"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:layout_alignParentBottom="true">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginVertical="12dp"
+ style="@style/TextAppearance.MaterialComponents.Caption"
+ android:text="@string/please_wait" />
+ <ProgressBar
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:indeterminate="true"
+ android:layout_marginHorizontal="64dp"
+ style="@style/Widget.AppCompat.ProgressBar.Horizontal" />
+ </LinearLayout>
+</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 36f5960..619b965 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,14 @@
<resources>
<string name="app_name">Buoy</string>
+
+ <string name="title_permission">Permissions</string>
+
+ <string name="permission_title">Woah there!</string>
+ <string name="permission_message">We need a special permission to continue. Use ADB to run the following command (one line):</string>
+ <string name="permission_command">adb shell pm grant com.draco.buoy android.permission.WRITE_SECURE_SETTINGS</string>
+
+ <string name="please_wait">Waiting for permission</string>
+ <string name="copied">Copied to clipboard</string>
+
+ <string name="snackbar_intent_failed">Could not handle this action</string>
</resources> \ No newline at end of file