mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +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 }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user