mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
feat: app groups importing and exporting (#222)
Show group name in app group operation dialog (#224)
This commit is contained in:
@@ -642,7 +642,7 @@ fun Home(vm: MyViewModel, onLock: () -> Unit) {
|
||||
}
|
||||
composable<ManageAppGroups> {
|
||||
ManageAppGroupsScreen(
|
||||
vm.appGroups,
|
||||
vm.appGroups, vm::exportAppGroups, vm::importAppGroups,
|
||||
{ id, name, apps -> navController.navigate(EditAppGroup(id, name, apps)) },
|
||||
::navigateUp
|
||||
)
|
||||
|
||||
@@ -65,6 +65,7 @@ import com.bintianqi.owndroid.dpm.ApnProtocol
|
||||
import com.bintianqi.owndroid.dpm.AppGroup
|
||||
import com.bintianqi.owndroid.dpm.AppRestriction
|
||||
import com.bintianqi.owndroid.dpm.AppStatus
|
||||
import com.bintianqi.owndroid.dpm.BasicAppGroup
|
||||
import com.bintianqi.owndroid.dpm.CaCertInfo
|
||||
import com.bintianqi.owndroid.dpm.CreateUserResult
|
||||
import com.bintianqi.owndroid.dpm.CreateWorkProfileOptions
|
||||
@@ -119,6 +120,10 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.addJsonObject
|
||||
import kotlinx.serialization.json.buildJsonArray
|
||||
import kotlinx.serialization.json.put
|
||||
import java.net.InetAddress
|
||||
import java.security.MessageDigest
|
||||
import java.security.cert.CertificateException
|
||||
@@ -632,6 +637,20 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
group.filter { it.id != id }
|
||||
}
|
||||
}
|
||||
fun exportAppGroups(uri: Uri) {
|
||||
application.contentResolver.openOutputStream(uri)!!.use {
|
||||
val list: List<BasicAppGroup> = appGroups.value
|
||||
it.write(Json.encodeToString(list).encodeToByteArray())
|
||||
}
|
||||
}
|
||||
fun importAppGroups(uri: Uri) {
|
||||
application.contentResolver.openInputStream(uri)!!.use {
|
||||
Json.decodeFromString<List<BasicAppGroup>>(it.readBytes().decodeToString())
|
||||
}.forEach {
|
||||
myRepo.setAppGroup(null, it.name, it.apps)
|
||||
}
|
||||
getAppGroups()
|
||||
}
|
||||
|
||||
@RequiresApi(24)
|
||||
fun reboot() {
|
||||
|
||||
@@ -5,8 +5,11 @@ import android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED
|
||||
import android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
|
||||
import android.app.admin.PackagePolicy
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build.VERSION
|
||||
import android.os.Looper
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
@@ -904,6 +907,8 @@ fun PackageFunctionScreen(
|
||||
if (dialog) AlertDialog(
|
||||
text = {
|
||||
Column {
|
||||
Text(selectedGroup!!.name, style = typography.titleLarge)
|
||||
Spacer(Modifier.height(6.dp))
|
||||
Button({
|
||||
onSet(selectedGroup!!.apps, true)
|
||||
dialog = false
|
||||
@@ -927,22 +932,68 @@ fun PackageFunctionScreen(
|
||||
)
|
||||
}
|
||||
|
||||
class AppGroup(val id: Int, val name: String, val apps: List<String>)
|
||||
@Serializable
|
||||
open class BasicAppGroup(open val name: String, open val apps: List<String>)
|
||||
|
||||
class AppGroup(
|
||||
val id: Int, override val name: String, override val apps: List<String>
|
||||
) : BasicAppGroup(name, apps)
|
||||
|
||||
@Serializable object ManageAppGroups
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ManageAppGroupsScreen(
|
||||
appGroups: StateFlow<List<AppGroup>>,
|
||||
appGroups: StateFlow<List<AppGroup>>, exportData: (Uri) -> Unit, importData: (Uri) -> Unit,
|
||||
navigateToEditScreen: (Int?, String, List<String>) -> Unit, navigateUp: () -> Unit
|
||||
) {
|
||||
val groups by appGroups.collectAsStateWithLifecycle()
|
||||
val exportLauncher = rememberLauncherForActivityResult(
|
||||
ActivityResultContracts.CreateDocument("application/json")
|
||||
) {
|
||||
if (it != null) exportData(it)
|
||||
}
|
||||
val importLauncher = rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) {
|
||||
if (it != null) importData(it)
|
||||
}
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
{ Text(stringResource(R.string.app_group)) },
|
||||
navigationIcon = { NavIcon(navigateUp) }
|
||||
navigationIcon = { NavIcon(navigateUp) },
|
||||
actions = {
|
||||
var dropdown by remember { mutableStateOf(false) }
|
||||
Box {
|
||||
IconButton({
|
||||
dropdown = true
|
||||
}) {
|
||||
Icon(Icons.Default.MoreVert, null)
|
||||
}
|
||||
DropdownMenu(dropdown, { dropdown = false }) {
|
||||
DropdownMenuItem(
|
||||
{ Text(stringResource(R.string.export)) },
|
||||
{
|
||||
exportLauncher.launch("owndroid_app_groups")
|
||||
dropdown = false
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(painterResource(R.drawable.file_export_fill0), null)
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
{ Text(stringResource(R.string.import_str)) },
|
||||
{
|
||||
importLauncher.launch(arrayOf("application/json"))
|
||||
dropdown = false
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(painterResource(R.drawable.file_open_fill0), null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
|
||||
9
app/src/main/res/drawable/file_export_fill0.xml
Normal file
9
app/src/main/res/drawable/file_export_fill0.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="M480,480ZM202,895l-56,-57 118,-118h-90v-80h226v226h-80v-89L202,895ZM480,880v-80h240v-440L520,360v-200L240,160v400h-80v-400q0,-33 23.5,-56.5T240,80h320l240,240v480q0,33 -23.5,56.5T720,880L480,880Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/file_open_fill0.xml
Normal file
9
app/src/main/res/drawable/file_open_fill0.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="M240,880q-33,0 -56.5,-23.5T160,800v-640q0,-33 23.5,-56.5T240,80h320l240,240v240h-80v-200L520,360v-200L240,160v640h360v80L240,880ZM878,895L760,777v89h-80v-226h226v80h-90l118,118 -56,57ZM240,800v-640,640Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
@@ -376,6 +376,7 @@
|
||||
<string name="search">搜索</string>
|
||||
<string name="app_group">应用组</string>
|
||||
<string name="manage_app_groups">管理组</string>
|
||||
<string name="import_str">导入</string>
|
||||
<string name="edit_app_group">编辑组</string>
|
||||
<string name="add_to_list">添加到列表</string>
|
||||
<string name="remove_from_list">从列表中移除</string>
|
||||
|
||||
@@ -410,6 +410,7 @@
|
||||
<string name="search">Search</string>
|
||||
<string name="app_group">App group</string>
|
||||
<string name="manage_app_groups">Manage groups</string>
|
||||
<string name="import_str">Import</string>
|
||||
<string name="edit_app_group">Edit group</string>
|
||||
<string name="add_to_list">Add to list</string>
|
||||
<string name="remove_from_list">Remove from list</string>
|
||||
|
||||
Reference in New Issue
Block a user