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 -