Update README

Use Compose AlertDialog instead android.app.AlertDialog
Set default affiliation id after activation
The 'dev' branch will be deleted, use 'master' instead
This commit is contained in:
BinTianqi
2025-03-08 18:08:24 +08:00
parent f399866944
commit ada12bf3dc
10 changed files with 57 additions and 38 deletions

View File

@@ -3,7 +3,6 @@ name: Build APK
on: on:
workflow_dispatch: workflow_dispatch:
push: push:
branches: ["master", "dev"]
paths-ignore: paths-ignore:
- '**.md' - '**.md'
tags-ignore: tags-ignore:
@@ -63,13 +62,11 @@ jobs:
path: app/build/outputs/apk/release/app-release.apk path: app/build/outputs/apk/release/app-release.apk
- name: Generate and submit dependency graph - name: Generate and submit dependency graph
if: github.ref_name == 'master'
uses: gradle/actions/dependency-submission@v4 uses: gradle/actions/dependency-submission@v4
upload-telegram: upload-telegram:
name: Upload Builds name: Upload Builds
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.ref_name == 'dev'
needs: build needs: build
steps: steps:
- name: Download Artifacts - name: Download Artifacts

View File

@@ -6,8 +6,8 @@ Use Android Device owner privilege to manage your device.
## Download ## Download
[IzzyOnDroid F-Droid Repository](https://apt.izzysoft.de/fdroid/index/apk/com.bintianqi.owndroid) - [IzzyOnDroid F-Droid Repository](https://apt.izzysoft.de/fdroid/index/apk/com.bintianqi.owndroid)
[Releases on GitHub](https://github.com/BinTianqi/OwnDroid/releases) - [Releases on GitHub](https://github.com/BinTianqi/OwnDroid/releases)
> [!NOTE] > [!NOTE]
> ColorOS users should download testkey version from releases on GitHub > ColorOS users should download testkey version from releases on GitHub
@@ -16,7 +16,6 @@ Use Android Device owner privilege to manage your device.
- System - System
- Options: disable camera, disable screenshot, master volume mute, disable USB signal... - Options: disable camera, disable screenshot, master volume mute, disable USB signal...
- Permission policy
- Manage CA certificates - Manage CA certificates
- _Wipe data_ - _Wipe data_
- ... - ...
@@ -35,6 +34,7 @@ Use Android Device owner privilege to manage your device.
- Suspend/hide app - Suspend/hide app
- Block app uninstallation - Block app uninstallation
- Install/uninstall app - Install/uninstall app
- Grant/revoke permissions
- ... - ...
- User restriction - User restriction
- Network: disable configuring mobile network, disable configuring Wi-Fi, disable SMS, disable outgoing calls... - Network: disable configuring mobile network, disable configuring Wi-Fi, disable SMS, disable outgoing calls...

View File

@@ -6,8 +6,8 @@ AndroidのDevice owner特権を使用してデバイスを管理します。
## ダウンロード ## ダウンロード
[IzzyOnDroid F-Droid Repository](https://apt.izzysoft.de/fdroid/index/apk/com.bintianqi.owndroid) - [IzzyOnDroid F-Droid Repository](https://apt.izzysoft.de/fdroid/index/apk/com.bintianqi.owndroid)
[Releases on GitHub](https://github.com/BinTianqi/OwnDroid/releases) - [Releases on GitHub](https://github.com/BinTianqi/OwnDroid/releases)
> [!NOTE] > [!NOTE]
> ColorOSユーザーはGitHubのリリースからtestkeyバージョンをダウンロードしてください > ColorOSユーザーはGitHubのリリースからtestkeyバージョンをダウンロードしてください

View File

@@ -6,8 +6,8 @@
## 下载 ## 下载
[IzzyOnDroid F-Droid Repository](https://apt.izzysoft.de/fdroid/index/apk/com.bintianqi.owndroid) - [IzzyOnDroid F-Droid Repository](https://apt.izzysoft.de/fdroid/index/apk/com.bintianqi.owndroid)
[Releases on GitHub](https://github.com/BinTianqi/OwnDroid/releases) - [Releases on GitHub](https://github.com/BinTianqi/OwnDroid/releases)
> [!NOTE] > [!NOTE]
> ColorOS用户应在GitHub上的releases下载testkey版本 > ColorOS用户应在GitHub上的releases下载testkey版本
@@ -16,7 +16,6 @@
- 系统 - 系统
- 选项禁用摄像头、禁止截屏、全局静音、禁用USB信号... - 选项禁用摄像头、禁止截屏、全局静音、禁用USB信号...
- 权限策略
- 管理CA证书 - 管理CA证书
- _清除数据_ - _清除数据_
- ... - ...
@@ -35,6 +34,7 @@
- 挂起/隐藏应用 - 挂起/隐藏应用
- 阻止应用卸载 - 阻止应用卸载
- 安装/卸载应用 - 安装/卸载应用
- 授予/撤销权限
- ... - ...
- 用户限制 - 用户限制
- 网络禁止配置移动网络、禁止配置Wi-Fi、禁用短信、禁止拨出电话... - 网络禁止配置移动网络、禁止配置Wi-Fi、禁用短信、禁止拨出电话...

View File

@@ -14,6 +14,7 @@ import com.bintianqi.owndroid.dpm.handleNetworkLogs
import com.bintianqi.owndroid.dpm.isDeviceOwner import com.bintianqi.owndroid.dpm.isDeviceOwner
import com.bintianqi.owndroid.dpm.isProfileOwner import com.bintianqi.owndroid.dpm.isProfileOwner
import com.bintianqi.owndroid.dpm.processSecurityLogs import com.bintianqi.owndroid.dpm.processSecurityLogs
import com.bintianqi.owndroid.dpm.setDefaultAffiliationID
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -34,6 +35,7 @@ class Receiver : DeviceAdminReceiver() {
override fun onEnabled(context: Context, intent: Intent) { override fun onEnabled(context: Context, intent: Intent) {
super.onEnabled(context, intent) super.onEnabled(context, intent)
if(context.isProfileOwner || context.isDeviceOwner){ if(context.isProfileOwner || context.isDeviceOwner){
setDefaultAffiliationID(context)
Toast.makeText(context, context.getString(R.string.onEnabled), Toast.LENGTH_SHORT).show() Toast.makeText(context, context.getString(R.string.onEnabled), Toast.LENGTH_SHORT).show()
} }
} }
@@ -41,6 +43,7 @@ class Receiver : DeviceAdminReceiver() {
override fun onDisabled(context: Context, intent: Intent) { override fun onDisabled(context: Context, intent: Intent) {
super.onDisabled(context, intent) super.onDisabled(context, intent)
Toast.makeText(context, R.string.onDisabled, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.onDisabled, Toast.LENGTH_SHORT).show()
SharedPrefs(context).isDefaultAffiliationIdSet = false
} }
override fun onProfileProvisioningComplete(context: Context, intent: Intent) { override fun onProfileProvisioningComplete(context: Context, intent: Intent) {

View File

@@ -1,6 +1,5 @@
package com.bintianqi.owndroid.dpm package com.bintianqi.owndroid.dpm
import android.app.AlertDialog
import android.app.PendingIntent import android.app.PendingIntent
import android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT import android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT
import android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED import android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED
@@ -91,9 +90,9 @@ import com.bintianqi.owndroid.R
import com.bintianqi.owndroid.showOperationResultToast import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.Animations import com.bintianqi.owndroid.ui.Animations
import com.bintianqi.owndroid.ui.FunctionItem import com.bintianqi.owndroid.ui.FunctionItem
import com.bintianqi.owndroid.ui.Notes
import com.bintianqi.owndroid.ui.ListItem import com.bintianqi.owndroid.ui.ListItem
import com.bintianqi.owndroid.ui.NavIcon import com.bintianqi.owndroid.ui.NavIcon
import com.bintianqi.owndroid.ui.Notes
import com.bintianqi.owndroid.ui.RadioButtonItem import com.bintianqi.owndroid.ui.RadioButtonItem
import com.bintianqi.owndroid.ui.SwitchItem import com.bintianqi.owndroid.ui.SwitchItem
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@@ -901,6 +900,7 @@ private fun KeepUninstalledPackagesScreen(pkgName: String) {
@Composable @Composable
private fun UninstallPackageScreen(pkgName: String) { private fun UninstallPackageScreen(pkgName: String) {
val context = LocalContext.current val context = LocalContext.current
var errorMessage by remember { mutableStateOf<String?>(null) }
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())) { Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())) {
Spacer(Modifier.padding(vertical = 10.dp)) Spacer(Modifier.padding(vertical = 10.dp))
Text(text = stringResource(R.string.uninstall_app), style = typography.headlineLarge) Text(text = stringResource(R.string.uninstall_app), style = typography.headlineLarge)
@@ -919,11 +919,7 @@ private fun UninstallPackageScreen(pkgName: String) {
if(statusExtra == PackageInstaller.STATUS_SUCCESS) { if(statusExtra == PackageInstaller.STATUS_SUCCESS) {
context.showOperationResultToast(true) context.showOperationResultToast(true)
} else { } else {
AlertDialog.Builder(context) errorMessage = parsePackageInstallerMessage(context, intent)
.setTitle(R.string.failure)
.setMessage(parsePackageInstallerMessage(context, intent))
.setPositiveButton(R.string.confirm) { dialog, _ -> dialog.dismiss() }
.show()
} }
} }
} }
@@ -960,5 +956,13 @@ private fun UninstallPackageScreen(pkgName: String) {
} }
} }
} }
if(errorMessage != null) AlertDialog(
title = { Text(stringResource(R.string.failure)) },
text = { Text(errorMessage!!) },
confirmButton = {
TextButton({ errorMessage = null }) { Text(stringResource(R.string.confirm)) }
},
onDismissRequest = { errorMessage = null }
)
} }

View File

@@ -2,7 +2,6 @@ package com.bintianqi.owndroid.dpm
import android.Manifest import android.Manifest
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.AlertDialog
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OFF import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OFF
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OPPORTUNISTIC import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OPPORTUNISTIC
import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME import android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME
@@ -133,14 +132,15 @@ import com.bintianqi.owndroid.humanReadableDate
import com.bintianqi.owndroid.humanReadableDateTime import com.bintianqi.owndroid.humanReadableDateTime
import com.bintianqi.owndroid.showOperationResultToast import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CheckBoxItem import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.ErrorDialog
import com.bintianqi.owndroid.ui.ExpandExposedTextFieldIcon import com.bintianqi.owndroid.ui.ExpandExposedTextFieldIcon
import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem
import com.bintianqi.owndroid.ui.FunctionItem import com.bintianqi.owndroid.ui.FunctionItem
import com.bintianqi.owndroid.ui.Notes
import com.bintianqi.owndroid.ui.ListItem import com.bintianqi.owndroid.ui.ListItem
import com.bintianqi.owndroid.ui.MyScaffold import com.bintianqi.owndroid.ui.MyScaffold
import com.bintianqi.owndroid.ui.MySmallTitleScaffold import com.bintianqi.owndroid.ui.MySmallTitleScaffold
import com.bintianqi.owndroid.ui.NavIcon import com.bintianqi.owndroid.ui.NavIcon
import com.bintianqi.owndroid.ui.Notes
import com.bintianqi.owndroid.ui.RadioButtonItem import com.bintianqi.owndroid.ui.RadioButtonItem
import com.bintianqi.owndroid.ui.SwitchItem import com.bintianqi.owndroid.ui.SwitchItem
import com.bintianqi.owndroid.writeClipBoard import com.bintianqi.owndroid.writeClipBoard
@@ -507,6 +507,7 @@ private fun AddNetworkScreen(wifiConfig: WifiConfiguration? = null, onNavigateUp
ssid = wifiConfig.SSID.removeSurrounding("\"") ssid = wifiConfig.SSID.removeSurrounding("\"")
} }
} }
var errorMessage by remember { mutableStateOf<String?>(null) }
Column( Column(
modifier = (if(wifiConfig == null) Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(bottom = 60.dp) else Modifier) modifier = (if(wifiConfig == null) Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(bottom = 60.dp) else Modifier)
.padding(start = 8.dp, end = 8.dp, top = 12.dp) .padding(start = 8.dp, end = 8.dp, top = 12.dp)
@@ -721,11 +722,7 @@ private fun AddNetworkScreen(wifiConfig: WifiConfiguration? = null, onNavigateUp
resultDialog = true resultDialog = true
} catch(e: Exception) { } catch(e: Exception) {
e.printStackTrace() e.printStackTrace()
AlertDialog.Builder(context) errorMessage = e.message
.setTitle(R.string.error)
.setPositiveButton(R.string.confirm) { dialog, _ -> dialog.cancel() }
.setMessage(e.message ?: "")
.show()
} }
}, },
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp) modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)
@@ -755,6 +752,7 @@ private fun AddNetworkScreen(wifiConfig: WifiConfiguration? = null, onNavigateUp
onDismissRequest = { resultDialog = false } onDismissRequest = { resultDialog = false }
) )
} }
ErrorDialog(errorMessage) { errorMessage = null }
} }
@Serializable object WifiSecurityLevel @Serializable object WifiSecurityLevel
@@ -914,6 +912,7 @@ fun NetworkStatsScreen(onNavigateUp: () -> Unit, onNavigateToViewer: (NetworkSta
val endTimeTextFieldInteractionSource = remember { MutableInteractionSource() } val endTimeTextFieldInteractionSource = remember { MutableInteractionSource() }
if(startTimeTextFieldInteractionSource.collectIsPressedAsState().value) activeTextField = NetworkStatsActiveTextField.StartTime if(startTimeTextFieldInteractionSource.collectIsPressedAsState().value) activeTextField = NetworkStatsActiveTextField.StartTime
if(endTimeTextFieldInteractionSource.collectIsPressedAsState().value) activeTextField = NetworkStatsActiveTextField.EndTime if(endTimeTextFieldInteractionSource.collectIsPressedAsState().value) activeTextField = NetworkStatsActiveTextField.EndTime
var errorMessage by remember { mutableStateOf<String?>(null) }
MyScaffold(R.string.network_stats, 8.dp, onNavigateUp) { MyScaffold(R.string.network_stats, 8.dp, onNavigateUp) {
ExposedDropdownMenuBox( ExposedDropdownMenuBox(
activeTextField == NetworkStatsActiveTextField.Type, activeTextField == NetworkStatsActiveTextField.Type,
@@ -1202,14 +1201,10 @@ fun NetworkStatsScreen(onNavigateUp: () -> Unit, onNavigateToViewer: (NetworkSta
e.printStackTrace() e.printStackTrace()
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
querying = false querying = false
AlertDialog.Builder(context) errorMessage = e.message
.setTitle(R.string.error)
.setMessage(e.message ?: "")
.setPositiveButton(R.string.confirm) { dialog, _ -> dialog.dismiss() }
.show()
} }
return@launch return@launch
} }.filterNot { it == null }
if(buckets.isEmpty()) { if(buckets.isEmpty()) {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
querying = false querying = false
@@ -1263,6 +1258,7 @@ fun NetworkStatsScreen(onNavigateUp: () -> Unit, onNavigateToViewer: (NetworkSta
} }
} }
} }
ErrorDialog(errorMessage) { errorMessage = null }
} }
@Serializable @Serializable

View File

@@ -2,7 +2,6 @@ package com.bintianqi.owndroid.dpm
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.ActivityOptions import android.app.ActivityOptions
import android.app.AlertDialog
import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManager
import android.app.admin.DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY import android.app.admin.DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY
import android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback import android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback
@@ -126,6 +125,7 @@ import com.bintianqi.owndroid.humanReadableDate
import com.bintianqi.owndroid.parseDate import com.bintianqi.owndroid.parseDate
import com.bintianqi.owndroid.showOperationResultToast import com.bintianqi.owndroid.showOperationResultToast
import com.bintianqi.owndroid.ui.CheckBoxItem import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.ErrorDialog
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem
import com.bintianqi.owndroid.ui.FunctionItem import com.bintianqi.owndroid.ui.FunctionItem
@@ -286,7 +286,7 @@ fun SystemOptionsScreen(onNavigateUp: () -> Unit) {
} }
} }
if(deviceOwner || profileOwner) { if(deviceOwner || profileOwner) {
SwitchItem(R.string.master_mute, icon = R.drawable.volume_up_fill0, SwitchItem(R.string.master_mute, icon = R.drawable.volume_off_fill0,
getState = { dpm.isMasterVolumeMuted(receiver) }, onCheckedChange = { dpm.setMasterVolumeMuted(receiver,it) } getState = { dpm.isMasterVolumeMuted(receiver) }, onCheckedChange = { dpm.setMasterVolumeMuted(receiver,it) }
) )
} }
@@ -1197,6 +1197,7 @@ private fun ColumnScope.LockTaskFeatures() {
val receiver = context.getReceiver() val receiver = context.getReceiver()
var flags by remember { mutableIntStateOf(0) } var flags by remember { mutableIntStateOf(0) }
var custom by rememberSaveable { mutableStateOf(false) } var custom by rememberSaveable { mutableStateOf(false) }
var errorMessage by remember { mutableStateOf<String?>(null) }
fun refresh() { fun refresh() {
flags = dpm.getLockTaskFeatures(receiver) flags = dpm.getLockTaskFeatures(receiver)
custom = flags != 0 custom = flags != 0
@@ -1230,17 +1231,14 @@ private fun ColumnScope.LockTaskFeatures() {
dpm.setLockTaskFeatures(receiver, flags) dpm.setLockTaskFeatures(receiver, flags)
context.showOperationResultToast(true) context.showOperationResultToast(true)
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
AlertDialog.Builder(context) errorMessage = e.message
.setTitle(R.string.error)
.setMessage(e.message)
.setPositiveButton(R.string.confirm) { dialog, _ -> dialog.dismiss() }
.show()
} }
refresh() refresh()
} }
) { ) {
Text(stringResource(R.string.apply)) Text(stringResource(R.string.apply))
} }
ErrorDialog(errorMessage) { errorMessage = null }
} }
data class CaCertInfo( data class CaCertInfo(

View File

@@ -357,3 +357,15 @@ fun ExpandExposedTextFieldIcon(active: Boolean) {
modifier = Modifier.rotate(degrees) modifier = Modifier.rotate(degrees)
) )
} }
@Composable
fun ErrorDialog(message: String?, onDismiss: () -> Unit) {
if(!message.isNullOrEmpty()) AlertDialog(
title = { Text(stringResource(R.string.error)) },
text = { Text(message) },
confirmButton = {
TextButton(onDismiss) { Text(stringResource(R.string.confirm)) }
},
onDismissRequest = onDismiss
)
}

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="M792,904 L671,783q-25,16 -53,27.5T560,829v-82q14,-5 27.5,-10t25.5,-12L480,592v208L280,600L120,600v-240h128L56,168l56,-56 736,736 -56,56ZM784,672 L726,614q17,-31 25.5,-65t8.5,-70q0,-94 -55,-168T560,211v-82q124,28 202,125.5T840,479q0,53 -14.5,102T784,672ZM650,538l-90,-90v-130q47,22 73.5,66t26.5,96q0,15 -2.5,29.5T650,538ZM480,368 L376,264l104,-104v208ZM400,606v-94l-72,-72L200,440v80h114l86,86ZM364,476Z"
android:fillColor="#000000"/>
</vector>