support transform ownership

This commit is contained in:
BinTianqi
2024-02-13 12:38:33 +08:00
parent 0aa514fc4b
commit 599f6c06bb
10 changed files with 162 additions and 45 deletions

View File

@@ -166,6 +166,16 @@ adb shell dpm remove-active-admin com.binbin.androidowner/com.binbin.androidowne
提供支持的长消息不知道有啥用 提供支持的长消息不知道有啥用
### 转移所有权
需要Device owner或Profile owner
需要API28或以上
转移设备所有权到另外一个Device owner或Profile owner
目标应用必须是Device admin且支持被转移所有权
## 系统 ## 系统
### 禁用相机 ### 禁用相机
@@ -450,7 +460,7 @@ API34或以上将不能在系统用户中使用WipeData如果要恢复出厂
### 网络日志记录 ### 网络日志记录
需要的权限Device owner或Profile owner 需要的权限Device owner或工作资料的Profile owner
需要API26或以上 需要API26或以上
@@ -476,22 +486,28 @@ API34或以上将不能在系统用户中使用WipeData如果要恢复出厂
## 工作资料 ## 工作资料
工作资料是一种特殊的用户,使用`adb shell pm list user`命令可以看到工作资料 工作资料是一种特殊的用户,使用`adb shell pm list user`命令可以看到工作资料工作资料的默认用户名是“工作资料”或“Work Profile”
### 创建工作资料 ### 创建工作资料
设备上不能有Device owner或Profile owner 设备上不能有Device owner或Profile owner
只能有一个工作资料 一个设备只能有一个工作资料
选项: 选项:
- 跳过加密需要API24或以上用) - 跳过加密需要API24或以上有实际作用)
创建后会跳转到工作资料中的Android owner请立即按照指引激活工作资料 创建后会跳转到工作资料中的Android owner请立即按照指引激活工作资料
创建后工作资料中的Android owner会成为Profile owner 创建后工作资料中的Android owner会成为Profile owner
在WearOS上创建工作资料会导致SystemUI停止运行一次。WearOS原生的启动器不支持工作资料你需要使用第三方启动器比如微软桌面。你可以通过[ADB命令移除工作资料](#删除工作资料)
此外,不要作死给工作资料重置密码,不然你连输入密码的地方都没有
只在原生WearOS4(AVD)上测试过)
### 由组织拥有的工作资料 ### 由组织拥有的工作资料
需要API30或以上 需要API30或以上
@@ -527,8 +543,6 @@ dpm mark-profile-owner-on-organization-owned-device --user USER_ID com.binbin.an
### 跨资料Intent过滤器 ### 跨资料Intent过滤器
[安卓开发者Intent](https://developer.android.google.cn/reference/kotlin/android/content/Intent)
需要的权限工作资料的Profile owner 需要的权限工作资料的Profile owner
默认情况下,工作资料中的应用不能打开个人应用,个人应用也不可以打开工作资料中的应用 默认情况下,工作资料中的应用不能打开个人应用,个人应用也不可以打开工作资料中的应用
@@ -551,6 +565,12 @@ dpm mark-profile-owner-on-organization-owned-device --user USER_ID com.binbin.an
如果你的工作资料不是由组织拥有的,你可以打开安卓设置->安全->更多安全设置->设备管理器->带工作资料图标的Android owner->移除工作资料(非原生用户自己找) 如果你的工作资料不是由组织拥有的,你可以打开安卓设置->安全->更多安全设置->设备管理器->带工作资料图标的Android owner->移除工作资料(非原生用户自己找)
你也可以使用ADB命令移除工作资料把USER_ID替换为工作资料的UserID
```shell
adb shell pm remove-user USER_ID
```
## 应用管理 ## 应用管理
如果是工作资料,只能管理工作资料中的应用 如果是工作资料,只能管理工作资料中的应用
@@ -770,19 +790,33 @@ Profile owner无法禁用部分功能工作资料中部分功能无效wear
## 用户管理 ## 用户管理
用户user不是账号account
使用ADB查看所有用户
```shell
adb shell pm list users
```
用户名前面的数字就是UserID
### 用户信息 ### 用户信息
当前用户的信息 用户已解锁:你能看到这个的时候一定解锁了
支持多用户系统是否支持多用户。WearOS即使写着支持多用户但不一定支持
系统用户UserID为0的用户需API23 系统用户UserID为0的用户需API23
管理员用户可以创建、删除用户。一个设备可以有多个管理员用户需API34
无头系统用户:~~头被砍掉了~~ 系统用户运行着系统服务但是没有分配给任何人使用也不能切换到系统用户需API31 无头系统用户:~~头被砍掉了~~ 系统用户运行着系统服务但是没有分配给任何人使用也不能切换到系统用户需API31
可以登出:用户限制->[用户](#用户)->切换用户需API28 可以登出:功能未知,无论什么用户都不能登出
临时用户临时用户登出后会被删除需API28 临时用户:临时用户登出后或重启后会被删除需API28
附属用户:运行Device owner的用户是附属于设备的用户受管理用户可以设置附属用户ID以成为附属用户开发中 附属用户:详见[附属用户ID](#附属用户ID)
UserID不是UID。系统用户的UserID为0其他用户包括工作资料的UserID从10开始计算 UserID不是UID。系统用户的UserID为0其他用户包括工作资料的UserID从10开始计算
@@ -798,7 +832,7 @@ UserID不是UID。系统用户的UserID为0其他用户包括工作资
### 创建并管理用户 ### 创建并管理用户
创建一个受管理用户 创建一个受管理用户,新用户的头像右下方会有公文包标志
需要Device owner和API24 需要Device owner和API24
@@ -808,6 +842,36 @@ UserID不是UID。系统用户的UserID为0其他用户包括工作资
- 临时用户需API28 - 临时用户需API28
- 启用所有系统应用有些系统应用在新用户中是默认不启用的比如谷歌手机上的YouTube - 启用所有系统应用有些系统应用在新用户中是默认不启用的比如谷歌手机上的YouTube
创建后Android owner会成为受管理用户中的Profile owner
这个功能在WearOS上使用会导致SystemUI停止运行一次过几秒恢复正常。创建用户实际上成功了回到Android owner后能看到新用户的序列号`pm list users`也能看到新用户。如果切换到新用户SystemUI无法使用表现为黑屏可以用ADB命令启动别的应用。如果黑屏无法使用ADB执行下面这个命令把USER_ID替换成受管理用户的用户序列号
```shell
adb shell pm remove-user --set-ephemeral-if-in-use USER_ID
```
新用户会被设为临时用户,重启后临时用户会被删除并切换到主用户
原生WearOS4(AVD)会出现这个问题,其他版本不知道有没有这个问题)
### 使用Intent创建用户
不需要任何权限但也没啥用建议Device owner创建并管理用户
可能会导致Android owner停止运行但是停止运行后没log所以不知道为什么无法创建
### 附属用户ID
需要Device owner或Profile owner工作资料中的Profile owner虽然也能设置但是没有实际作用
附属用户ID是一个列表列表中可以有多个不相同的ID不考虑顺序
当Device owner创建并管理用户时新的用户不是附属用户。Device owner设置和受管理用户完全相同的附属用户ID后受管理用户成为附属于Device owner的用户
Device owner无论在何时都是附属于设备的用户
你可以在用户管理->[用户信息](#用户信息)查看当前用户是否附属用户
### 用户名 ### 用户名
修改当前用户的用户名 修改当前用户的用户名

View File

@@ -522,6 +522,7 @@ fun DeviceControl(){
TextField( TextField(
value = reason, onValueChange = {reason=it}, value = reason, onValueChange = {reason=it},
label = {Text("原因")}, label = {Text("原因")},
enabled = !confirmed,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}), keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
modifier = Modifier.fillMaxWidth().padding(vertical = 3.dp) modifier = Modifier.fillMaxWidth().padding(vertical = 3.dp)
@@ -529,6 +530,7 @@ fun DeviceControl(){
} }
Button( Button(
onClick = { onClick = {
focusMgr.clearFocus()
flag = 0 flag = 0
if(externalStorage){flag += WIPE_EXTERNAL_STORAGE} if(externalStorage){flag += WIPE_EXTERNAL_STORAGE}
if(protectionData&&VERSION.SDK_INT>=22){flag += WIPE_RESET_PROTECTION_DATA} if(protectionData&&VERSION.SDK_INT>=22){flag += WIPE_RESET_PROTECTION_DATA}
@@ -571,8 +573,10 @@ fun DeviceControl(){
if(VERSION.SDK_INT>=24&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)){ if(VERSION.SDK_INT>=24&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)){
Text(text = "将会删除工作资料", style = bodyTextStyle) Text(text = "将会删除工作资料", style = bodyTextStyle)
} }
if(VERSION.SDK_INT>=34){
Text(text = "API34或以上将不能在系统用户中使用WipeData", style = bodyTextStyle) Text(text = "API34或以上将不能在系统用户中使用WipeData", style = bodyTextStyle)
} }
}
Spacer(Modifier.padding(vertical = 30.dp)) Spacer(Modifier.padding(vertical = 30.dp))
} }
} }

View File

@@ -71,16 +71,15 @@ class MainActivity : ComponentActivity() {
} }
createUser = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { createUser = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
when(it.resultCode){ when(it.resultCode){
UserManager.USER_CREATION_FAILED_NO_MORE_USERS->Toast.makeText(applicationContext, "用户太多了", Toast.LENGTH_SHORT).show() Activity.RESULT_OK->Toast.makeText(applicationContext, "成功", Toast.LENGTH_SHORT).show()
Activity.RESULT_CANCELED->Toast.makeText(applicationContext, "用户太多了", Toast.LENGTH_SHORT).show()
UserManager.USER_CREATION_FAILED_NOT_PERMITTED->Toast.makeText(applicationContext, "不是管理员用户", Toast.LENGTH_SHORT).show() UserManager.USER_CREATION_FAILED_NOT_PERMITTED->Toast.makeText(applicationContext, "不是管理员用户", Toast.LENGTH_SHORT).show()
else->Toast.makeText(applicationContext, "成功", Toast.LENGTH_SHORT).show() UserManager.USER_CREATION_FAILED_NO_MORE_USERS->Toast.makeText(applicationContext, "用户太多了", Toast.LENGTH_SHORT).show()
else->Toast.makeText(applicationContext, "创建用户结果未知", Toast.LENGTH_SHORT).show()
} }
} }
createManagedProfile = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { createManagedProfile = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
when(it.resultCode){ if(it.resultCode==Activity.RESULT_CANCELED){Toast.makeText(applicationContext, "用户已取消", Toast.LENGTH_SHORT).show()}
Activity.RESULT_OK->Toast.makeText(applicationContext, "创建成功", Toast.LENGTH_SHORT).show()
Activity.RESULT_CANCELED->Toast.makeText(applicationContext, "用户已取消", Toast.LENGTH_SHORT).show()
}
} }
setContent { setContent {
AndroidOwnerTheme { AndroidOwnerTheme {
@@ -141,12 +140,8 @@ fun MyScaffold(){
if(sharedPref.getBoolean("isWear",false)&&topBarName!=R.string.app_name){ if(sharedPref.getBoolean("isWear",false)&&topBarName!=R.string.app_name){
FloatingActionButton( FloatingActionButton(
onClick = { onClick = {
navCtrl.navigate("HomePage") {
popUpTo(
navCtrl.graph.findStartDestination().id
) { saveState = true }
}
focusMgr.clearFocus() focusMgr.clearFocus()
navCtrl.navigateUp()
}, },
modifier = Modifier.size(35.dp), modifier = Modifier.size(35.dp),
containerColor = MaterialTheme.colorScheme.tertiaryContainer, containerColor = MaterialTheme.colorScheme.tertiaryContainer,

View File

@@ -65,7 +65,7 @@ fun ManagedProfile() {
Text("跳转至个人应用") Text("跳转至个人应用")
} }
}else{ }else{
if(!myDpm.isProvisioningAllowed(ACTION_PROVISION_MANAGED_PROFILE)&&!isDeviceOwner(myDpm)){ if(!myDpm.isProvisioningAllowed(ACTION_PROVISION_MANAGED_PROFILE)&&!isDeviceOwner(myDpm)&&!isProfileOwner(myDpm)){
Button( Button(
onClick = { myContext.startActivity(Intent("com.binbin.androidowner.MAIN_ACTION")) }, modifier = Modifier.fillMaxWidth() onClick = { myContext.startActivity(Intent("com.binbin.androidowner.MAIN_ACTION")) }, modifier = Modifier.fillMaxWidth()
){ ){

View File

@@ -216,7 +216,7 @@ fun Network(){
} }
} }
if(VERSION.SDK_INT>=26&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){ if(VERSION.SDK_INT>=26&&(isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)))){
Column(modifier = sections()){ Column(modifier = sections()){
Text(text = "收集网络日志", style = typography.titleLarge) Text(text = "收集网络日志", style = typography.titleLarge)
Text(text = "功能开发中", style = bodyTextStyle) Text(text = "功能开发中", style = bodyTextStyle)

View File

@@ -179,8 +179,8 @@ fun Password(){
Button( Button(
onClick = { onClick = {
val resetSuccess = myDpm.resetPasswordWithToken(myComponent,newPwd,myByteArray,resetPwdFlag) val resetSuccess = myDpm.resetPasswordWithToken(myComponent,newPwd,myByteArray,resetPwdFlag)
if(resetSuccess){ Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show() if(resetSuccess){ Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show();newPwd=""}
}else{ Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show() } else{ Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show() }
confirmed=false confirmed=false
}, },
colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError), colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError),
@@ -193,8 +193,8 @@ fun Password(){
Button( Button(
onClick = { onClick = {
val resetSuccess = myDpm.resetPassword(newPwd,resetPwdFlag) val resetSuccess = myDpm.resetPassword(newPwd,resetPwdFlag)
if(resetSuccess){ Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show() if(resetSuccess){ Toast.makeText(myContext, "设置成功", Toast.LENGTH_SHORT).show();newPwd=""}
}else{ Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show() } else{ Toast.makeText(myContext, "设置失败", Toast.LENGTH_SHORT).show() }
confirmed=false confirmed=false
}, },
enabled = confirmed, enabled = confirmed,

View File

@@ -23,6 +23,7 @@ import androidx.compose.material3.TextField
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusManager import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
@@ -32,6 +33,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat.startActivity import androidx.core.content.ContextCompat.startActivity
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import java.lang.IllegalArgumentException
@Composable @Composable
@@ -320,6 +322,41 @@ fun DpmPermissions(navCtrl:NavHostController){
DeviceOwnerInfo(R.string.long_support_msg,R.string.long_support_msg_desc,R.string.message,focusManager,myContext, DeviceOwnerInfo(R.string.long_support_msg,R.string.long_support_msg_desc,R.string.message,focusManager,myContext,
{myDpm.getLongSupportMessage(myComponent)},{content -> myDpm.setLongSupportMessage(myComponent,content)}) {myDpm.getLongSupportMessage(myComponent)},{content -> myDpm.setLongSupportMessage(myComponent,content)})
} }
if(VERSION.SDK_INT>=28&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){
Column(modifier = sections()){
var pkg by remember{mutableStateOf("")}
var cls by remember{mutableStateOf("")}
Text(text = "转移所有权", style = typography.titleLarge)
Text(text = "把Device owner或Profile owner权限转移到另一个应用。目标必须是Device admin", style = bodyTextStyle)
TextField(
value = pkg, onValueChange = {pkg = it}, label = {Text("目标包名")},
modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
keyboardActions = KeyboardActions(onNext = {focusManager.moveFocus(FocusDirection.Down)})
)
TextField(
value = cls, onValueChange = {cls = it}, label = {Text("目标类名")},
modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusManager.clearFocus()})
)
Button(
onClick = {
try {
myDpm.transferOwnership(myComponent,ComponentName(pkg, cls),null)
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
}catch(e:IllegalArgumentException){
Toast.makeText(myContext, "失败", Toast.LENGTH_SHORT).show()
}
},
modifier = Modifier.fillMaxWidth()
) {
Text("转移")
}
}
}
if(isWear&&(myDpm.isAdminActive(myComponent)||isProfileOwner(myDpm)||isDeviceOwner(myDpm))){ if(isWear&&(myDpm.isAdminActive(myComponent)||isProfileOwner(myDpm)||isDeviceOwner(myDpm))){
Column(modifier = sections(), horizontalAlignment = Alignment.CenterHorizontally) { Column(modifier = sections(), horizontalAlignment = Alignment.CenterHorizontally) {
Button( Button(

View File

@@ -7,6 +7,7 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageInstaller.* import android.content.pm.PackageInstaller.*
import android.os.Build.VERSION import android.os.Build.VERSION
import android.os.PersistableBundle
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
@@ -15,6 +16,22 @@ class MyDeviceAdminReceiver : DeviceAdminReceiver() {
super.onEnabled(context, intent) super.onEnabled(context, intent)
Toast.makeText(context, "已启用", Toast.LENGTH_SHORT).show() Toast.makeText(context, "已启用", Toast.LENGTH_SHORT).show()
} }
override fun onTransferOwnershipComplete(context: Context, bundle: PersistableBundle?) {
super.onTransferOwnershipComplete(context, bundle)
if(bundle!=null){
Toast.makeText(context,"转移控制权完毕,附加内容长度:${bundle.size()}",Toast.LENGTH_SHORT).show()
Log.d("TransferOwnerShip",bundle.toString())
}else{
Toast.makeText(context,"转移控制权完毕,无附加内容}",Toast.LENGTH_SHORT).show()
}
}
override fun onProfileProvisioningComplete(context: Context, intent: Intent) {
super.onProfileProvisioningComplete(context, intent)
Toast.makeText(context, "创建工作资料完成", Toast.LENGTH_SHORT).show()
}
@SuppressLint("UnsafeProtectedBroadcastReceiver") @SuppressLint("UnsafeProtectedBroadcastReceiver")
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent) super.onReceive(context, intent)

View File

@@ -49,11 +49,9 @@ fun UserManage() {
Column(modifier = sections()) { Column(modifier = sections()) {
Text(text = "用户信息", style = typography.titleLarge,color = colorScheme.onPrimaryContainer) Text(text = "用户信息", style = typography.titleLarge,color = colorScheme.onPrimaryContainer)
Text("用户已解锁:${UserManagerCompat.isUserUnlocked(myContext)}",style = bodyTextStyle) Text("用户已解锁:${UserManagerCompat.isUserUnlocked(myContext)}",style = bodyTextStyle)
if(VERSION.SDK_INT>=24){ if(VERSION.SDK_INT>=24){ Text("支持多用户:${UserManager.supportsMultipleUsers()}",style = bodyTextStyle) }
Text("支持多用户:${UserManager.supportsMultipleUsers()}",style = bodyTextStyle) if(VERSION.SDK_INT>=23){ Text(text = "系统用户:${userManager.isSystemUser}", style = bodyTextStyle) }
if(isWear&&UserManager.supportsMultipleUsers()){Text(text = "实际上手表可能不支持", style = typography.bodyMedium, color = colorScheme.error)} if(VERSION.SDK_INT>=34){ Text(text = "管理员用户:${userManager.isAdminUser}", style = bodyTextStyle) }
}
if(VERSION.SDK_INT>=23){Text(text = "系统用户:${userManager.isSystemUser}")}
if(VERSION.SDK_INT>=31){ Text(text = "无头系统用户: ${UserManager.isHeadlessSystemUserMode()}",style = bodyTextStyle) } if(VERSION.SDK_INT>=31){ Text(text = "无头系统用户: ${UserManager.isHeadlessSystemUserMode()}",style = bodyTextStyle) }
Spacer(Modifier.padding(vertical = if(isWear){2.dp}else{5.dp})) Spacer(Modifier.padding(vertical = if(isWear){2.dp}else{5.dp}))
if (VERSION.SDK_INT >= 28) { if (VERSION.SDK_INT >= 28) {
@@ -140,7 +138,6 @@ fun UserManage() {
onClick = { onClick = {
focusMgr.clearFocus() focusMgr.clearFocus()
if(myDpm.switchUser(myComponent,userHandleById)){ if(myDpm.switchUser(myComponent,userHandleById)){
focusMgr.clearFocus()
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show() Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
}else{ }else{
Toast.makeText(myContext, "失败", Toast.LENGTH_SHORT).show() Toast.makeText(myContext, "失败", Toast.LENGTH_SHORT).show()
@@ -200,7 +197,6 @@ fun UserManage() {
onValueChange = {userName=it}, onValueChange = {userName=it},
label = {Text("用户名")}, label = {Text("用户名")},
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp), modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp),
enabled = isDeviceOwner(myDpm),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}) keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()})
) )
@@ -223,6 +219,7 @@ fun UserManage() {
) { ) {
Text("创建(Owner)") Text("创建(Owner)")
} }
if(UserManager.supportsMultipleUsers()&&(VERSION.SDK_INT<34||(VERSION.SDK_INT>=34&&userManager.isAdminUser))){
Button( Button(
onClick = { onClick = {
val intent = UserManager.createUserCreationIntent(userName,null,null,null) val intent = UserManager.createUserCreationIntent(userName,null,null,null)
@@ -233,6 +230,7 @@ fun UserManage() {
Text("创建(Intent)") Text("创建(Intent)")
} }
Text(text = "尽量用Device owner模式创建Intent模式可能没有效果", style = bodyTextStyle) Text(text = "尽量用Device owner模式创建Intent模式可能没有效果", style = bodyTextStyle)
}
if(newUserHandle!=null){ Text(text = "新用户的序列号:${userManager.getSerialNumberForUser(newUserHandle)}", style = bodyTextStyle) } if(newUserHandle!=null){ Text(text = "新用户的序列号:${userManager.getSerialNumberForUser(newUserHandle)}", style = bodyTextStyle) }
} }
} }
@@ -288,6 +286,7 @@ fun UserManage() {
) { ) {
Text("应用") Text("应用")
} }
Text(text = "如果多用户附属用户ID相同时可以让其他用户附属于主用户", style = bodyTextStyle)
} }
} }

View File

@@ -12,4 +12,5 @@
<set-global-proxy/> <set-global-proxy/>
<disable-keyguard-features/> <disable-keyguard-features/>
</uses-policies> </uses-policies>
<support-transfer-ownership />
</device-admin> </device-admin>