diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 44bc16f..41478fd 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -4,6 +4,10 @@ on:
push:
paths-ignore:
- '**.md'
+ tags-ignore:
+ - '**'
+ branches-ignore:
+ - 'master'
jobs:
build:
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 479ce08..0506601 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -52,13 +52,24 @@
android:windowSoftInputMode="adjustResize|stateHidden"
android:theme="@style/Theme.OwnDroid">
+
+
+
+
+
+ android:theme="@style/Theme.Transparent">
@@ -95,6 +106,13 @@
android:name=".StopLockTaskModeReceiver"
android:description="@string/app_name">
+
+
+
+
+
finish() }
+ .show()
+ }
+ } else {
+ finish()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bintianqi/owndroid/AutomationReceiver.kt b/app/src/main/java/com/bintianqi/owndroid/AutomationReceiver.kt
new file mode 100644
index 0000000..ee32652
--- /dev/null
+++ b/app/src/main/java/com/bintianqi/owndroid/AutomationReceiver.kt
@@ -0,0 +1,48 @@
+package com.bintianqi.owndroid
+
+import android.annotation.SuppressLint
+import android.app.admin.DevicePolicyManager
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import androidx.activity.ComponentActivity
+
+class AutomationReceiver: BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ handleTask(context, intent)
+ }
+}
+
+@SuppressLint("NewApi")
+fun handleTask(context: Context, intent: Intent): String {
+ val sharedPrefs = context.getSharedPreferences("data", Context.MODE_PRIVATE)
+ val key = sharedPrefs.getString("automation_key", "") ?: ""
+ if(key.length < 6) {
+ return "Key length must longer than 6"
+ }
+ if(key != intent.getStringExtra("key")) {
+ return "Wrong key"
+ }
+ val operation = intent.getStringExtra("operation")
+ val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
+ val receiver = ComponentName(context,Receiver::class.java)
+ val app = intent.getStringExtra("app")
+ val restriction = intent.getStringExtra("restriction")
+ try {
+ when(operation) {
+ "suspend" -> dpm.setPackagesSuspended(receiver, arrayOf(app), true)
+ "unsuspend" -> dpm.setPackagesSuspended(receiver, arrayOf(app), false)
+ "hide" -> dpm.setApplicationHidden(receiver, app, true)
+ "unhide" -> dpm.setApplicationHidden(receiver, app, false)
+ "lock" -> dpm.lockNow()
+ "reboot" -> dpm.reboot(receiver)
+ "addUserRestriction" -> dpm.addUserRestriction(receiver, restriction)
+ "clearUserRestriction" -> dpm.clearUserRestriction(receiver, restriction)
+ else -> return "Operation not defined"
+ }
+ } catch(e: Exception) {
+ return e.message ?: "Failed to get error message"
+ }
+ return "No error, or error is unhandled"
+}
diff --git a/app/src/main/java/com/bintianqi/owndroid/Setting.kt b/app/src/main/java/com/bintianqi/owndroid/Setting.kt
index a5ef2f9..e0ed1bc 100644
--- a/app/src/main/java/com/bintianqi/owndroid/Setting.kt
+++ b/app/src/main/java/com/bintianqi/owndroid/Setting.kt
@@ -4,13 +4,16 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build.VERSION
+import android.widget.Toast
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
+import androidx.compose.material3.TextField
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
@@ -43,6 +46,7 @@ fun AppSetting(navCtrl:NavHostController, materialYou: MutableState, bl
composable(route = "Home") { Home(localNavCtrl) }
composable(route = "Theme") { ThemeSettings(materialYou, blackTheme) }
composable(route = "Auth") { AuthSettings() }
+ composable(route = "Automation") { Automation() }
composable(route = "About") { About() }
}
}
@@ -53,6 +57,7 @@ private fun Home(navCtrl: NavHostController) {
Column(modifier = Modifier.fillMaxSize()) {
SubPageItem(R.string.theme, "", R.drawable.format_paint_fill0) { navCtrl.navigate("Theme") }
SubPageItem(R.string.security, "", R.drawable.lock_fill0) { navCtrl.navigate("Auth") }
+ SubPageItem(R.string.automation_api, "", R.drawable.apps_fill0) { navCtrl.navigate("Automation") }
SubPageItem(R.string.about, "", R.drawable.info_fill0) { navCtrl.navigate("About") }
}
}
@@ -122,6 +127,36 @@ private fun AuthSettings() {
}
}
+@Composable
+private fun Automation() {
+ val context = LocalContext.current
+ val sharedPref = context.getSharedPreferences("data", Context.MODE_PRIVATE)
+ Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())) {
+ Spacer(Modifier.padding(vertical = 10.dp))
+ Text(text = stringResource(R.string.automation_api), style = typography.headlineLarge)
+ Spacer(Modifier.padding(vertical = 5.dp))
+ var key by remember { mutableStateOf("") }
+ TextField(
+ value = key, onValueChange = { key = it }, label = { Text("Key")},
+ modifier = Modifier.fillMaxWidth()
+ )
+ Button(
+ modifier = Modifier.fillMaxWidth(),
+ onClick = {
+ sharedPref.edit().putString("automation_key", key).apply()
+ Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
+ }
+ ) {
+ Text(stringResource(R.string.apply))
+ }
+ SwitchItem(
+ R.string.automation_debug, "", null,
+ { sharedPref.getBoolean("automation_debug", false) },
+ { sharedPref.edit().putBoolean("automation_debug", it).apply() }
+ )
+ }
+}
+
@Composable
private fun About() {
val context = LocalContext.current
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index f0456df..cf45513 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -543,6 +543,9 @@
清除存储空间
清除存储空间成功\n应用即将退出
+ 自动化API
+ 调试模式
+
读取外部存储
写入外部存储
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 66e01d6..d3e0c89 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -559,6 +559,9 @@
Clear storage
Clear storage success\nApplication will exit
+ Automation API
+ Debug mode
+
Read external storage
Write external storage
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 83f2a43..7ed11ac 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -4,7 +4,7 @@
- #FFFFFF
- #FFFFFF
-