From 8dedd63f6123eeb7ef61132d85fe84f0873f31d3 Mon Sep 17 00:00:00 2001 From: BinTianqi <1220958406@qq.com> Date: Fri, 9 Feb 2024 23:58:07 +0800 Subject: [PATCH] org-owned profile features --- app/build.gradle.kts | 4 +- .../binbin/androidowner/ApplicationManage.kt | 141 ++++++++---------- .../com/binbin/androidowner/DeviceControl.kt | 63 ++++---- .../com/binbin/androidowner/ManagedProfile.kt | 13 -- .../java/com/binbin/androidowner/Network.kt | 6 +- .../java/com/binbin/androidowner/Password.kt | 2 +- .../com/binbin/androidowner/Permissions.kt | 2 +- 7 files changed, 100 insertions(+), 131 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1bcefe2..b2e4770 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 = 12 - versionName = "2.5" + versionCode = 13 + versionName = "3.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/java/com/binbin/androidowner/ApplicationManage.kt b/app/src/main/java/com/binbin/androidowner/ApplicationManage.kt index 5a5873b..c910033 100644 --- a/app/src/main/java/com/binbin/androidowner/ApplicationManage.kt +++ b/app/src/main/java/com/binbin/androidowner/ApplicationManage.kt @@ -59,7 +59,6 @@ fun ApplicationManage(){ value = pkgName, onValueChange = { pkgName = it }, label = { Text("包名") }, - enabled = isDeviceOwner(myDpm)|| isProfileOwner(myDpm), modifier = Modifier.fillMaxWidth().padding(horizontal = 4.dp), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}) @@ -71,7 +70,6 @@ fun ApplicationManage(){ value = pkgName, onValueChange = { pkgName = it }, label = { Text("包名") }, - enabled = isDeviceOwner(myDpm)|| isProfileOwner(myDpm), modifier = Modifier.fillMaxWidth().padding(horizontal = 2.dp,vertical = 2.dp), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}) @@ -80,6 +78,18 @@ fun ApplicationManage(){ if(VERSION.SDK_INT>=24&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)){ Text(text = "作用域: 工作资料", style = bodyTextStyle, textAlign = TextAlign.Center,modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp)) } + + Button( + onClick = { + val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + intent.setData(Uri.parse("package:$pkgName")) + startActivity(myContext,intent,null) + }, + modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp) + ){ + Text("应用详情") + } + if(VERSION.SDK_INT>=24&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){ AppManageItem( R.string.suspend,R.string.place_holder, @@ -441,87 +451,66 @@ fun ApplicationManage(){ } } - Column(modifier = sections()) { - Text(text = "许可的输入法", style = typography.titleLarge,color = colorScheme.onPrimaryContainer) - var imeList = mutableListOf() - var imeListText by remember{ mutableStateOf("") } - val refreshList = { - if(isProfileOwner(myDpm) || isDeviceOwner(myDpm)){ - if(myDpm.getPermittedInputMethods(myComponent)!=null){ - imeList = myDpm.getPermittedInputMethods(myComponent)!! + if(isDeviceOwner(myDpm)||isProfileOwner(myDpm)){ + Column(modifier = sections()) { + Text(text = "许可的输入法", style = typography.titleLarge,color = colorScheme.onPrimaryContainer) + var imeList = mutableListOf() + var imeListText by remember{ mutableStateOf("") } + val refreshList = { + if(myDpm.getPermittedInputMethods(myComponent)!=null){ imeList = myDpm.getPermittedInputMethods(myComponent)!! } + imeListText = "" + for(eachIme in imeList){ imeListText += "$eachIme \n" } + } + var inited by remember{mutableStateOf(false)} + if(!inited){refreshList();inited=true} + Text(text = if(imeListText!=""){imeListText}else{"无"}, style = bodyTextStyle) + Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceBetween){ + Button( + onClick = { + focusMgr.clearFocus() + imeList.plus(pkgName) + Toast.makeText(myContext, if(myDpm.setPermittedInputMethods(myComponent, imeList)){"成功"}else{"失败"}, Toast.LENGTH_SHORT).show() + refreshList() + }, + modifier = Modifier.fillMaxWidth(0.49F) + ) { + Text("添加") + } + Button( + onClick = { + focusMgr.clearFocus() + imeList.remove(pkgName) + Toast.makeText(myContext, if(myDpm.setPermittedInputMethods(myComponent, imeList)){"成功"}else{"失败"}, Toast.LENGTH_SHORT).show() + refreshList() + }, + modifier = Modifier.fillMaxWidth(0.96F) + ) { + Text("移除") } - } - imeListText = "" - for(eachIme in imeList){ imeListText += "$eachIme \n" } - } - var inited by remember{mutableStateOf(false)} - if(!inited){refreshList();inited=true} - Text(text = if(imeListText!=""){imeListText}else{"无"}, style = bodyTextStyle) - Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceBetween){ - Button( - onClick = { - imeList.plus(pkgName) - focusMgr.clearFocus() - Toast.makeText(myContext, if(myDpm.setPermittedInputMethods(myComponent, imeList)){"成功"}else{"失败"}, Toast.LENGTH_SHORT).show() - refreshList() - }, - modifier = Modifier.fillMaxWidth(0.49F), - enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm) - ) { - Text("添加") - } - Button( - onClick = { - imeList.remove(pkgName) - focusMgr.clearFocus() - Toast.makeText(myContext, if(myDpm.setPermittedInputMethods(myComponent, imeList)){"成功"}else{"失败"}, Toast.LENGTH_SHORT).show() - refreshList() - }, - modifier = Modifier.fillMaxWidth(0.96F), - enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm) - ) { - Text("移除") } } } - Column(modifier = sections()){ - Text(text = "清除应用存储", style = typography.titleLarge, color = colorScheme.onPrimaryContainer) - Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween){ - Button( - onClick = { - val executor = Executors.newCachedThreadPool() - val onClear = DevicePolicyManager.OnClearApplicationUserDataListener { pkg: String, succeed: Boolean -> - Looper.prepare() - focusMgr.clearFocus() - val toastText = if(pkg!=""){"$pkg\n"}else{""} + "数据清除" + if(succeed){"成功"}else{"失败"} - Toast.makeText(myContext, toastText, Toast.LENGTH_SHORT).show() - Looper.loop() - } - if(VERSION.SDK_INT>=28){ - myDpm.clearApplicationUserData(myComponent,pkgName,executor,onClear) - } - }, - enabled = (isDeviceOwner(myDpm)||isProfileOwner(myDpm))&&VERSION.SDK_INT>=28, - modifier = Modifier.fillMaxWidth(0.49F) - ) { - Text("清除") - } - Button( - onClick = { - val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - intent.setData(Uri.parse("package:$pkgName")) - startActivity(myContext,intent,null) - }, - modifier = Modifier.fillMaxWidth(0.96F) - ){ - Text("详情") - } - } - if(VERSION.SDK_INT<28){ - Text(text = "清除存储需API28", style = bodyTextStyle) + if(VERSION.SDK_INT>=28){ + Button( + onClick = { + val executor = Executors.newCachedThreadPool() + val onClear = DevicePolicyManager.OnClearApplicationUserDataListener { pkg: String, succeed: Boolean -> + Looper.prepare() + focusMgr.clearFocus() + val toastText = if(pkg!=""){"$pkg\n"}else{""} + "数据清除" + if(succeed){"成功"}else{"失败"} + Toast.makeText(myContext, toastText, Toast.LENGTH_SHORT).show() + Looper.loop() + } + myDpm.clearApplicationUserData(myComponent,pkgName,executor,onClear) + }, + enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm), + modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp) + ) { + Text("清除应用存储") } } + if(VERSION.SDK_INT>=34){ Button( onClick = { diff --git a/app/src/main/java/com/binbin/androidowner/DeviceControl.kt b/app/src/main/java/com/binbin/androidowner/DeviceControl.kt index 710ae27..5ce4f73 100644 --- a/app/src/main/java/com/binbin/androidowner/DeviceControl.kt +++ b/app/src/main/java/com/binbin/androidowner/DeviceControl.kt @@ -43,12 +43,12 @@ fun DeviceControl(){ val bodyTextStyle = if(isWear){typography.bodyMedium}else{typography.bodyLarge} val focusMgr = LocalFocusManager.current Column(modifier = Modifier.verticalScroll(rememberScrollState()).navigationBarsPadding()) { - if(isDeviceOwner(myDpm)){ + if(isDeviceOwner(myDpm)||isProfileOwner(myDpm)){ DeviceCtrlItem(R.string.disable_cam,R.string.place_holder, R.drawable.photo_camera_fill0, {myDpm.getCameraDisabled(null)},{b -> myDpm.setCameraDisabled(myComponent,b)} ) } - if(isDeviceOwner(myDpm)){ + if(isDeviceOwner(myDpm)||isProfileOwner(myDpm)){ DeviceCtrlItem(R.string.disable_scrcap,R.string.aosp_scrrec_also_work,R.drawable.screenshot_fill0, {myDpm.getScreenCaptureDisabled(null)},{b -> myDpm.setScreenCaptureDisabled(myComponent,b) } ) @@ -58,7 +58,7 @@ fun DeviceControl(){ {myDpm.isStatusBarDisabled},{b -> myDpm.setStatusBarDisabled(myComponent,b) } ) } - if(isDeviceOwner(myDpm)){ + if(isDeviceOwner(myDpm)||(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile)){ if(VERSION.SDK_INT>=30){ DeviceCtrlItem(R.string.auto_time,R.string.place_holder,R.drawable.schedule_fill0, {myDpm.getAutoTimeEnabled(myComponent)},{b -> myDpm.setAutoTimeEnabled(myComponent,b) } @@ -95,7 +95,7 @@ fun DeviceControl(){ {myDpm.isCommonCriteriaModeEnabled(myComponent)},{b -> myDpm.setCommonCriteriaModeEnabled(myComponent,b)} ) } - if(VERSION.SDK_INT>=31&&isDeviceOwner(myDpm)){ + if(VERSION.SDK_INT>=31&&(isDeviceOwner(myDpm)||(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile))){ if(myDpm.canUsbDataSignalingBeDisabled()){ DeviceCtrlItem(R.string.usb_signal,R.string.place_holder,R.drawable.usb_fill0, {myDpm.isUsbDataSignalingEnabled},{b -> myDpm.isUsbDataSignalingEnabled = b } @@ -104,37 +104,27 @@ fun DeviceControl(){ Text(text = "你的设备不支持关闭USB信号",modifier = Modifier.fillMaxWidth(), style = bodyTextStyle, textAlign = TextAlign.Center) } } - if(isDeviceOwner(myDpm)){ - if(VERSION.SDK_INT<23){ Text(text = "禁止蓝牙分享联系人需API23") } - if(VERSION.SDK_INT<24){ Text(text = "安全日志API24",modifier=Modifier.fillMaxWidth(), textAlign = TextAlign.Center, style = bodyTextStyle) } - if(VERSION.SDK_INT<26){ Text(text = "备份服务和网络日志需要API26",modifier=Modifier.fillMaxWidth(), textAlign = TextAlign.Center, style = bodyTextStyle) } - if(VERSION.SDK_INT<30){ Text(text = "自动设置时区和通用标准模式需要API30",modifier=Modifier.fillMaxWidth(), textAlign = TextAlign.Center, style = bodyTextStyle) } - if(VERSION.SDK_INT<31){ Text(text = "关闭USB信号需API31",modifier=Modifier.fillMaxWidth(), textAlign = TextAlign.Center, style = bodyTextStyle) } - if(VERSION.SDK_INT<34){ Text(text = "隐藏状态栏需要API34",modifier=Modifier.fillMaxWidth(), textAlign = TextAlign.Center, style = bodyTextStyle) } - } if(VERSION.SDK_INT>=28){ Column(modifier = sections()) { Text(text = "锁屏方式", style = typography.titleLarge,color = colorScheme.onPrimaryContainer) Text(text = "禁用需要无密码",style=bodyTextStyle) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - Button( - onClick = { Toast.makeText(myContext, if(myDpm.setKeyguardDisabled(myComponent,true)){"成功"}else{"失败"}, Toast.LENGTH_SHORT).show() }, - enabled = isDeviceOwner(myDpm)|| (isProfileOwner(myDpm)&&myDpm.isAffiliatedUser), - modifier = if(isWear){Modifier}else{Modifier.fillMaxWidth(0.49F)} - ) { - Text("禁用") + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { + Button( + onClick = { Toast.makeText(myContext, if(myDpm.setKeyguardDisabled(myComponent,true)){"成功"}else{"失败"}, Toast.LENGTH_SHORT).show() }, + enabled = isDeviceOwner(myDpm)|| (isProfileOwner(myDpm)&&myDpm.isAffiliatedUser), + modifier = Modifier.fillMaxWidth(0.49F) + ) { + Text("禁用") + } + Button( + onClick = { Toast.makeText(myContext, if(myDpm.setKeyguardDisabled(myComponent,false)){"成功"}else{"失败"}, Toast.LENGTH_SHORT).show() }, + enabled = isDeviceOwner(myDpm)|| (isProfileOwner(myDpm)&&myDpm.isAffiliatedUser), + modifier = Modifier.fillMaxWidth(0.96F) + ) { + Text("启用") + } } - Button( - onClick = { Toast.makeText(myContext, if(myDpm.setKeyguardDisabled(myComponent,false)){"成功"}else{"失败"}, Toast.LENGTH_SHORT).show() }, - enabled = isDeviceOwner(myDpm)|| (isProfileOwner(myDpm)&&myDpm.isAffiliatedUser), - modifier = if(isWear){Modifier}else{Modifier.fillMaxWidth(0.96F)} - ) { - Text("启用") - } - }} + } } Column(modifier = sections()){ @@ -183,7 +173,7 @@ fun DeviceControl(){ onValueChange = {inputTime = it}, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done), keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}), - enabled = isDeviceOwner(myDpm), + enabled = isDeviceOwner(myDpm)||(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile), modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp) ) if(isWear){ @@ -198,7 +188,7 @@ fun DeviceControl(){ Button( onClick = {myDpm.setTime(myComponent,inputTime.toLong())}, modifier = Modifier.fillMaxWidth(if(isWear){1F}else{0.35F}), - enabled = inputTime!=""&&isDeviceOwner(myDpm) + enabled = inputTime!=""&&(isDeviceOwner(myDpm)||(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile)) ) { Text("应用") } @@ -505,7 +495,8 @@ fun DeviceControl(){ containerColor = if(confirmed){ colorScheme.primary }else{ colorScheme.error }, contentColor = if(confirmed){ colorScheme.onPrimary }else{ colorScheme.onError } ), - enabled = myDpm.isAdminActive(myComponent) + enabled = myDpm.isAdminActive(myComponent), + modifier = Modifier.fillMaxWidth() ) { Text(text = if(confirmed){"取消"}else{"确定"}) } @@ -516,7 +507,8 @@ fun DeviceControl(){ containerColor = colorScheme.error, contentColor = colorScheme.onError ), - enabled = confirmed + enabled = confirmed, + modifier = Modifier.fillMaxWidth(if(VERSION.SDK_INT>=34){0.49F}else{1F}) ) { Text("WipeData") } @@ -527,7 +519,8 @@ fun DeviceControl(){ containerColor = colorScheme.error, contentColor = colorScheme.onError ), - enabled = confirmed + enabled = confirmed, + modifier = Modifier.fillMaxWidth(0.96F) ) { Text("WipeDevice(API34)") } diff --git a/app/src/main/java/com/binbin/androidowner/ManagedProfile.kt b/app/src/main/java/com/binbin/androidowner/ManagedProfile.kt index 6431243..535bcff 100644 --- a/app/src/main/java/com/binbin/androidowner/ManagedProfile.kt +++ b/app/src/main/java/com/binbin/androidowner/ManagedProfile.kt @@ -6,7 +6,6 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.IntentFilter -import android.content.pm.PackageInstaller import android.os.Build.VERSION import android.widget.Toast import androidx.activity.ComponentActivity @@ -225,18 +224,6 @@ fun ManagedProfile() { } } - if(isProfileOwner(myDpm)&&(VERSION.SDK_INT<24||(VERSION.SDK_INT>=24&&myDpm.isManagedProfile(myComponent)))){ - Column(modifier = sections(colorScheme.tertiaryContainer)){ - Text(text = "提示", style = typography.titleLarge) - SelectionContainer { - Text( - text = "安装应用的Action是android.intent.action.INSTALL_PACKAGE,需配合android.intent.action.VIEW使用", - style = bodyTextStyle, color = colorScheme.onTertiaryContainer - ) - } - } - } - Spacer(Modifier.padding(vertical = 30.dp)) } } diff --git a/app/src/main/java/com/binbin/androidowner/Network.kt b/app/src/main/java/com/binbin/androidowner/Network.kt index 3bd72e6..dff049d 100644 --- a/app/src/main/java/com/binbin/androidowner/Network.kt +++ b/app/src/main/java/com/binbin/androidowner/Network.kt @@ -62,7 +62,7 @@ fun Network(){ {myDpm.isPreferentialNetworkServiceEnabled},{b -> myDpm.isPreferentialNetworkServiceEnabled = b} ) } - if(VERSION.SDK_INT>=30&&isDeviceOwner(myDpm)){ + if(VERSION.SDK_INT>=30&&(isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile))){ DeviceCtrlItem(R.string.wifi_lockdown,R.string.place_holder,R.drawable.wifi_password_fill0, {myDpm.hasLockdownAdminConfiguredNetworks(myComponent)},{b -> myDpm.setConfiguredNetworksLockdownState(myComponent,b)} ) @@ -76,7 +76,7 @@ fun Network(){ 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), + enabled = isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile), onClick = { myDpm.minimumRequiredWifiSecurityLevel=selectedWifiSecLevel Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show() @@ -90,7 +90,7 @@ fun Network(){ Text(text = "Wifi安全等级需API33", modifier = Modifier.padding(vertical = 3.dp)) } - if(VERSION.SDK_INT>=33&&isDeviceOwner(myDpm)){ + if(VERSION.SDK_INT>=33&&(isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile))){ Column(modifier = sections()){ var policy = myDpm.wifiSsidPolicy var selectedPolicyType by remember{mutableIntStateOf(policy?.policyType ?: -1)} diff --git a/app/src/main/java/com/binbin/androidowner/Password.kt b/app/src/main/java/com/binbin/androidowner/Password.kt index f57db9e..366a73c 100644 --- a/app/src/main/java/com/binbin/androidowner/Password.kt +++ b/app/src/main/java/com/binbin/androidowner/Password.kt @@ -346,7 +346,7 @@ fun Password(){ Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show() calculateCustomFeature() }, - enabled = isProfileOwner(myDpm)||isDeviceOwner(myDpm), + enabled = isDeviceOwner(myDpm), modifier = Modifier.fillMaxWidth() ) { Text(text = "应用") diff --git a/app/src/main/java/com/binbin/androidowner/Permissions.kt b/app/src/main/java/com/binbin/androidowner/Permissions.kt index 7c602cf..dcb37e8 100644 --- a/app/src/main/java/com/binbin/androidowner/Permissions.kt +++ b/app/src/main/java/com/binbin/androidowner/Permissions.kt @@ -314,7 +314,7 @@ fun DpmPermissions(navCtrl:NavHostController){ } } - if(isDeviceOwner(myDpm)&&VERSION.SDK_INT>=24){ + if((isDeviceOwner(myDpm)||isProfileOwner(myDpm))&&VERSION.SDK_INT>=24){ DeviceOwnerInfo(R.string.owner_lockscr_info,R.string.place_holder,R.string.owner_lockscr_info,focusManager,myContext, {myDpm.deviceOwnerLockScreenInfo},{content -> myDpm.setDeviceOwnerLockScreenInfo(myComponent,content)}) DeviceOwnerInfo(R.string.support_msg,R.string.support_msg_desc,R.string.message,focusManager,myContext,