diff --git a/Readme.md b/Readme.md
index 00c992f..21b5644 100644
--- a/Readme.md
+++ b/Readme.md
@@ -13,10 +13,12 @@
适配了一些预见式返回动画(需安卓13或14),可能不太稳定,如果有问题请向我反馈
- 设备控制
+ - 重启、锁屏
- 禁用相机
- 禁止截屏
- 全局静音
- 关闭USB信号(需设备支持)
+ - 设置时间
- 管理系统更新策略
- 清除数据
- 管理应用
@@ -49,9 +51,9 @@
### 即将加入的功能
- Managed Profile,工作资料和多用户相关
-- 应用管理--安装/卸载应用
-- 应用管理--包选择器(目前只能手动输入包名)
-- 用户管理--用户选择器(目前只能手动输入序列号)
+- ~~应用管理:安装/卸载应用~~(暂不考虑)
+- 应用管理:包选择器(目前只能手动输入包名)
+- 用户管理:用户选择器(目前只能手动输入序列号)
### 许可证
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 4a88355..c097f3a 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -11,8 +11,8 @@ android {
applicationId = "com.binbin.androidowner"
minSdk = 21
targetSdk = 34
- versionCode = 10
- versionName = "2.3"
+ versionCode = 11
+ versionName = "2.4"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 05dac6e..34c175c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -13,6 +13,7 @@
+
myDpm.setBluetoothContactSharingDisabled(myComponent,b)}
)
}
- if(VERSION.SDK_INT>=26&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){
- DeviceCtrlItem(R.string.network_logging,R.string.no_effect,R.drawable.wifi_fill0,
- {myDpm.isNetworkLoggingEnabled(myComponent)},{b -> myDpm.setNetworkLoggingEnabled(myComponent,b) }
- )
- }
if(VERSION.SDK_INT>=24&&isDeviceOwner(myDpm)){
DeviceCtrlItem(R.string.secure_logging,R.string.no_effect,R.drawable.description_fill0,
{myDpm.isSecurityLoggingEnabled(myComponent)},{b -> myDpm.setSecurityLoggingEnabled(myComponent,b) }
)
}
- if(VERSION.SDK_INT>=33&&isDeviceOwner(myDpm)){
- DeviceCtrlItem(R.string.preferential_network_service,R.string.no_effect,R.drawable.globe_fill0,
- {myDpm.isPreferentialNetworkServiceEnabled},{b -> myDpm.isPreferentialNetworkServiceEnabled = b}
- )
- }
if(VERSION.SDK_INT>=30&&isDeviceOwner(myDpm)){
DeviceCtrlItem(R.string.common_criteria_mode,R.string.common_criteria_mode_desc,R.drawable.security_fill0,
{myDpm.isCommonCriteriaModeEnabled(myComponent)},{b -> myDpm.setCommonCriteriaModeEnabled(myComponent,b)}
@@ -156,11 +144,6 @@ fun DeviceControl(){
}
}
}
- if(VERSION.SDK_INT<24){ Text(text = "重启和WiFi Mac需要API24",modifier=Modifier.fillMaxWidth(), textAlign = TextAlign.Center, style = bodyTextStyle) }
- if(VERSION.SDK_INT>=24){
- val wifimac = try { myDpm.getWifiMacAddress(myComponent).toString() }catch(e:SecurityException){ "没有权限" }
- Text(text = "WiFi MAC: $wifimac",modifier=Modifier.fillMaxWidth(), textAlign = TextAlign.Center,style=bodyTextStyle)
- }
if(isDeviceOwner(myDpm)||isProfileOwner(myDpm)){
Button(
onClick = {myDpm.uninstallAllUserCaCerts(myComponent);Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()},
@@ -173,7 +156,7 @@ fun DeviceControl(){
Column(modifier = sections()){
Text(text = "修改时间", style = typography.titleLarge)
var inputTime by remember{mutableStateOf("")}
- Text(text = "从epoch(1970/1/1 00:00:00 UTC)到现在(毫秒)")
+ Text(text = "从Epoch(1970/1/1 00:00:00 UTC)到你想设置的时间(毫秒)", style = bodyTextStyle)
TextField(
value = inputTime,
label = { Text("时间(ms)")},
@@ -236,29 +219,6 @@ fun DeviceControl(){
}
}
- if(VERSION.SDK_INT>=33){
- Column(modifier = sections()){
- var selectedWifiSecLevel by remember{mutableIntStateOf(myDpm.minimumRequiredWifiSecurityLevel)}
- Text(text = "要求最小WiFi安全等级", style = typography.titleLarge, color = colorScheme.onPrimaryContainer)
- RadioButtonItem("开放", {selectedWifiSecLevel==WIFI_SECURITY_OPEN}, {selectedWifiSecLevel= WIFI_SECURITY_OPEN})
- RadioButtonItem("WEP, WPA(2)-PSK", {selectedWifiSecLevel==WIFI_SECURITY_PERSONAL}, {selectedWifiSecLevel= WIFI_SECURITY_PERSONAL})
- RadioButtonItem("WPA-EAP", {selectedWifiSecLevel==WIFI_SECURITY_ENTERPRISE_EAP}, {selectedWifiSecLevel= WIFI_SECURITY_ENTERPRISE_EAP})
- RadioButtonItem("WPA3-192bit", {selectedWifiSecLevel==WIFI_SECURITY_ENTERPRISE_192}, {selectedWifiSecLevel= WIFI_SECURITY_ENTERPRISE_192})
- Button(
- enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm),
- onClick = {
- myDpm.minimumRequiredWifiSecurityLevel=selectedWifiSecLevel
- Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
- },
- modifier = Modifier.fillMaxWidth()
- ){
- Text("应用")
- }
- }
- }else{
- Text(text = "Wifi安全等级需API33", modifier = Modifier.padding(vertical = 3.dp))
- }
-
if(VERSION.SDK_INT>=28&&isDeviceOwner(myDpm)){
Column(modifier = sections()){
val lockTaskPolicyList = mutableListOf(
@@ -335,6 +295,7 @@ fun DeviceControl(){
var listText by remember{mutableStateOf("")}
var inputPkg by remember{mutableStateOf("")}
val refreshWhitelist = {
+ inputPkg=""
listText=""
var currentItem = whitelist.size
for(each in whitelist){
@@ -354,92 +315,35 @@ fun DeviceControl(){
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
modifier = Modifier.fillMaxWidth().padding(vertical = 3.dp)
)
- Button(
- onClick = {
- focusMgr.clearFocus()
- whitelist.add(inputPkg)
- myDpm.setLockTaskPackages(myComponent,whitelist.toTypedArray())
- Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
- inputPkg=""
- refreshWhitelist()
- },
- modifier = Modifier.fillMaxWidth()
- ) {
- Text("加入白名单")
- }
- Button(
- onClick = {
- focusMgr.clearFocus()
- if(inputPkg in whitelist){
- whitelist.remove(inputPkg)
+ Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween){
+ Button(
+ onClick = {
+ focusMgr.clearFocus()
+ whitelist.add(inputPkg)
myDpm.setLockTaskPackages(myComponent,whitelist.toTypedArray())
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
- }else{
- Toast.makeText(myContext, "不存在", Toast.LENGTH_SHORT).show()
- }
- inputPkg=""
- refreshWhitelist()
- },
- modifier = Modifier.fillMaxWidth()
- ) {
- Text("从白名单中移除")
- }
- }
- }
-
- if(VERSION.SDK_INT>=29&&isDeviceOwner(myDpm)){
- Column(modifier = sections()){
- Text(text = "私人DNS", style = typography.titleLarge)
- val dnsStatus = mapOf(
- PRIVATE_DNS_MODE_UNKNOWN to "未知",
- PRIVATE_DNS_MODE_OFF to "关闭",
- PRIVATE_DNS_MODE_OPPORTUNISTIC to "自动",
- PRIVATE_DNS_MODE_PROVIDER_HOSTNAME to "指定主机名"
- )
- val operationResult = mapOf(
- PRIVATE_DNS_SET_NO_ERROR to "成功",
- PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING to "主机不支持DNS over TLS",
- PRIVATE_DNS_SET_ERROR_FAILURE_SETTING to "失败"
- )
- var status by remember{mutableStateOf(dnsStatus[myDpm.getGlobalPrivateDnsMode(myComponent)])}
- Text(text = "状态:$status")
- Button(
- onClick = {
- val result = myDpm.setGlobalPrivateDnsModeOpportunistic(myComponent)
- Toast.makeText(myContext, operationResult[result], Toast.LENGTH_SHORT).show()
- status = dnsStatus[myDpm.getGlobalPrivateDnsMode(myComponent)]
- },
- modifier = Modifier.fillMaxWidth()
- ) {
- Text("设为自动")
- }
- Spacer(Modifier.padding(vertical = 3.dp))
- var inputHost by remember{mutableStateOf(myDpm.getGlobalPrivateDnsHost(myComponent) ?: "")}
- TextField(
- value = inputHost,
- onValueChange = {inputHost=it},
- label = {Text("DNS主机名")},
- keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
- keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
- modifier = Modifier.fillMaxWidth()
- )
- Button(
- onClick = {
- val result: Int
- try{
- result = myDpm.setGlobalPrivateDnsModeSpecifiedHost(myComponent,inputHost)
- Toast.makeText(myContext, operationResult[result], Toast.LENGTH_SHORT).show()
- }catch(e:IllegalArgumentException){
- Toast.makeText(myContext, "无效主机名", Toast.LENGTH_SHORT).show()
- }catch(e:SecurityException){
- Toast.makeText(myContext, "安全错误", Toast.LENGTH_SHORT).show()
- }finally {
- status = dnsStatus[myDpm.getGlobalPrivateDnsMode(myComponent)]
- }
- },
- modifier = Modifier.fillMaxWidth()
- ) {
- Text("设置DNS主机")
+ refreshWhitelist()
+ },
+ modifier = Modifier.fillMaxWidth(0.49F)
+ ) {
+ Text("添加")
+ }
+ Button(
+ onClick = {
+ focusMgr.clearFocus()
+ if(inputPkg in whitelist){
+ whitelist.remove(inputPkg)
+ myDpm.setLockTaskPackages(myComponent,whitelist.toTypedArray())
+ Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
+ }else{
+ Toast.makeText(myContext, "不存在", Toast.LENGTH_SHORT).show()
+ }
+ refreshWhitelist()
+ },
+ modifier = Modifier.fillMaxWidth(0.96F)
+ ) {
+ Text("移除")
+ }
}
}
}
@@ -505,7 +409,7 @@ fun DeviceControl(){
}
@Composable
-private fun DeviceCtrlItem(
+fun DeviceCtrlItem(
itemName:Int,
itemDesc:Int,
leadIcon:Int,
diff --git a/app/src/main/java/com/binbin/androidowner/MainActivity.kt b/app/src/main/java/com/binbin/androidowner/MainActivity.kt
index aeceae1..75d1706 100644
--- a/app/src/main/java/com/binbin/androidowner/MainActivity.kt
+++ b/app/src/main/java/com/binbin/androidowner/MainActivity.kt
@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
+import android.os.Build.VERSION
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
@@ -67,6 +68,7 @@ fun MyScaffold(){
val topBarNameMap = mapOf(
"HomePage" to R.string.app_name,
"DeviceControl" to R.string.device_ctrl,
+ "Network" to R.string.network,
"Permissions" to R.string.permission,
"UserManage" to R.string.user_manage,
"ApplicationManage" to R.string.app_manage,
@@ -133,6 +135,7 @@ fun MyScaffold(){
composable(route = "UserManage", content = { UserManage(navCtrl)})
composable(route = "Password", content = { Password()})
composable(route = "AppSetting", content = { AppSetting(navCtrl)})
+ composable(route = "Network", content = {Network()})
}
}
}
@@ -176,6 +179,7 @@ fun HomePage(navCtrl:NavHostController){
}
}
HomePageItem(R.string.device_ctrl, R.drawable.mobile_phone_fill0, "DeviceControl", navCtrl)
+ if(VERSION.SDK_INT>=26){HomePageItem(R.string.network, R.drawable.wifi_fill0, "Network",navCtrl)}
HomePageItem(R.string.app_manage, R.drawable.apps_fill0, "ApplicationManage", navCtrl)
HomePageItem(R.string.user_restrict, R.drawable.manage_accounts_fill0, "UserRestriction", navCtrl)
HomePageItem(R.string.user_manage,R.drawable.account_circle_fill0,"UserManage",navCtrl)
diff --git a/app/src/main/java/com/binbin/androidowner/Network.kt b/app/src/main/java/com/binbin/androidowner/Network.kt
new file mode 100644
index 0000000..d2ac1fe
--- /dev/null
+++ b/app/src/main/java/com/binbin/androidowner/Network.kt
@@ -0,0 +1,251 @@
+package com.binbin.androidowner
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.WifiSsidPolicy
+import android.content.ComponentName
+import android.content.Context
+import android.net.wifi.WifiSsid
+import android.os.Build.VERSION
+import android.widget.Toast
+import androidx.activity.ComponentActivity
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.text.KeyboardActions
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.Button
+import androidx.compose.material3.MaterialTheme.colorScheme
+import androidx.compose.material3.MaterialTheme.typography
+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
+import androidx.compose.ui.platform.LocalFocusManager
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+
+@Composable
+fun Network(){
+ Column(modifier = Modifier.verticalScroll(rememberScrollState()).fillMaxWidth()){
+ val myContext = LocalContext.current
+ val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
+ val myComponent = ComponentName(myContext,MyDeviceAdminReceiver::class.java)
+ val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
+ val isWear = sharedPref.getBoolean("isWear",false)
+ val bodyTextStyle = if(isWear){ typography.bodyMedium }else{ typography.bodyLarge }
+ val focusMgr = LocalFocusManager.current
+
+ if(VERSION.SDK_INT>=24){
+ val wifimac = try { myDpm.getWifiMacAddress(myComponent).toString() }catch(e:SecurityException){ "没有权限" }
+ Text(text = "WiFi MAC: $wifimac",modifier=Modifier.fillMaxWidth(), textAlign = TextAlign.Center,style=bodyTextStyle)
+ }
+
+ if(VERSION.SDK_INT>=26&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){
+ DeviceCtrlItem(R.string.network_logging,R.string.developing,R.drawable.wifi_fill0,
+ {myDpm.isNetworkLoggingEnabled(myComponent)},{b -> myDpm.setNetworkLoggingEnabled(myComponent,b) }
+ )
+ }
+ if(VERSION.SDK_INT>=33&&isDeviceOwner(myDpm)){
+ DeviceCtrlItem(R.string.preferential_network_service,R.string.developing,R.drawable.globe_fill0,
+ {myDpm.isPreferentialNetworkServiceEnabled},{b -> myDpm.isPreferentialNetworkServiceEnabled = b}
+ )
+ }
+ if(VERSION.SDK_INT>=30){
+ DeviceCtrlItem(R.string.wifi_lockdown,R.string.place_holder,R.drawable.wifi_password_fill0,
+ {myDpm.hasLockdownAdminConfiguredNetworks(myComponent)},{b -> myDpm.setConfiguredNetworksLockdownState(myComponent,b)}
+ )
+ }
+ if(VERSION.SDK_INT>=33){
+ Column(modifier = sections()){
+ var selectedWifiSecLevel by remember{mutableIntStateOf(myDpm.minimumRequiredWifiSecurityLevel)}
+ Text(text = "要求最小WiFi安全等级", style = typography.titleLarge, color = colorScheme.onPrimaryContainer)
+ RadioButtonItem("开放", {selectedWifiSecLevel==DevicePolicyManager.WIFI_SECURITY_OPEN}, {selectedWifiSecLevel= DevicePolicyManager.WIFI_SECURITY_OPEN})
+ RadioButtonItem("WEP, WPA(2)-PSK", {selectedWifiSecLevel==DevicePolicyManager.WIFI_SECURITY_PERSONAL}, {selectedWifiSecLevel= DevicePolicyManager.WIFI_SECURITY_PERSONAL})
+ RadioButtonItem("WPA-EAP", {selectedWifiSecLevel==DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_EAP}, {selectedWifiSecLevel= DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_EAP})
+ RadioButtonItem("WPA3-192bit", {selectedWifiSecLevel==DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_192}, {selectedWifiSecLevel= DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_192})
+ Button(
+ enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm),
+ onClick = {
+ myDpm.minimumRequiredWifiSecurityLevel=selectedWifiSecLevel
+ Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
+ },
+ modifier = Modifier.fillMaxWidth()
+ ){
+ Text("应用")
+ }
+ }
+ }else{
+ Text(text = "Wifi安全等级需API33", modifier = Modifier.padding(vertical = 3.dp))
+ }
+
+ if(VERSION.SDK_INT>=33&&isDeviceOwner(myDpm)){
+ Column(modifier = sections()){
+ var policy = myDpm.wifiSsidPolicy
+ var selectedPolicyType by remember{mutableIntStateOf(policy?.policyType ?: -1)}
+ var inputSsid by remember{mutableStateOf("")}
+ var ssidSet = policy?.ssids ?: mutableSetOf()
+ var ssidList by remember{mutableStateOf("")}
+ val refreshList = {
+ policy = myDpm.wifiSsidPolicy
+ selectedPolicyType = policy?.policyType ?: -1
+ ssidSet = policy?.ssids ?: mutableSetOf()
+ inputSsid = ""
+ ssidList = ""
+ var count = ssidSet.size
+ for(ssid in ssidSet){
+ count-=1
+ ssidList+=ssid
+ if(count>0){ssidList+="\n"}
+ }
+ }
+ var inited by remember{mutableStateOf(false)}
+ if(!inited){refreshList(); inited=true}
+ Text(text = "WiFi SSID策略", style = typography.titleLarge)
+ RadioButtonItem("白名单",{selectedPolicyType==WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST},{selectedPolicyType= WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST})
+ RadioButtonItem("黑名单",{selectedPolicyType==WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST},{selectedPolicyType= WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST})
+ Text("SSID列表:")
+ Text(text = if(ssidList!=""){ssidList}else{"无"}, style = bodyTextStyle)
+ TextField(
+ value = inputSsid,
+ label = { Text("SSID")},
+ onValueChange = {inputSsid = it},
+ keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
+ keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
+ modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp)
+ )
+ Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween){
+ Button(
+ onClick = {
+ focusMgr.clearFocus()
+ if(selectedPolicyType==-1){
+ Toast.makeText(myContext, "请选择策略", Toast.LENGTH_SHORT).show()
+ }else{
+ ssidSet.add(WifiSsid.fromBytes(inputSsid.toByteArray()))
+ myDpm.wifiSsidPolicy = WifiSsidPolicy(selectedPolicyType, ssidSet)
+ refreshList()
+ }
+ },
+ modifier = Modifier.fillMaxWidth(0.49F)
+ ) {
+ Text("添加")
+ }
+ Button(
+ onClick = {
+ focusMgr.clearFocus()
+ if(selectedPolicyType==-1){
+ Toast.makeText(myContext, "请选择策略", Toast.LENGTH_SHORT).show()
+ }else{
+ if(WifiSsid.fromBytes(inputSsid.toByteArray()) in ssidSet){
+ ssidSet.remove(WifiSsid.fromBytes(inputSsid.toByteArray()))
+ myDpm.wifiSsidPolicy = if(ssidSet.size==0){ null }else{ WifiSsidPolicy(selectedPolicyType, ssidSet) }
+ refreshList()
+ }else{
+ Toast.makeText(myContext, "不存在", Toast.LENGTH_SHORT).show()
+ }
+ }
+ },
+ modifier = Modifier.fillMaxWidth(0.96F)
+ ) {
+ Text("移除")
+ }
+ }
+ }
+ }
+ if(VERSION.SDK_INT>=29&&isDeviceOwner(myDpm)){
+ Column(modifier = sections()){
+ Text(text = "私人DNS", style = typography.titleLarge)
+ val dnsStatus = mapOf(
+ DevicePolicyManager.PRIVATE_DNS_MODE_UNKNOWN to "未知",
+ DevicePolicyManager.PRIVATE_DNS_MODE_OFF to "关闭",
+ DevicePolicyManager.PRIVATE_DNS_MODE_OPPORTUNISTIC to "自动",
+ DevicePolicyManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME to "指定主机名"
+ )
+ val operationResult = mapOf(
+ DevicePolicyManager.PRIVATE_DNS_SET_NO_ERROR to "成功",
+ DevicePolicyManager.PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING to "主机不支持DNS over TLS",
+ DevicePolicyManager.PRIVATE_DNS_SET_ERROR_FAILURE_SETTING to "失败"
+ )
+ var status by remember{mutableStateOf(dnsStatus[myDpm.getGlobalPrivateDnsMode(myComponent)])}
+ Text(text = "状态:$status")
+ Button(
+ onClick = {
+ val result = myDpm.setGlobalPrivateDnsModeOpportunistic(myComponent)
+ Toast.makeText(myContext, operationResult[result], Toast.LENGTH_SHORT).show()
+ status = dnsStatus[myDpm.getGlobalPrivateDnsMode(myComponent)]
+ },
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ Text("设为自动")
+ }
+ Spacer(Modifier.padding(vertical = 3.dp))
+ var inputHost by remember{mutableStateOf(myDpm.getGlobalPrivateDnsHost(myComponent) ?: "")}
+ TextField(
+ value = inputHost,
+ onValueChange = {inputHost=it},
+ label = {Text("DNS主机名")},
+ keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
+ keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
+ modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp)
+ )
+ Button(
+ onClick = {
+ val result: Int
+ try{
+ result = myDpm.setGlobalPrivateDnsModeSpecifiedHost(myComponent,inputHost)
+ Toast.makeText(myContext, operationResult[result], Toast.LENGTH_SHORT).show()
+ }catch(e:IllegalArgumentException){
+ Toast.makeText(myContext, "无效主机名", Toast.LENGTH_SHORT).show()
+ }catch(e:SecurityException){
+ Toast.makeText(myContext, "安全错误", Toast.LENGTH_SHORT).show()
+ }finally {
+ status = dnsStatus[myDpm.getGlobalPrivateDnsMode(myComponent)]
+ }
+ },
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ Text("设置DNS主机")
+ }
+ }
+ }
+
+ if(VERSION.SDK_INT>=31&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){
+ Column(modifier = sections()){
+ var keyPair by remember{mutableStateOf("")}
+ Text(text = "WiFi密钥对", style = typography.titleLarge)
+ TextField(
+ value = keyPair,
+ label = { Text("密钥对")},
+ onValueChange = {keyPair = it},
+ keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
+ keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
+ modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp)
+ )
+ val isExist = try{myDpm.isKeyPairGrantedToWifiAuth(keyPair)}catch(e:java.lang.IllegalArgumentException){false}
+ Text("已存在:$isExist")
+ Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween){
+ Button(
+ onClick = {
+ val result = myDpm.grantKeyPairToWifiAuth(keyPair)
+ Toast.makeText(myContext, if(result){"成功"}else{"失败"}, Toast.LENGTH_SHORT).show()
+ },
+ modifier = Modifier.fillMaxWidth(0.49F)
+ ) {
+ Text("添加")
+ }
+ Button(
+ onClick = {
+ val result = myDpm.revokeKeyPairFromWifiAuth(keyPair)
+ Toast.makeText(myContext, if(result){"成功"}else{"失败"}, Toast.LENGTH_SHORT).show()
+ },
+ modifier = Modifier.fillMaxWidth(0.96F)
+ ) {
+ Text("移除")
+ }
+ }
+ }
+ }
+ Spacer(Modifier.padding(vertical = 30.dp))
+ }
+}
diff --git a/app/src/main/java/com/binbin/androidowner/Setting.kt b/app/src/main/java/com/binbin/androidowner/Setting.kt
index e2fd0fd..fc6787c 100644
--- a/app/src/main/java/com/binbin/androidowner/Setting.kt
+++ b/app/src/main/java/com/binbin/androidowner/Setting.kt
@@ -35,31 +35,26 @@ fun AppSetting(navCtrl:NavHostController){
val myContext = LocalContext.current
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
val isWear = sharedPref.getBoolean("isWear",false)
+ val bodyTextStyle = if(isWear){typography.bodyMedium}else{typography.bodyLarge}
Column(modifier = sections()) {
Row(modifier = Modifier.fillMaxWidth().padding(horizontal = 3.dp),horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
- Text(text = "Wear", style = MaterialTheme.typography.titleLarge)
+ Text(text = "Wear", style = typography.titleLarge)
Switch(
checked = isWear,
onCheckedChange = {
- sharedPref.edit().putBoolean("isWear",!sharedPref.getBoolean("isWear",false)).apply()
- navCtrl.navigate("HomePage") {
- popUpTo(
- navCtrl.graph.findStartDestination().id
- ) { saveState = true }
- }
+ sharedPref.edit().putBoolean("isWear",!isWear).apply()
+ navCtrl.navigateUp()
}
)
}
if(VERSION.SDK_INT>=32){
Row(modifier = Modifier.fillMaxWidth().padding(horizontal = 3.dp),horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
- Text(text = "动态取色", style = MaterialTheme.typography.titleLarge)
+ Text(text = "动态取色", style = typography.titleLarge)
Switch(
checked = sharedPref.getBoolean("dynamicColor",false),
onCheckedChange = {
sharedPref.edit().putBoolean("dynamicColor",!sharedPref.getBoolean("dynamicColor",false)).apply()
- navCtrl.navigate("HomePage") {
- popUpTo(navCtrl.graph.findStartDestination().id) { saveState = true }
- }
+ navCtrl.navigateUp()
}
)
}
@@ -70,12 +65,14 @@ fun AppSetting(navCtrl:NavHostController){
Column(
modifier = Modifier.padding(start = 8.dp, end = 8.dp, bottom = 12.dp)
) {
- Text(text = "Android owner", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onPrimaryContainer)
- Text(text = "使用安卓的Device admin、Device owner 、Profile owner,全方位掌控你的设备",
- style = if(!sharedPref.getBoolean("isWear",false)){MaterialTheme.typography.bodyLarge}else{MaterialTheme.typography.bodyMedium})
+ Text(text = "关于", style = typography.headlineSmall, color = MaterialTheme.colorScheme.onPrimaryContainer)
+ Text(text = "使用安卓的Device admin、Device owner 、Profile owner,全方位掌控你的设备", style = bodyTextStyle)
Spacer(Modifier.padding(vertical = 4.dp))
- Text(text = "这个应用只在AOSP和LineageOS上测试过,不确保每个功能都在其它系统可用,尤其是国内的魔改系统。",
- style = if(!sharedPref.getBoolean("isWear",false)){MaterialTheme.typography.bodyLarge}else{MaterialTheme.typography.bodyMedium})
+ Text(text = "这个应用只在AOSP和LineageOS上测试过,不确保每个功能都在其它系统可用,尤其是国内的魔改系统。", style = bodyTextStyle)
+ Spacer(Modifier.padding(vertical = 4.dp))
+ Text(text = "大部分功能都要Device owner权限", style = bodyTextStyle)
+ Spacer(Modifier.padding(vertical = 2.dp))
+ Text(text = "安卓版本越高,支持的功能越多", style = bodyTextStyle)
}
Row(
verticalAlignment = Alignment.CenterVertically,
@@ -92,7 +89,7 @@ fun AppSetting(navCtrl:NavHostController){
)
Column {
Text(text = "源代码", fontSize = 18.sp, fontWeight = FontWeight.SemiBold)
- if(!sharedPref.getBoolean("isWear",false)){
+ if(!isWear){
Text(text = "https://github.com/BinTianqi/AndroidOwner", color = MaterialTheme.colorScheme.onPrimaryContainer)
Text(text = "欢迎提交issue、给小星星")
}
diff --git a/app/src/main/res/drawable/wifi_password_fill0.xml b/app/src/main/res/drawable/wifi_password_fill0.xml
new file mode 100644
index 0000000..6acbb88
--- /dev/null
+++ b/app/src/main/res/drawable/wifi_password_fill0.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 1b9fe93..8033fe6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -119,4 +119,7 @@
通用标准模式
Common Criteria
优先网络服务
+ 网络
+ 功能开发中
+ WiFi锁定