mirror of
https://codeberg.org/timelimit/timelimit-android.git
synced 2025-10-05 02:39:30 +02:00
Move device owner organization name to the device owner screen
This commit is contained in:
parent
8fb102390f
commit
34f7bab46d
13 changed files with 104 additions and 151 deletions
|
@ -333,7 +333,7 @@ abstract class ConfigDao {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun getCustomOrganizationName(): String = getValueOfKeyCoroutine(ConfigurationItemType.CustomOrganizationName) ?: ""
|
suspend fun getCustomOrganizationName(): String? = getValueOfKeyCoroutine(ConfigurationItemType.CustomOrganizationName)
|
||||||
fun setCustomOrganizationName(value: String) = updateValueSync(ConfigurationItemType.CustomOrganizationName, value)
|
fun setCustomOrganizationName(value: String) = updateValueSync(ConfigurationItemType.CustomOrganizationName, value)
|
||||||
|
|
||||||
fun getServerApiLevelSync() = getValueOfKeySync(ConfigurationItemType.ServerApiLevel).let { it?.toInt() ?: 0 }
|
fun getServerApiLevelSync() = getValueOfKeySync(ConfigurationItemType.ServerApiLevel).let { it?.toInt() ?: 0 }
|
||||||
|
|
|
@ -22,4 +22,5 @@ interface DeviceOwnerApi {
|
||||||
|
|
||||||
fun setDelegations(packageName: String, scopes: List<DelegationScope>)
|
fun setDelegations(packageName: String, scopes: List<DelegationScope>)
|
||||||
fun getDelegations(): Map<String, List<DelegationScope>>
|
fun getDelegations(): Map<String, List<DelegationScope>>
|
||||||
|
fun setOrganizationName(name: String)
|
||||||
}
|
}
|
|
@ -75,9 +75,6 @@ abstract class PlatformIntegration(
|
||||||
|
|
||||||
// this function requires the device owner permission and a recent android version
|
// this function requires the device owner permission and a recent android version
|
||||||
abstract fun setForceNetworkTime(enable: Boolean)
|
abstract fun setForceNetworkTime(enable: Boolean)
|
||||||
abstract fun canSetOrganizationName(): Boolean
|
|
||||||
abstract fun setOrganizationName(name: String): Boolean
|
|
||||||
|
|
||||||
abstract fun restartApp()
|
abstract fun restartApp()
|
||||||
|
|
||||||
abstract fun getCurrentNetworkId(): NetworkId
|
abstract fun getCurrentNetworkId(): NetworkId
|
||||||
|
|
|
@ -94,4 +94,12 @@ class AndroidDeviceOwnerApi(
|
||||||
entry.value.map { it.second }
|
entry.value.map { it.second }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setOrganizationName(name: String) {
|
||||||
|
if (VERSION.SDK_INT >= VERSION_CODES.O && !BuildConfig.storeCompilant) {
|
||||||
|
if (devicePolicyManager.isDeviceOwnerApp(componentName.packageName)) {
|
||||||
|
devicePolicyManager.setOrganizationName(componentName, name)
|
||||||
|
} else throw SecurityException()
|
||||||
|
} else throw SecurityException()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* TimeLimit Copyright <C> 2019 - 2022 Jonas Lochmann
|
* TimeLimit Copyright <C> 2019 - 2023 Jonas Lochmann
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -629,28 +629,6 @@ class AndroidIntegration(context: Context): PlatformIntegration(maximumProtectio
|
||||||
session.playbackState?.state == PlaybackState.STATE_REWINDING
|
session.playbackState?.state == PlaybackState.STATE_REWINDING
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canSetOrganizationName(): Boolean {
|
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !BuildConfig.storeCompilant) {
|
|
||||||
policyManager.isDeviceOwnerApp(context.packageName)
|
|
||||||
} else false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setOrganizationName(name: String): Boolean {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !BuildConfig.storeCompilant) {
|
|
||||||
if (policyManager.isDeviceOwnerApp(context.packageName)) {
|
|
||||||
return try {
|
|
||||||
policyManager.setOrganizationName(deviceAdmin, name)
|
|
||||||
|
|
||||||
true
|
|
||||||
} catch (ex: SecurityException) {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openSystemPermissionScren(
|
override fun openSystemPermissionScren(
|
||||||
activity: FragmentActivity,
|
activity: FragmentActivity,
|
||||||
permission: SystemPermission,
|
permission: SystemPermission,
|
||||||
|
|
|
@ -181,9 +181,6 @@ class DummyIntegration(
|
||||||
|
|
||||||
override fun getCurrentNetworkId(): NetworkId = NetworkId.NoNetworkConnected
|
override fun getCurrentNetworkId(): NetworkId = NetworkId.NoNetworkConnected
|
||||||
|
|
||||||
override fun canSetOrganizationName(): Boolean = false
|
|
||||||
override fun setOrganizationName(name: String): Boolean = false
|
|
||||||
|
|
||||||
override fun openSystemPermissionScren(
|
override fun openSystemPermissionScren(
|
||||||
activity: FragmentActivity,
|
activity: FragmentActivity,
|
||||||
permission: SystemPermission,
|
permission: SystemPermission,
|
||||||
|
@ -202,5 +199,7 @@ class DummyIntegration(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDelegations(): Map<String, List<DeviceOwnerApi.DelegationScope>> = emptyMap()
|
override fun getDelegations(): Map<String, List<DeviceOwnerApi.DelegationScope>> = emptyMap()
|
||||||
|
|
||||||
|
override fun setOrganizationName(name: String) = throw SecurityException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,12 +80,6 @@ class DiagnoseMainFragment : Fragment(), FragmentWithCustomTitle {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
binding.diagnoseOrganizationNameButton.setOnClickListener {
|
|
||||||
if (auth.requestAuthenticationOrReturnTrue()) {
|
|
||||||
DiagnoseOrganizationNameDialogFragment.newInstance().show(parentFragmentManager)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.diagnoseDom.setOnClickListener {
|
binding.diagnoseDom.setOnClickListener {
|
||||||
requireActivity().execute(UpdateStateCommand.Diagnose.DeviceOwner)
|
requireActivity().execute(UpdateStateCommand.Diagnose.DeviceOwner)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
/*
|
|
||||||
* TimeLimit Copyright <C> 2019 - 2021 Jonas Lochmann
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation version 3 of the License.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package io.timelimit.android.ui.diagnose
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.fragment.app.FragmentManager
|
|
||||||
import io.timelimit.android.R
|
|
||||||
import io.timelimit.android.async.Threads
|
|
||||||
import io.timelimit.android.coroutines.runAsync
|
|
||||||
import io.timelimit.android.data.model.UserType
|
|
||||||
import io.timelimit.android.extensions.showSafe
|
|
||||||
import io.timelimit.android.integration.platform.ProtectionLevel
|
|
||||||
import io.timelimit.android.logic.AppLogic
|
|
||||||
import io.timelimit.android.logic.DefaultAppLogic
|
|
||||||
import io.timelimit.android.ui.main.ActivityViewModel
|
|
||||||
import io.timelimit.android.ui.main.getActivityViewModel
|
|
||||||
import io.timelimit.android.ui.util.EditTextBottomSheetDialog
|
|
||||||
|
|
||||||
class DiagnoseOrganizationNameDialogFragment: EditTextBottomSheetDialog() {
|
|
||||||
companion object {
|
|
||||||
private const val DIALOG_TAG = "DiagnoseOrganizationNameDialogFragment"
|
|
||||||
|
|
||||||
fun newInstance() = DiagnoseOrganizationNameDialogFragment()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val appLogic: AppLogic by lazy { DefaultAppLogic.with(requireContext()) }
|
|
||||||
private val auth: ActivityViewModel by lazy { getActivityViewModel(requireActivity()) }
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
auth.authenticatedUser.observe(this) {
|
|
||||||
if (it?.second?.type != UserType.Parent) {
|
|
||||||
dismissAllowingStateLoss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
binding.title = getString(R.string.diagnose_don_title)
|
|
||||||
|
|
||||||
if (appLogic.platformIntegration.getCurrentProtectionLevel() != ProtectionLevel.DeviceOwner) {
|
|
||||||
Toast.makeText(
|
|
||||||
requireContext(),
|
|
||||||
R.string.diagnose_don_no_owner_toast,
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
|
|
||||||
dismissAllowingStateLoss()
|
|
||||||
} else if (!appLogic.platformIntegration.canSetOrganizationName()) {
|
|
||||||
Toast.makeText(requireContext(), R.string.diagnose_don_not_supported_toast, Toast.LENGTH_SHORT).show()
|
|
||||||
|
|
||||||
dismissAllowingStateLoss()
|
|
||||||
} else {
|
|
||||||
if (savedInstanceState == null) {
|
|
||||||
runAsync {
|
|
||||||
val name = appLogic.database.config().getCustomOrganizationName()
|
|
||||||
|
|
||||||
binding.editText.setText(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun go() {
|
|
||||||
val value = binding.editText.text.toString()
|
|
||||||
|
|
||||||
if (appLogic.platformIntegration.setOrganizationName(value)) {
|
|
||||||
val database = appLogic.database
|
|
||||||
|
|
||||||
Threads.database.execute { database.config().setCustomOrganizationName(value) }
|
|
||||||
} else {
|
|
||||||
Toast.makeText(requireContext(), R.string.diagnose_don_not_supported_toast, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
dismissAllowingStateLoss()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun show(fragmentManager: FragmentManager) = showSafe(fragmentManager, DIALOG_TAG)
|
|
||||||
}
|
|
|
@ -15,11 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package io.timelimit.android.ui.diagnose.deviceowner
|
package io.timelimit.android.ui.diagnose.deviceowner
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
@ -29,6 +31,7 @@ import androidx.compose.runtime.key
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
@ -58,7 +61,22 @@ fun DeviceOwnerScreen(
|
||||||
modifier = modifier.verticalScroll(rememberScrollState()),
|
modifier = modifier.verticalScroll(rememberScrollState()),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
TextField(
|
||||||
|
value = screen.organizationName,
|
||||||
|
onValueChange = screen.actions.updateOrganizationName ?: {},
|
||||||
|
enabled = screen.actions.updateOrganizationName != null,
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||||
|
singleLine = true,
|
||||||
|
label = { Text(stringResource(R.string.diagnose_don_title)) },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
|
||||||
|
AnimatedVisibility(visible = !screen.isParentAuthenticated) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.diagnose_don_auth),
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
stringResource(
|
stringResource(
|
||||||
|
|
|
@ -16,8 +16,12 @@
|
||||||
package io.timelimit.android.ui.model.diagnose
|
package io.timelimit.android.ui.model.diagnose
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.material.SnackbarHostState
|
import androidx.compose.material.SnackbarHostState
|
||||||
|
import io.timelimit.android.BuildConfig
|
||||||
import io.timelimit.android.R
|
import io.timelimit.android.R
|
||||||
|
import io.timelimit.android.async.Threads
|
||||||
|
import io.timelimit.android.coroutines.executeAndWait
|
||||||
import io.timelimit.android.data.IdGenerator
|
import io.timelimit.android.data.IdGenerator
|
||||||
import io.timelimit.android.data.model.App
|
import io.timelimit.android.data.model.App
|
||||||
import io.timelimit.android.extensions.whileTrue
|
import io.timelimit.android.extensions.whileTrue
|
||||||
|
@ -33,21 +37,33 @@ import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.channels.ReceiveChannel
|
import kotlinx.coroutines.channels.ReceiveChannel
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
object DeviceOwnerHandling {
|
object DeviceOwnerHandling {
|
||||||
|
private const val LOG_TAG = "DeviceOwnerHandling"
|
||||||
|
|
||||||
data class OwnerState(
|
data class OwnerState(
|
||||||
val appListDialog: AppListDialog? = null,
|
val appListDialog: AppListDialog? = null,
|
||||||
val apps: List<String> = emptyList()
|
val apps: List<String> = emptyList(),
|
||||||
): java.io.Serializable {
|
val organizationName: OrganizationName = OrganizationName.Original
|
||||||
|
): Serializable {
|
||||||
data class AppListDialog(
|
data class AppListDialog(
|
||||||
val filter: String = ""
|
val filter: String = ""
|
||||||
): java.io.Serializable
|
): Serializable
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class OrganizationName: Serializable {
|
||||||
|
object Original: OrganizationName()
|
||||||
|
object Error: OrganizationName()
|
||||||
|
class Modified(val value: String): OrganizationName()
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class OwnerScreen {
|
sealed class OwnerScreen {
|
||||||
object Error: OwnerScreen()
|
object Error: OwnerScreen()
|
||||||
|
|
||||||
data class Normal(
|
data class Normal(
|
||||||
|
val isParentAuthenticated: Boolean,
|
||||||
|
val organizationName: String,
|
||||||
val appListDialog: AppListDialog?,
|
val appListDialog: AppListDialog?,
|
||||||
val scopes: List<DeviceOwnerApi.DelegationScope>,
|
val scopes: List<DeviceOwnerApi.DelegationScope>,
|
||||||
val apps: List<AppInfo>,
|
val apps: List<AppInfo>,
|
||||||
|
@ -66,6 +82,7 @@ object DeviceOwnerHandling {
|
||||||
)
|
)
|
||||||
|
|
||||||
data class Actions(
|
data class Actions(
|
||||||
|
val updateOrganizationName: ((String) -> Unit)?,
|
||||||
val showAppListDialog: () -> Unit,
|
val showAppListDialog: () -> Unit,
|
||||||
val dismissAppListDialog: () -> Unit,
|
val dismissAppListDialog: () -> Unit,
|
||||||
val addApp: (String) -> Unit,
|
val addApp: (String) -> Unit,
|
||||||
|
@ -132,7 +149,40 @@ object DeviceOwnerHandling {
|
||||||
|
|
||||||
val refreshSignal = Channel<Unit>(Channel.CONFLATED)
|
val refreshSignal = Channel<Unit>(Channel.CONFLATED)
|
||||||
|
|
||||||
|
val hadUpdateOrganizationNameErrorLive = state.map { it.organizationName == OrganizationName.Error }.distinctUntilChanged()
|
||||||
|
val isParentAuthenticatedLive = authentication.authenticatedParentOnly.map { it != null }.distinctUntilChanged()
|
||||||
|
|
||||||
|
val organizationNameLive = state.map { it.organizationName }.distinctUntilChanged().map {
|
||||||
|
when (it) {
|
||||||
|
is OrganizationName.Modified -> it.value
|
||||||
|
is OrganizationName.Error, OrganizationName.Original -> logic.database.config().getCustomOrganizationName() ?: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val actions = OwnerScreen.Normal.Actions(
|
val actions = OwnerScreen.Normal.Actions(
|
||||||
|
updateOrganizationName = { organizationName ->
|
||||||
|
updateState { state ->
|
||||||
|
if (state.organizationName == OrganizationName.Error) state
|
||||||
|
else state.copy(organizationName = OrganizationName.Modified(organizationName))
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
if (isParentAuthenticatedLive.first()) try {
|
||||||
|
owner.setOrganizationName(organizationName)
|
||||||
|
|
||||||
|
Threads.database.executeAndWait {
|
||||||
|
logic.database.config().setCustomOrganizationName(organizationName)
|
||||||
|
}
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
updateState { it.copy(organizationName = OrganizationName.Error) }
|
||||||
|
|
||||||
|
throw ex
|
||||||
|
} else updateState { state ->
|
||||||
|
if (state.organizationName == OrganizationName.Error) state
|
||||||
|
else state.copy(organizationName = OrganizationName.Original)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
addApp = { packageName ->
|
addApp = { packageName ->
|
||||||
launch {
|
launch {
|
||||||
if (authentication.authenticatedParentOnly.first() != null) updateState { state ->
|
if (authentication.authenticatedParentOnly.first() != null) updateState { state ->
|
||||||
|
@ -182,16 +232,30 @@ object DeviceOwnerHandling {
|
||||||
)
|
)
|
||||||
|
|
||||||
emitAll(
|
emitAll(
|
||||||
appsLive.combine(dialogLive) { apps, dialog ->
|
combine(
|
||||||
|
appsLive, dialogLive, hadUpdateOrganizationNameErrorLive, isParentAuthenticatedLive, organizationNameLive
|
||||||
|
) { apps, dialog, hadUpdateOrganizationNameError, isParentAuthenticated, organizationName ->
|
||||||
OwnerScreen.Normal(
|
OwnerScreen.Normal(
|
||||||
|
isParentAuthenticated = isParentAuthenticated,
|
||||||
|
organizationName = organizationName,
|
||||||
appListDialog = dialog,
|
appListDialog = dialog,
|
||||||
scopes = scopes,
|
scopes = scopes,
|
||||||
apps = apps,
|
apps = apps,
|
||||||
actions = actions
|
actions = actions.copy(
|
||||||
|
updateOrganizationName =
|
||||||
|
if (hadUpdateOrganizationNameError || !isParentAuthenticated) null
|
||||||
|
else actions.updateOrganizationName
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}.catch { emit(OwnerScreen.Error) }
|
}.catch {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.w(LOG_TAG, "error during generating screen", it)
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(OwnerScreen.Error)
|
||||||
|
}
|
||||||
|
|
||||||
private fun getApps(
|
private fun getApps(
|
||||||
integration: PlatformIntegration,
|
integration: PlatformIntegration,
|
||||||
|
|
|
@ -87,13 +87,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<Button
|
|
||||||
style="?materialButtonOutlinedStyle"
|
|
||||||
android:id="@+id/diagnose_organization_name_button"
|
|
||||||
android:text="@string/diagnose_don_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
style="?materialButtonOutlinedStyle"
|
style="?materialButtonOutlinedStyle"
|
||||||
android:id="@+id/diagnose_dom"
|
android:id="@+id/diagnose_dom"
|
||||||
|
|
|
@ -561,8 +561,7 @@
|
||||||
<string name="diagnose_bat_level">Akkustand: %d\%%</string>
|
<string name="diagnose_bat_level">Akkustand: %d\%%</string>
|
||||||
|
|
||||||
<string name="diagnose_don_title">Gerätebesitzerorganisationsname</string>
|
<string name="diagnose_don_title">Gerätebesitzerorganisationsname</string>
|
||||||
<string name="diagnose_don_no_owner_toast">TimeLimit ist KEIN Geräte-Besitzer</string>
|
<string name="diagnose_don_auth">Melden Sie sich an, um den Namen zu ändern</string>
|
||||||
<string name="diagnose_don_not_supported_toast">Ihr System ermöglicht es nicht, einen Organisationsnamen zu hinterlegen</string>
|
|
||||||
|
|
||||||
<string name="diagnose_dom_title">Geräte-Besitzer</string>
|
<string name="diagnose_dom_title">Geräte-Besitzer</string>
|
||||||
<string name="diagnose_dom_error">Diese Funktion erfordert eine ausreichend neue Android-Version und die Geräte-Besitzer-Berechtigung</string>
|
<string name="diagnose_dom_error">Diese Funktion erfordert eine ausreichend neue Android-Version und die Geräte-Besitzer-Berechtigung</string>
|
||||||
|
|
|
@ -614,8 +614,7 @@
|
||||||
<string name="diagnose_bat_level">Level: %d\%%</string>
|
<string name="diagnose_bat_level">Level: %d\%%</string>
|
||||||
|
|
||||||
<string name="diagnose_don_title">Device Owner Organization Name</string>
|
<string name="diagnose_don_title">Device Owner Organization Name</string>
|
||||||
<string name="diagnose_don_no_owner_toast">TimeLimit is NOT set as device owner</string>
|
<string name="diagnose_don_auth">Sign in to change the name</string>
|
||||||
<string name="diagnose_don_not_supported_toast">Your system does not support setting the organization name</string>
|
|
||||||
|
|
||||||
<string name="diagnose_dom_title">Device Owner</string>
|
<string name="diagnose_dom_title">Device Owner</string>
|
||||||
<string name="diagnose_dom_error">You need a recent Android version and the device owner permission to use this</string>
|
<string name="diagnose_dom_error">You need a recent Android version and the device owner permission to use this</string>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue