mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 11:05:59 +00:00
Add events notifications
This commit is contained in:
@@ -397,6 +397,7 @@ fun Home(activity: FragmentActivity, vm: MyViewModel) {
|
||||
}
|
||||
composable<AuthSettings> { AuthSettingsScreen(::navigateUp) }
|
||||
composable<ApiSettings> { ApiSettings(::navigateUp) }
|
||||
composable<Notifications> { NotificationsScreen(::navigateUp) }
|
||||
composable<About> { AboutScreen(::navigateUp) }
|
||||
|
||||
composable<Authenticate>(
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
package com.bintianqi.owndroid
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
|
||||
/**
|
||||
* ### Notification channels
|
||||
* - LockTaskMode
|
||||
*
|
||||
* ### Notification IDs
|
||||
* - 1: Stop lock task mode
|
||||
*/
|
||||
object NotificationUtils {
|
||||
fun checkPermission(context: Context): Boolean {
|
||||
return if(Build.VERSION.SDK_INT >= 33)
|
||||
@@ -23,7 +17,33 @@ object NotificationUtils {
|
||||
fun registerChannels(context: Context) {
|
||||
if(Build.VERSION.SDK_INT < 26) return
|
||||
val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val channel = NotificationChannel("LockTaskMode", context.getString(R.string.lock_task_mode), NotificationManager.IMPORTANCE_HIGH)
|
||||
nm.createNotificationChannel(channel)
|
||||
val lockTaskMode = NotificationChannel(Channel.LOCK_TASK_MODE, context.getString(R.string.lock_task_mode), NotificationManager.IMPORTANCE_HIGH)
|
||||
val events = NotificationChannel(Channel.EVENTS, context.getString(R.string.events), NotificationManager.IMPORTANCE_HIGH)
|
||||
nm.createNotificationChannels(listOf(lockTaskMode, events))
|
||||
}
|
||||
fun notify(context: Context, id: Int, notification: Notification) {
|
||||
val sp = context.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||
if(sp.getBoolean("n_$id", true) && checkPermission(context)) {
|
||||
registerChannels(context)
|
||||
val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
nm.notify(id, notification)
|
||||
}
|
||||
}
|
||||
object Channel {
|
||||
const val LOCK_TASK_MODE = "LockTaskMode"
|
||||
const val EVENTS = "Events"
|
||||
}
|
||||
object ID {
|
||||
const val LOCK_TASK_MODE = 1
|
||||
const val PASSWORD_CHANGED = 2
|
||||
const val USER_ADDED = 3
|
||||
const val USER_STARTED = 4
|
||||
const val USER_SWITCHED = 5
|
||||
const val USER_STOPPED = 6
|
||||
const val USER_REMOVED = 7
|
||||
const val BUG_REPORT_SHARED = 8
|
||||
const val BUG_REPORT_SHARING_DECLINED = 9
|
||||
const val BUG_REPORT_FAILED = 10
|
||||
const val SYSTEM_UPDATE_PENDING = 11
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build.VERSION
|
||||
import android.os.PersistableBundle
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.bintianqi.owndroid.dpm.handleNetworkLogs
|
||||
@@ -18,6 +20,9 @@ import com.bintianqi.owndroid.dpm.setDefaultAffiliationID
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
class Receiver : DeviceAdminReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
@@ -82,21 +87,101 @@ class Receiver : DeviceAdminReceiver() {
|
||||
|
||||
override fun onLockTaskModeEntering(context: Context, intent: Intent, pkg: String) {
|
||||
super.onLockTaskModeEntering(context, intent, pkg)
|
||||
if(!NotificationUtils.checkPermission(context)) return
|
||||
NotificationUtils.registerChannels(context)
|
||||
val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val intent = Intent(context, this::class.java).apply { action = "com.bintianqi.owndroid.action.STOP_LOCK_TASK_MODE" }
|
||||
val intent = Intent(context, this::class.java).setAction("com.bintianqi.owndroid.action.STOP_LOCK_TASK_MODE")
|
||||
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
|
||||
val builder = NotificationCompat.Builder(context, "LockTaskMode")
|
||||
val builder = NotificationCompat.Builder(context, NotificationUtils.Channel.LOCK_TASK_MODE)
|
||||
.setContentTitle(context.getText(R.string.lock_task_mode))
|
||||
.setSmallIcon(R.drawable.lock_fill0)
|
||||
.addAction(NotificationCompat.Action.Builder(null, context.getString(R.string.stop), pendingIntent).build())
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
nm.notify(1, builder.build())
|
||||
NotificationUtils.notify(context, NotificationUtils.ID.LOCK_TASK_MODE, builder.build())
|
||||
}
|
||||
|
||||
override fun onLockTaskModeExiting(context: Context, intent: Intent) {
|
||||
super.onLockTaskModeExiting(context, intent)
|
||||
val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
nm.cancel(1)
|
||||
nm.cancel(NotificationUtils.ID.LOCK_TASK_MODE)
|
||||
}
|
||||
|
||||
override fun onPasswordChanged(context: Context, intent: Intent, userHandle: UserHandle) {
|
||||
super.onPasswordChanged(context, intent, userHandle)
|
||||
sendUserRelatedNotification(context, userHandle, NotificationUtils.ID.PASSWORD_CHANGED, R.string.password_changed, R.drawable.password_fill0)
|
||||
}
|
||||
|
||||
override fun onUserAdded(context: Context, intent: Intent, addedUser: UserHandle) {
|
||||
super.onUserAdded(context, intent, addedUser)
|
||||
sendUserRelatedNotification(context, addedUser, NotificationUtils.ID.USER_ADDED, R.string.user_added, R.drawable.person_add_fill0)
|
||||
}
|
||||
|
||||
override fun onUserStarted(context: Context, intent: Intent, startedUser: UserHandle) {
|
||||
super.onUserStarted(context, intent, startedUser)
|
||||
sendUserRelatedNotification(context, startedUser, NotificationUtils.ID.USER_STARTED, R.string.user_started, R.drawable.person_fill0)
|
||||
}
|
||||
|
||||
override fun onUserSwitched(context: Context, intent: Intent, switchedUser: UserHandle) {
|
||||
super.onUserSwitched(context, intent, switchedUser)
|
||||
sendUserRelatedNotification(context, switchedUser, NotificationUtils.ID.USER_SWITCHED, R.string.user_switched, R.drawable.person_fill0)
|
||||
}
|
||||
|
||||
override fun onUserStopped(context: Context, intent: Intent, stoppedUser: UserHandle) {
|
||||
super.onUserStopped(context, intent, stoppedUser)
|
||||
sendUserRelatedNotification(context, stoppedUser, NotificationUtils.ID.USER_STOPPED, R.string.user_stopped, R.drawable.person_fill0)
|
||||
}
|
||||
|
||||
override fun onUserRemoved(context: Context, intent: Intent, removedUser: UserHandle) {
|
||||
super.onUserRemoved(context, intent, removedUser)
|
||||
sendUserRelatedNotification(context, removedUser, NotificationUtils.ID.USER_REMOVED, R.string.user_removed, R.drawable.person_remove_fill0)
|
||||
}
|
||||
|
||||
override fun onBugreportShared(context: Context, intent: Intent, hash: String) {
|
||||
super.onBugreportShared(context, intent, hash)
|
||||
val builder = NotificationCompat.Builder(context, NotificationUtils.Channel.EVENTS)
|
||||
.setContentTitle(context.getString(R.string.bug_report_shared))
|
||||
.setContentText("SHA-256 hash: $hash")
|
||||
.setSmallIcon(R.drawable.bug_report_fill0)
|
||||
NotificationUtils.notify(context, NotificationUtils.ID.BUG_REPORT_SHARED, builder.build())
|
||||
}
|
||||
|
||||
override fun onBugreportSharingDeclined(context: Context, intent: Intent) {
|
||||
super.onBugreportSharingDeclined(context, intent)
|
||||
val builder = NotificationCompat.Builder(context, NotificationUtils.Channel.EVENTS)
|
||||
.setContentTitle(context.getString(R.string.bug_report_sharing_declined))
|
||||
.setSmallIcon(R.drawable.bug_report_fill0)
|
||||
NotificationUtils.notify(context, NotificationUtils.ID.BUG_REPORT_SHARING_DECLINED, builder.build())
|
||||
}
|
||||
|
||||
override fun onBugreportFailed(context: Context, intent: Intent, failureCode: Int) {
|
||||
super.onBugreportFailed(context, intent, failureCode)
|
||||
val message = when(failureCode) {
|
||||
BUGREPORT_FAILURE_FAILED_COMPLETING -> R.string.bug_report_failure_failed_completing
|
||||
BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE -> R.string.bug_report_failure_no_longer_available
|
||||
else -> R.string.place_holder
|
||||
}
|
||||
val builder = NotificationCompat.Builder(context, NotificationUtils.Channel.EVENTS)
|
||||
.setContentTitle(context.getString(R.string.bug_report_failed))
|
||||
.setContentText(context.getString(message))
|
||||
.setSmallIcon(R.drawable.bug_report_fill0)
|
||||
NotificationUtils.notify(context, NotificationUtils.ID.BUG_REPORT_FAILED, builder.build())
|
||||
}
|
||||
|
||||
override fun onSystemUpdatePending(context: Context, intent: Intent, receivedTime: Long) {
|
||||
super.onSystemUpdatePending(context, intent, receivedTime)
|
||||
val time = SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault()).format(Date(receivedTime))
|
||||
val builder = NotificationCompat.Builder(context, NotificationUtils.Channel.EVENTS)
|
||||
.setContentTitle(context.getString(R.string.system_update_pending))
|
||||
.setContentText(context.getString(R.string.received_time) + ": $time")
|
||||
.setSmallIcon(R.drawable.system_update_fill0)
|
||||
NotificationUtils.notify(context, NotificationUtils.ID.SYSTEM_UPDATE_PENDING, builder.build())
|
||||
}
|
||||
|
||||
private fun sendUserRelatedNotification(context: Context, userHandle: UserHandle, id: Int, title: Int, icon: Int) {
|
||||
val um = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||
val serial = um.getSerialNumberForUser(userHandle)
|
||||
val builder = NotificationCompat.Builder(context, NotificationUtils.Channel.EVENTS)
|
||||
.setContentTitle(context.getString(title))
|
||||
.setContentText(context.getString(R.string.serial_number) + ": $serial")
|
||||
.setSmallIcon(icon)
|
||||
NotificationUtils.notify(context, id, builder.build())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ fun SettingsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
FunctionItem(title = R.string.appearance, icon = R.drawable.format_paint_fill0) { onNavigate(Appearance) }
|
||||
FunctionItem(title = R.string.security, icon = R.drawable.lock_fill0) { onNavigate(AuthSettings) }
|
||||
FunctionItem(title = R.string.api, icon = R.drawable.apps_fill0) { onNavigate(ApiSettings) }
|
||||
FunctionItem(R.string.notifications, icon = R.drawable.notifications_fill0) { onNavigate(Notifications) }
|
||||
FunctionItem(title = R.string.export_logs, icon = R.drawable.description_fill0) {
|
||||
val time = SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(Date(System.currentTimeMillis()))
|
||||
exportLogsLauncher.launch("owndroid_log_$time")
|
||||
@@ -219,6 +220,25 @@ fun ApiSettings(onNavigateUp: () -> Unit) {
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object Notifications
|
||||
|
||||
@Composable
|
||||
fun NotificationsScreen(onNavigateUp: () -> Unit) = MyScaffold(R.string.notifications, 0.dp, onNavigateUp) {
|
||||
val sp = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||
val map = mapOf(
|
||||
NotificationUtils.ID.PASSWORD_CHANGED to R.string.password_changed, NotificationUtils.ID.USER_ADDED to R.string.user_added,
|
||||
NotificationUtils.ID.USER_STARTED to R.string.user_started, NotificationUtils.ID.USER_SWITCHED to R.string.user_switched,
|
||||
NotificationUtils.ID.USER_STOPPED to R.string.user_stopped, NotificationUtils.ID.USER_REMOVED to R.string.user_removed,
|
||||
NotificationUtils.ID.BUG_REPORT_SHARED to R.string.bug_report_shared,
|
||||
NotificationUtils.ID.BUG_REPORT_SHARING_DECLINED to R.string.bug_report_sharing_declined,
|
||||
NotificationUtils.ID.BUG_REPORT_FAILED to R.string.bug_report_failed,
|
||||
NotificationUtils.ID.SYSTEM_UPDATE_PENDING to R.string.system_update_pending
|
||||
)
|
||||
map.forEach { (k, v) ->
|
||||
SwitchItem(v, getState = { sp.getBoolean("n_$k", true) }, onCheckedChange = { sp.edit { putBoolean("n_$k", it) } })
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object About
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -1841,6 +1841,7 @@ fun InstallSystemUpdateScreen(onNavigateUp: () -> Unit) {
|
||||
}
|
||||
}
|
||||
var uri by remember { mutableStateOf<Uri?>(null) }
|
||||
var errorMessage by remember { mutableStateOf<String?>(null) }
|
||||
val getFileLauncher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri = it }
|
||||
MyScaffold(R.string.install_system_update, 8.dp, onNavigateUp) {
|
||||
Button(
|
||||
@@ -1859,11 +1860,7 @@ fun InstallSystemUpdateScreen(onNavigateUp: () -> Unit) {
|
||||
dpm.installSystemUpdate(receiver, uri!!, executor, callback)
|
||||
Toast.makeText(context, R.string.start_install_system_update, Toast.LENGTH_SHORT).show()
|
||||
} catch(e: Exception) {
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.install_system_update_failed) + e.cause.toString(),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
errorMessage = e.message
|
||||
}
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
@@ -1874,4 +1871,5 @@ fun InstallSystemUpdateScreen(onNavigateUp: () -> Unit) {
|
||||
Spacer(Modifier.padding(vertical = 10.dp))
|
||||
Notes(R.string.auto_reboot_after_install_succeed)
|
||||
}
|
||||
ErrorDialog(errorMessage) { errorMessage = null }
|
||||
}
|
||||
|
||||
9
app/src/main/res/drawable/person_remove_fill0.xml
Normal file
9
app/src/main/res/drawable/person_remove_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="M640,440v-80h240v80L640,440ZM360,480q-66,0 -113,-47t-47,-113q0,-66 47,-113t113,-47q66,0 113,47t47,113q0,66 -47,113t-113,47ZM40,800v-112q0,-34 17.5,-62.5T104,582q62,-31 126,-46.5T360,520q66,0 130,15.5T616,582q29,15 46.5,43.5T680,688v112L40,800ZM120,720h480v-32q0,-11 -5.5,-20T580,654q-54,-27 -109,-40.5T360,600q-56,0 -111,13.5T140,654q-9,5 -14.5,14t-5.5,20v32ZM360,400q33,0 56.5,-23.5T440,320q0,-33 -23.5,-56.5T360,240q-33,0 -56.5,23.5T280,320q0,33 23.5,56.5T360,400ZM360,320ZM360,720Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
@@ -593,6 +593,7 @@
|
||||
<string name="dark_theme">Тёмная тема</string>
|
||||
<string name="follow_system">Следовать за системой</string>
|
||||
<string name="black_theme">Чёрная тема</string>
|
||||
<string name="notifications">Notifications</string> <!--TODO-->
|
||||
<string name="about">О приложении</string>
|
||||
<string name="project_homepage">Домашняя страница проекта</string>
|
||||
<string name="appearance">Оформление</string>
|
||||
@@ -665,6 +666,8 @@
|
||||
<string name="status_failure_storage">Операция не удалась из-за проблем с хранилищем. Например, на устройстве может быть недостаточно места или внешние носители могут быть недоступны. Вы можете попытаться освободить место или вставить другой внешний носитель.</string>
|
||||
<string name="status_failure_incompatible">Операция не удалась, так как она принципиально несовместима с этим устройством. Например, приложению может потребоваться аппаратная функция, которой нет, в нем может отсутствовать собственный код для ABI, поддерживаемых устройством, или ему требуется более новая версия SDK и т.д.</string>
|
||||
|
||||
<!--TODO: events notification-->
|
||||
|
||||
<string name="info_dhizuku">Dhizuku это инструмент позволяющий делиться правами Владельца устройства с другими приложениями.</string>
|
||||
<string name="info_device_id_attestation">Указывает, поддерживает ли устройство проверку идентификаторов устройств в дополнение к проверке ключей.</string>
|
||||
<string name="info_unique_device_attestation">Да, если реализация StrongBox Keymaster на устройстве была обеспечена индивидуальным сертификатом аттестации и может использовать его для подписи записей аттестации (индивидуальный сертификат аттестации могут использовать только Keymaster с уровнем безопасности StrongBox).</string>
|
||||
|
||||
@@ -597,6 +597,7 @@
|
||||
<string name="dark_theme">Koyu Tema</string>
|
||||
<string name="follow_system">Sistemi Takip Et</string>
|
||||
<string name="black_theme">Siyah Tema</string>
|
||||
<string name="notifications">Notifications</string> <!--TODO-->
|
||||
<string name="about">Hakkında</string>
|
||||
<string name="project_homepage">Proje Ana Sayfası</string>
|
||||
<string name="appearance">Görünüm</string>
|
||||
@@ -668,6 +669,8 @@
|
||||
<string name="status_failure_storage">Depolama sorunları nedeniyle işlem başarısız oldu. Örneğin, cihazda yer azalmış olabilir veya harici medya kullanılamıyor olabilir. Yer açmayı veya farklı bir harici medya takmayı deneyebilirsiniz.</string>
|
||||
<string name="status_failure_incompatible">Bu cihazla temel olarak uyumsuz olduğu için işlem başarısız oldu. Örneğin, uygulama mevcut olmayan bir donanım özelliği gerektirebilir, cihazın desteklediği ABI\'lar için yerel kod eksik olabilir veya daha yeni bir SDK sürümü gerektirebilir vb.</string>
|
||||
|
||||
<!--TODO: events notification-->
|
||||
|
||||
<string name="info_dhizuku">Dhizuku, Cihaz Sahibi izinlerini diğer uygulamalarla paylaşabilen bir araçtır.</string>
|
||||
<string name="info_device_id_attestation">Cihazın, anahtar doğrulamanın yanı sıra cihaz tanımlayıcılarının doğrulamasını destekleyip desteklemediğini belirtir.</string>
|
||||
<string name="info_unique_device_attestation">Evet, eğer cihaz üzerindeki StrongBox Keymaster uygulaması bireysel bir doğrulama sertifikası ile sağlanmışsa ve bunu kullanarak doğrulama kayıtlarını imzalayabiliyorsa (yalnızca StrongBox güvenlik seviyesine sahip Keymaster bireysel doğrulama sertifikası kullanabilir).</string>
|
||||
|
||||
@@ -577,6 +577,7 @@
|
||||
<string name="dark_theme">深色主题</string>
|
||||
<string name="follow_system">跟随系统</string>
|
||||
<string name="black_theme">黑色主题</string>
|
||||
<string name="notifications">通知</string>
|
||||
<string name="about">关于</string>
|
||||
<string name="project_homepage">项目主页</string>
|
||||
<string name="appearance">外观</string>
|
||||
@@ -647,6 +648,21 @@
|
||||
<string name="status_failure_storage">由于存储问题,操作失败。例如,设备空间不足,或外部媒体不可用。你可以尝试清理空间或插入不同的外部媒体。</string>
|
||||
<string name="status_failure_incompatible">操作失败,因为它与设备不兼容。例如,这个app可能需要不存在的硬件功能,它有可能缺少受此设备支持的ABI的本地代码,或它需要高于此设备的SDK版本。</string>
|
||||
|
||||
<string name="events">事件</string>
|
||||
<string name="password_changed">密码已更改</string>
|
||||
<string name="user_added">用户已添加</string>
|
||||
<string name="user_started">用户已启动</string>
|
||||
<string name="user_switched">用户已切换</string>
|
||||
<string name="user_stopped">用户已停止</string>
|
||||
<string name="user_removed">用户已移除</string>
|
||||
<string name="bug_report_shared">错误报告已分享</string>
|
||||
<string name="bug_report_sharing_declined">错误报告已取消分享</string>
|
||||
<string name="bug_report_failed">错误报告失败</string>
|
||||
<string name="bug_report_failure_failed_completing">错误报告完成失败</string>
|
||||
<string name="bug_report_failure_no_longer_available">错误报告不再可收集</string>
|
||||
<string name="system_update_pending">系统更新等待中</string>
|
||||
<string name="received_time">接收时间</string>
|
||||
|
||||
<string name="info_dhizuku">Dhizuku可以分享Device owner权限给其余应用</string>
|
||||
<string name="info_device_id_attestation">指示设备是否除了密钥证明之外还支持设备标识符证明</string>
|
||||
<string name="info_unique_device_attestation">如果设备上的StrongBox Keymaster可以配置单独的证明证书并且可以使用该证书签署证明记录,则返回true(只有StrongBox安全级别的Keymaster才能使用单独的证明证书进行证明)</string>
|
||||
|
||||
@@ -616,6 +616,7 @@
|
||||
<string name="dark_theme">Dark theme</string>
|
||||
<string name="follow_system">Follow system</string>
|
||||
<string name="black_theme">Black theme</string>
|
||||
<string name="notifications">Notifications</string>
|
||||
<string name="about">About</string>
|
||||
<string name="project_homepage">Project homepage</string>
|
||||
<string name="appearance">Appearance</string>
|
||||
@@ -687,6 +688,21 @@
|
||||
<string name="status_failure_storage">The operation failed because of storage issues. For example, the device may be running low on space, or external media may be unavailable. You may try to help free space or insert different external media.</string>
|
||||
<string name="status_failure_incompatible">The operation failed because it is fundamentally incompatible with this device. For example, the app may require a hardware feature that doesn\'t exist, it may be missing native code for the ABIs supported by the device, or it requires a newer SDK version, etc.</string>
|
||||
|
||||
<string name="events">Events</string>
|
||||
<string name="password_changed">Password changed</string>
|
||||
<string name="user_added">User added</string>
|
||||
<string name="user_started">User started</string>
|
||||
<string name="user_switched">User switched</string>
|
||||
<string name="user_stopped">User stopped</string>
|
||||
<string name="user_removed">User removed</string>
|
||||
<string name="bug_report_shared">Bug report shared</string>
|
||||
<string name="bug_report_sharing_declined">Bug report sharing declined</string>
|
||||
<string name="bug_report_failed">Bug report failed</string>
|
||||
<string name="bug_report_failure_failed_completing">Bug report completion process failed</string>
|
||||
<string name="bug_report_failure_no_longer_available">Bug report is no longer available for collection</string>
|
||||
<string name="system_update_pending">System update pending</string>
|
||||
<string name="received_time">Received time</string>
|
||||
|
||||
<string name="info_dhizuku">Dhizuku is a tool that can share Device owner permissions to other application.</string>
|
||||
<string name="info_device_id_attestation">Indicates if the device supports attestation of device identifiers in addition to key attestation.</string>
|
||||
<string name="info_unique_device_attestation">Yes if the StrongBox Keymaster implementation on the device was provisioned with an individual attestation certificate and can sign attestation records using it (only Keymaster with StrongBox security level can use an individual attestation certificate).</string>
|
||||
|
||||
Reference in New Issue
Block a user