diff --git a/app/src/main/java/com/bintianqi/owndroid/Receiver.kt b/app/src/main/java/com/bintianqi/owndroid/Receiver.kt index ed596d8..bb8576c 100644 --- a/app/src/main/java/com/bintianqi/owndroid/Receiver.kt +++ b/app/src/main/java/com/bintianqi/owndroid/Receiver.kt @@ -1,74 +1,46 @@ package com.bintianqi.owndroid -import android.annotation.SuppressLint import android.app.admin.DeviceAdminReceiver +import android.app.admin.DevicePolicyManager import android.content.BroadcastReceiver +import android.content.ComponentName 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 +import androidx.activity.ComponentActivity +import com.bintianqi.owndroid.dpm.isDeviceOwner +import com.bintianqi.owndroid.dpm.isProfileOwner class Receiver : DeviceAdminReceiver() { override fun onEnabled(context: Context, intent: Intent) { 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() + val myDpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager + val myComponent = ComponentName(context, this::class.java) + if(myDpm.isAdminActive(myComponent)||isProfileOwner(myDpm)||isDeviceOwner(myDpm)){ + Toast.makeText(context, context.getString(R.string.onEnabled), Toast.LENGTH_SHORT).show() + if(myDpm.isAdminActive(myComponent)&&!isProfileOwner(myDpm)&&!isDeviceOwner(myDpm)){ backToHome=true } } } - - 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) - } - - override fun onNetworkLogsAvailable(context: Context, intent: Intent, batchToken: Long, networkLogsCount: Int) { - super.onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount) - Toast.makeText(context,"可以收集网络日志",Toast.LENGTH_SHORT).show() - Log.e("","网络日志可用") - } - - override fun onSecurityLogsAvailable(context: Context, intent: Intent) { - super.onSecurityLogsAvailable(context, intent) - Toast.makeText(context,"可以收集安全日志",Toast.LENGTH_SHORT).show() - Log.e("","安全日志可用") - } - - override fun onDisableRequested(context: Context, intent: Intent): CharSequence { - Toast.makeText(context, "撤销授权", Toast.LENGTH_SHORT).show() - return "这是取消时的提示" - } + override fun onDisabled(context: Context, intent: Intent) { super.onDisabled(context, intent) - Toast.makeText(context, "已禁用", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.onDisabled), Toast.LENGTH_SHORT).show() } - override fun onSystemUpdatePending(context: Context, intent: Intent, receivedTime: Long) { - if (VERSION.SDK_INT < 26) { return } - Toast.makeText(context, "新的系统更新!", Toast.LENGTH_SHORT).show() + + override fun onProfileProvisioningComplete(context: Context, intent: Intent) { + super.onProfileProvisioningComplete(context, intent) + Toast.makeText(context, context.getString(R.string.create_work_profile_success), Toast.LENGTH_SHORT).show() } + } class PackageInstallerReceiver:BroadcastReceiver(){ override fun onReceive(context: Context, intent: Intent) { val toastText = when(intent.getIntExtra(EXTRA_STATUS,666)){ STATUS_PENDING_USER_ACTION->"等待用户交互" - STATUS_SUCCESS->"成功" - STATUS_FAILURE->"失败" + STATUS_SUCCESS->context.getString(R.string.success) + STATUS_FAILURE->context.getString(R.string.fail) STATUS_FAILURE_BLOCKED->"失败:被阻止" STATUS_FAILURE_ABORTED->"失败:被打断" STATUS_FAILURE_INVALID->"失败:无效" @@ -76,8 +48,8 @@ class PackageInstallerReceiver:BroadcastReceiver(){ STATUS_FAILURE_STORAGE->"失败:空间不足" STATUS_FAILURE_INCOMPATIBLE->"失败:不兼容" STATUS_FAILURE_TIMEOUT->"失败:超时" - else->"未知" + else->context.getString(R.string.unknown) } - Log.e("静默安装","${intent.getIntExtra(EXTRA_STATUS,666)}:$toastText") + Toast.makeText(context, toastText, Toast.LENGTH_SHORT).show() } } diff --git a/app/src/main/java/com/bintianqi/owndroid/Utils.kt b/app/src/main/java/com/bintianqi/owndroid/Utils.kt index 6de36a7..d228a41 100644 --- a/app/src/main/java/com/bintianqi/owndroid/Utils.kt +++ b/app/src/main/java/com/bintianqi/owndroid/Utils.kt @@ -53,14 +53,6 @@ fun Set.toText():String{ fun writeClipBoard(context: Context, string: String):Boolean{ val clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager try { - if(VERSION.SDK_INT>=23){ - val hasPermission: Boolean = clipboardManager.hasPrimaryClip() - if(!hasPermission) { - val intent = Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS) - intent.setData(Uri.parse("package:"+context.packageName)) - startActivity(context,intent,null) - } - } clipboardManager.setPrimaryClip(ClipData.newPlainText("", string)) }catch(e:Exception){ return false diff --git a/app/src/main/java/com/bintianqi/owndroid/dpm/Permissions.kt b/app/src/main/java/com/bintianqi/owndroid/dpm/Permissions.kt index a9a6693..817460d 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/Permissions.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/Permissions.kt @@ -9,6 +9,7 @@ import android.content.Intent import android.os.Build.VERSION import android.widget.Toast import androidx.activity.ComponentActivity +import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardActions @@ -191,34 +192,34 @@ private fun DeviceAdmin(navCtrl: NavHostController){ val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager val myComponent = ComponentName(myContext,Receiver::class.java) val co = rememberCoroutineScope() + var showDeactivateButton by remember{mutableStateOf(myDpm.isAdminActive(myComponent))} Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 8.dp)){ Spacer(Modifier.padding(vertical = 10.dp)) Text(text = stringResource(R.string.device_admin), style = typography.headlineLarge) Text(text = stringResource(if(myDpm.isAdminActive(myComponent)) { R.string.activated } else { R.string.deactivated }), style = typography.titleLarge) Spacer(Modifier.padding(vertical = 5.dp)) - if(myDpm.isAdminActive(myComponent)) { - if(!isDeviceOwner(myDpm)&&!isProfileOwner(myDpm)) { - Button( - onClick = { - myDpm.removeActiveAdmin(myComponent) - co.launch{ delay(600); if(!myDpm.isAdminActive(myComponent)){navCtrl.navigateUp()} } - }, - colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError) - ) { - Text(stringResource(R.string.deactivate)) - } - } - } else { - Button(onClick = {activateDeviceAdmin(myContext, myComponent)}, modifier = Modifier.fillMaxWidth()) { - Text(stringResource(R.string.activate)) + AnimatedVisibility(showDeactivateButton) { + Button( + onClick = { + myDpm.removeActiveAdmin(myComponent) + co.launch{ delay(400); showDeactivateButton=myDpm.isAdminActive(myComponent) } + }, + colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError) + ) { + Text(stringResource(R.string.deactivate)) } } - Spacer(Modifier.padding(vertical = 5.dp)) - if(!myDpm.isAdminActive(myComponent)) { - SelectionContainer { - Text(text = stringResource(R.string.activate_device_admin_command)) + AnimatedVisibility(!showDeactivateButton) { + Column { + Button(onClick = {activateDeviceAdmin(myContext, myComponent)}, modifier = Modifier.fillMaxWidth()) { + Text(stringResource(R.string.activate_jump)) + } + Spacer(Modifier.padding(vertical = 5.dp)) + SelectionContainer { + Text(text = stringResource(R.string.activate_device_admin_command)) + } + CopyTextButton(myContext, R.string.copy_command, stringResource(R.string.activate_device_admin_command)) } - CopyTextButton(myContext, R.string.copy_command, stringResource(R.string.activate_device_admin_command)) } } } @@ -228,28 +229,33 @@ private fun ProfileOwner(){ val myContext = LocalContext.current val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager val myComponent = ComponentName(myContext,Receiver::class.java) + var showDeactivateButton by remember{mutableStateOf(isProfileOwner(myDpm))} Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 8.dp)){ Spacer(Modifier.padding(vertical = 10.dp)) Text(text = stringResource(R.string.profile_owner), style = typography.headlineLarge) Text(stringResource(if(isProfileOwner(myDpm)){R.string.activated}else{R.string.deactivated}), style = typography.titleLarge) Spacer(Modifier.padding(vertical = 5.dp)) - if(isProfileOwner(myDpm)&&VERSION.SDK_INT>=24){ - val co = rememberCoroutineScope() - Button( - onClick = { - myDpm.clearProfileOwner(myComponent) - co.launch { delay(600); if(!isProfileOwner(myDpm)){ backToHome=true } } - }, - colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError) - ) { - Text(stringResource(R.string.deactivate)) + if(VERSION.SDK_INT>=24){ + AnimatedVisibility(showDeactivateButton) { + val co = rememberCoroutineScope() + Button( + onClick = { + myDpm.clearProfileOwner(myComponent) + co.launch { delay(400); showDeactivateButton=isProfileOwner(myDpm) } + }, + colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError) + ) { + Text(stringResource(R.string.deactivate)) + } } } - if(!isProfileOwner(myDpm)){ - SelectionContainer{ - Text(text = stringResource(R.string.activate_profile_owner_command)) + AnimatedVisibility(!showDeactivateButton) { + Column { + SelectionContainer{ + Text(text = stringResource(R.string.activate_profile_owner_command)) + } + CopyTextButton(myContext, R.string.copy_command, stringResource(R.string.activate_profile_owner_command)) } - CopyTextButton(myContext, R.string.copy_command, stringResource(R.string.activate_profile_owner_command)) } } } @@ -259,27 +265,30 @@ private fun DeviceOwner(navCtrl: NavHostController){ val myContext = LocalContext.current val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager val co = rememberCoroutineScope() + var showDeactivateButton by remember{mutableStateOf(isDeviceOwner(myDpm))} Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 8.dp)){ Spacer(Modifier.padding(vertical = 10.dp)) Text(text = stringResource(R.string.device_owner), style = typography.headlineLarge) Text(text = stringResource(if(isDeviceOwner(myDpm)){R.string.activated}else{R.string.deactivated}), style = typography.titleLarge) Spacer(Modifier.padding(vertical = 5.dp)) - if(isDeviceOwner(myDpm)){ + AnimatedVisibility(showDeactivateButton) { Button( onClick = { myDpm.clearDeviceOwnerApp(myContext.packageName) - co.launch{ delay(600); if(!isDeviceOwner(myDpm)){ backToHome=true } } + co.launch{ delay(400); showDeactivateButton=isDeviceOwner(myDpm) } }, colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError) ) { Text(text = stringResource(R.string.deactivate)) } } - if(!isDeviceOwner(myDpm)&&!isProfileOwner(myDpm)){ - SelectionContainer{ - Text(text = stringResource(R.string.activate_device_owner_command)) + AnimatedVisibility(!showDeactivateButton) { + Column { + SelectionContainer{ + Text(text = stringResource(R.string.activate_device_owner_command)) + } + CopyTextButton(myContext, R.string.copy_command, stringResource(R.string.activate_device_owner_command)) } - CopyTextButton(myContext, R.string.copy_command, stringResource(R.string.activate_device_owner_command)) } } } diff --git a/app/src/main/java/com/bintianqi/owndroid/dpm/ShizukuActivate.kt b/app/src/main/java/com/bintianqi/owndroid/dpm/ShizukuActivate.kt index 9eeb9fa..2934e97 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/ShizukuActivate.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/ShizukuActivate.kt @@ -32,7 +32,6 @@ import androidx.compose.ui.unit.dp import com.bintianqi.owndroid.IUserService import com.bintianqi.owndroid.R import com.bintianqi.owndroid.Receiver -import com.bintianqi.owndroid.backToHome import kotlinx.coroutines.delay import kotlinx.coroutines.launch import rikka.shizuku.Shizuku @@ -49,6 +48,10 @@ fun ShizukuActivate(){ var enabled by remember{ mutableStateOf(false) } var bindShizuku by remember{ mutableStateOf(false) } var outputText by remember{mutableStateOf("")} + var showDeviceAdminButton by remember{mutableStateOf(!myDpm.isAdminActive(myComponent))} + var showProfileOwnerButton by remember{mutableStateOf(!isProfileOwner(myDpm))} + var showDeviceOwnerButton by remember{mutableStateOf(!isDeviceOwner(myDpm))} + var showOrgProfileOwnerButton by remember{mutableStateOf(true)} LaunchedEffect(Unit){ if(service==null){userServiceControl(myContext, true)} while(true){ @@ -103,60 +106,59 @@ fun ShizukuActivate(){ Text(text = stringResource(R.string.list_owners)) } Spacer(Modifier.padding(vertical = 5.dp)) - - if(!isDeviceOwner(myDpm)&&!isProfileOwner(myDpm)){ - Column { - if(!myDpm.isAdminActive(myComponent)){ - Button( - onClick = { - coScope.launch{ - outputText = service!!.execute(myContext.getString(R.string.dpm_activate_da_command)) - outputTextScrollState.animateScrollTo(0, scrollAnim()) - delay(600) - if(myDpm.isAdminActive(myComponent)){backToHome=true} - } - }, - enabled = enabled - ) { - Text(text = stringResource(R.string.activate_device_admin)) + + AnimatedVisibility(showDeviceAdminButton&&showProfileOwnerButton&&showDeviceOwnerButton) { + Button( + onClick = { + coScope.launch{ + outputText = service!!.execute(myContext.getString(R.string.dpm_activate_da_command)) + outputTextScrollState.animateScrollTo(0, scrollAnim()) + delay(500) + showDeviceAdminButton = !myDpm.isAdminActive(myComponent) } - } - - Button( - onClick = { - coScope.launch{ - outputText = service!!.execute(myContext.getString(R.string.dpm_activate_po_command)) - outputTextScrollState.animateScrollTo(0, scrollAnim()) - delay(600) - if(isProfileOwner(myDpm)){backToHome=true} - } - }, - enabled = enabled - ) { - Text(text = stringResource(R.string.activate_profile_owner)) - } - - Button( - onClick = { - coScope.launch{ - outputText = service!!.execute(myContext.getString(R.string.dpm_activate_do_command)) - outputTextScrollState.animateScrollTo(0, scrollAnim()) - delay(600) - if(isDeviceOwner(myDpm)){backToHome=true} - } - }, - enabled = enabled - ) { - Text(text = stringResource(R.string.activate_device_owner)) - } - + }, + enabled = enabled + ) { + Text(text = stringResource(R.string.activate_device_admin)) + } + } + + AnimatedVisibility(showProfileOwnerButton&&showDeviceOwnerButton) { + Button( + onClick = { + coScope.launch{ + outputText = service!!.execute(myContext.getString(R.string.dpm_activate_po_command)) + outputTextScrollState.animateScrollTo(0, scrollAnim()) + delay(600) + showProfileOwnerButton = !isProfileOwner(myDpm) + } + }, + enabled = enabled + ) { + Text(text = stringResource(R.string.activate_profile_owner)) + } + } + + AnimatedVisibility(showDeviceOwnerButton&&showProfileOwnerButton) { + Button( + onClick = { + coScope.launch{ + outputText = service!!.execute(myContext.getString(R.string.dpm_activate_do_command)) + outputTextScrollState.animateScrollTo(0, scrollAnim()) + delay(500) + showDeviceOwnerButton = !isDeviceOwner(myDpm) + } + }, + enabled = enabled + ) { + Text(text = stringResource(R.string.activate_device_owner)) } } if( - VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent) + VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)&&!myDpm.isOrganizationOwnedDeviceWithManagedProfile ){ - Column { + AnimatedVisibility(showOrgProfileOwnerButton) { Button( onClick = { coScope.launch{ @@ -165,6 +167,8 @@ fun ShizukuActivate(){ "dpm mark-profile-owner-on-organization-owned-device --user $userID com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver" ) outputTextScrollState.animateScrollTo(0, scrollAnim()) + delay(500) + showOrgProfileOwnerButton = !myDpm.isOrganizationOwnedDeviceWithManagedProfile } }, enabled = enabled diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 25d09ec..92344e0 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -46,6 +46,7 @@ 点击以激活 Device admin + 激活... Profile owner Device owner 激活Device admin @@ -75,6 +76,11 @@ 转移 在这里激活Device admin + + OwnDroid:已启用 + OwnDroid:已禁用 + OwnDroid:创建工作资料成功 + 检查Shizuku 列出Owners diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3d2f3b2..933ca6f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -49,6 +49,7 @@ Click to activate Device admin + Activate... Profile owner Device owner Activate Device admin @@ -82,6 +83,11 @@ Transform Activate Device admin here. + + OwnDroid: Enabled + OwnDroid: Disabled + OwnDroid: Create work profile success + Shizuku Check permission