feat: snapshot notification
Some checks failed
Build-Apk / build (push) Has been cancelled

This commit is contained in:
lisonge 2024-09-28 18:25:14 +08:00
parent 0decf9a854
commit 876c047eb7
10 changed files with 77 additions and 37 deletions

View File

@ -17,9 +17,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
import li.songe.gkd.app
import li.songe.gkd.appScope
import li.songe.gkd.data.Tuple3
import li.songe.gkd.notif.createNotif
import li.songe.gkd.notif.floatingChannel
import li.songe.gkd.notif.floatingNotif
import li.songe.gkd.notif.notifyService
import li.songe.gkd.util.launchTry
import kotlin.math.sqrt
@ -79,7 +78,7 @@ class FloatingService : ExpandableBubbleService() {
override fun startNotificationForeground() {
createNotif(this, floatingChannel.id, floatingNotif)
floatingNotif.notifyService(this)
}
override fun onDestroy() {

View File

@ -39,9 +39,8 @@ import li.songe.gkd.data.deleteSubscription
import li.songe.gkd.data.selfAppInfo
import li.songe.gkd.db.DbSet
import li.songe.gkd.debug.SnapshotExt.captureSnapshot
import li.songe.gkd.notif.createNotif
import li.songe.gkd.notif.httpChannel
import li.songe.gkd.notif.httpNotif
import li.songe.gkd.notif.notifyService
import li.songe.gkd.service.A11yService
import li.songe.gkd.util.LOCAL_HTTP_SUBS_ID
import li.songe.gkd.util.SERVER_SCRIPT_URL
@ -79,11 +78,7 @@ class HttpService : Service() {
stopSelf()
return@collect
}
createNotif(
this@HttpService,
httpChannel.id,
httpNotif.copy(text = "HTTP服务-$port")
)
httpNotif.copy(text = "HTTP服务-$port").notifyService(this@HttpService)
}
}
}

View File

@ -8,8 +8,7 @@ import android.content.Intent
import com.blankj.utilcode.util.LogUtils
import kotlinx.coroutines.flow.MutableStateFlow
import li.songe.gkd.app
import li.songe.gkd.notif.createNotif
import li.songe.gkd.notif.screenshotChannel
import li.songe.gkd.notif.notifyService
import li.songe.gkd.notif.screenshotNotif
import li.songe.gkd.util.ScreenshotUtil
@ -19,7 +18,7 @@ class ScreenshotService : Service() {
override fun onCreate() {
super.onCreate()
isRunning.value = true
createNotif(this, screenshotChannel.id, screenshotNotif)
screenshotNotif.notifyService(this)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

View File

@ -18,6 +18,8 @@ import li.songe.gkd.data.RpcError
import li.songe.gkd.data.createComplexSnapshot
import li.songe.gkd.data.toSnapshot
import li.songe.gkd.db.DbSet
import li.songe.gkd.notif.notify
import li.songe.gkd.notif.snapshotNotif
import li.songe.gkd.service.A11yService
import li.songe.gkd.util.appInfoCacheFlow
import li.songe.gkd.util.keepNullJson
@ -142,6 +144,14 @@ object SnapshotExt {
DbSet.snapshotDao.insert(snapshot.toSnapshot())
}
toast("快照成功")
val desc = snapshot.appInfo?.name ?: snapshot.appId
snapshotNotif.copy(
text = if (desc != null) {
"快照[$desc]已保存至记录"
} else {
snapshotNotif.text
}
).notify()
return snapshot
} finally {
captureLoading.value = false

View File

@ -5,6 +5,7 @@ import li.songe.gkd.util.SafeR
data class Notif(
val channel: NotifChannel,
val id: Int,
val smallIcon: Int = SafeR.ic_status,
val title: String = app.getString(SafeR.app_name),
@ -16,6 +17,7 @@ data class Notif(
val abNotif by lazy {
Notif(
channel = defaultChannel,
id = 100,
text = "无障碍正在运行",
ongoing = true,
@ -25,6 +27,7 @@ val abNotif by lazy {
val screenshotNotif by lazy {
Notif(
channel = screenshotChannel,
id = 101,
text = "截屏服务正在运行",
ongoing = true,
@ -35,6 +38,7 @@ val screenshotNotif by lazy {
val floatingNotif by lazy {
Notif(
channel = floatingChannel,
id = 102,
text = "悬浮窗按钮正在显示",
ongoing = true,
@ -45,10 +49,22 @@ val floatingNotif by lazy {
val httpNotif by lazy {
Notif(
channel = httpChannel,
id = 103,
text = "HTTP服务正在运行",
ongoing = true,
autoCancel = false,
uri = "gkd://page/1",
)
}
val snapshotNotif by lazy {
Notif(
channel = snapshotChannel,
id = 104,
text = "快照已保存至记录",
ongoing = false,
autoCancel = true,
uri = "gkd://page/2",
)
}

View File

@ -29,10 +29,16 @@ val httpChannel by lazy {
id = "http", name = "HTTP服务", desc = "用于连接Web端工具调试"
)
}
val snapshotChannel by lazy {
NotifChannel(
id = "snapshot", name = "快照通知", desc = "捕获快照后发出通知"
)
}
fun initChannel() {
createChannel(app, defaultChannel)
createChannel(app, floatingChannel)
createChannel(app, screenshotChannel)
createChannel(app, httpChannel)
createChannel(app, snapshotChannel)
}

View File

@ -1,5 +1,7 @@
package li.songe.gkd.notif
import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
@ -12,6 +14,8 @@ import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import li.songe.gkd.MainActivity
import li.songe.gkd.app
import li.songe.gkd.permission.notificationState
fun createChannel(context: Context, notifChannel: NotifChannel) {
val importance = NotificationManager.IMPORTANCE_LOW
@ -21,30 +25,41 @@ fun createChannel(context: Context, notifChannel: NotifChannel) {
notificationManager.createNotificationChannel(channel)
}
fun createNotif(context: Service, channelId: String, notif: Notif) {
private fun Notif.toNotification(): Notification {
val pendingIntent = PendingIntent.getActivity(
context,
app,
0,
Intent(context, MainActivity::class.java).apply {
Intent(app, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
notif.uri?.let { data = Uri.parse(it) }
uri?.let { data = Uri.parse(it) }
},
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val notification = NotificationCompat.Builder(context, channelId)
.setSmallIcon(notif.smallIcon)
.setContentTitle(notif.title)
.setContentText(notif.text)
val notification = NotificationCompat.Builder(app, channel.id)
.setSmallIcon(smallIcon)
.setContentTitle(title)
.setContentText(text)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setOngoing(notif.ongoing)
.setAutoCancel(notif.autoCancel)
.setOngoing(ongoing)
.setAutoCancel(autoCancel)
.build()
return notification
}
@SuppressLint("MissingPermission")
fun Notif.notify() {
if (notificationState.updateAndGet()) {
NotificationManagerCompat.from(app).notify(id, toNotification())
}
}
fun Notif.notifyService(context: Service) {
val notification = toNotification()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
context.startForeground(
notif.id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST
id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST
)
} else {
context.startForeground(notif.id, notification)
context.startForeground(id, notification)
}
}
}

View File

@ -70,7 +70,7 @@ private suspend fun asyncRequestPermission(
val notificationState by lazy {
PermissionState(
check = {
XXPermissions.isGranted(app, Permission.NOTIFICATION_SERVICE)
XXPermissions.isGranted(app, Permission.POST_NOTIFICATIONS)
},
request = {
asyncRequestPermission(it, Permission.POST_NOTIFICATIONS)

View File

@ -12,8 +12,7 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import li.songe.gkd.app
import li.songe.gkd.notif.abNotif
import li.songe.gkd.notif.createNotif
import li.songe.gkd.notif.defaultChannel
import li.songe.gkd.notif.notifyService
import li.songe.gkd.permission.notificationState
import li.songe.gkd.util.actionCountFlow
import li.songe.gkd.util.getSubsStatus
@ -27,7 +26,7 @@ class ManageService : Service() {
override fun onCreate() {
super.onCreate()
isRunning.value = true
createNotif(this, defaultChannel.id, abNotif)
abNotif.notifyService(this)
scope.launch {
combine(
A11yService.isRunning,
@ -46,11 +45,7 @@ class ManageService : Service() {
}
return@combine getSubsStatus(ruleSummary, count)
}.debounce(500L).stateIn(scope, SharingStarted.Eagerly, "").collect { text ->
createNotif(
this@ManageService,
defaultChannel.id,
abNotif.copy(text = text)
)
abNotif.copy(text = text).notifyService(this@ManageService)
}
}
}

View File

@ -18,6 +18,7 @@ import com.blankj.utilcode.util.LogUtils
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.AdvancedPageDestination
import com.ramcosta.composedestinations.generated.destinations.SnapshotPageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
@ -69,6 +70,10 @@ fun HomePage() {
"/1" -> {
navController.toDestinationsNavigator().navigate(AdvancedPageDestination)
}
"/2" -> {
navController.toDestinationsNavigator().navigate(SnapshotPageDestination)
}
}
}
})
@ -100,4 +105,4 @@ fun HomePage() {
},
content = currentPage.content
)
}
}