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

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

View File

@@ -71,16 +71,15 @@ class MainActivity : ComponentActivity() {
}
createUser = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
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()
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()) {
when(it.resultCode){
Activity.RESULT_OK->Toast.makeText(applicationContext, "创建成功", Toast.LENGTH_SHORT).show()
Activity.RESULT_CANCELED->Toast.makeText(applicationContext, "用户已取消", Toast.LENGTH_SHORT).show()
}
if(it.resultCode==Activity.RESULT_CANCELED){Toast.makeText(applicationContext, "用户已取消", Toast.LENGTH_SHORT).show()}
}
setContent {
AndroidOwnerTheme {
@@ -141,12 +140,8 @@ fun MyScaffold(){
if(sharedPref.getBoolean("isWear",false)&&topBarName!=R.string.app_name){
FloatingActionButton(
onClick = {
navCtrl.navigate("HomePage") {
popUpTo(
navCtrl.graph.findStartDestination().id
) { saveState = true }
}
focusMgr.clearFocus()
navCtrl.navigateUp()
},
modifier = Modifier.size(35.dp),
containerColor = MaterialTheme.colorScheme.tertiaryContainer,

View File

@@ -65,7 +65,7 @@ fun ManagedProfile() {
Text("跳转至个人应用")
}
}else{
if(!myDpm.isProvisioningAllowed(ACTION_PROVISION_MANAGED_PROFILE)&&!isDeviceOwner(myDpm)){
if(!myDpm.isProvisioningAllowed(ACTION_PROVISION_MANAGED_PROFILE)&&!isDeviceOwner(myDpm)&&!isProfileOwner(myDpm)){
Button(
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()){
Text(text = "收集网络日志", style = typography.titleLarge)
Text(text = "功能开发中", style = bodyTextStyle)

View File

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

View File

@@ -23,6 +23,7 @@ import androidx.compose.material3.TextField
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
@@ -32,6 +33,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat.startActivity
import androidx.navigation.NavHostController
import java.lang.IllegalArgumentException
@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,
{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))){
Column(modifier = sections(), horizontalAlignment = Alignment.CenterHorizontally) {
Button(

View File

@@ -7,6 +7,7 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageInstaller.*
import android.os.Build.VERSION
import android.os.PersistableBundle
import android.util.Log
import android.widget.Toast
@@ -15,6 +16,22 @@ class MyDeviceAdminReceiver : DeviceAdminReceiver() {
super.onEnabled(context, intent)
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")
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)

View File

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

View File

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