Fix concurrent notification

This commit is contained in:
arm64v8a 2023-06-29 21:24:27 +09:00
parent 71094bac5a
commit 022cd798a9

View File

@ -19,8 +19,11 @@ import io.nekohasekai.sagernet.database.ProxyEntity
import io.nekohasekai.sagernet.database.SagerDatabase import io.nekohasekai.sagernet.database.SagerDatabase
import io.nekohasekai.sagernet.ktx.app import io.nekohasekai.sagernet.ktx.app
import io.nekohasekai.sagernet.ktx.getColorAttr import io.nekohasekai.sagernet.ktx.getColorAttr
import io.nekohasekai.sagernet.ktx.runOnMainDispatcher
import io.nekohasekai.sagernet.ui.SwitchActivity import io.nekohasekai.sagernet.ui.SwitchActivity
import io.nekohasekai.sagernet.utils.Theme import io.nekohasekai.sagernet.utils.Theme
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
/** /**
* User can customize visibility of notification since Android 8. * User can customize visibility of notification since Android 8.
@ -50,8 +53,8 @@ class ServiceNotification(
var listenPostSpeed = true var listenPostSpeed = true
fun postNotificationSpeedUpdate(stats: SpeedDisplayData) { suspend fun postNotificationSpeedUpdate(stats: SpeedDisplayData) {
builder.apply { useBuilder {
if (showDirectSpeed) { if (showDirectSpeed) {
val speedDetail = (service as Context).getString( val speedDetail = (service as Context).getString(
R.string.speed_detail, service.getString( R.string.speed_detail, service.getString(
@ -66,8 +69,8 @@ class ServiceNotification(
Formatter.formatFileSize(service, stats.rxRateDirect) Formatter.formatFileSize(service, stats.rxRateDirect)
) )
) )
setStyle(NotificationCompat.BigTextStyle().bigText(speedDetail)) it.setStyle(NotificationCompat.BigTextStyle().bigText(speedDetail))
setContentText(speedDetail) it.setContentText(speedDetail)
} else { } else {
val speedSimple = (service as Context).getString( val speedSimple = (service as Context).getString(
R.string.traffic, service.getString( R.string.traffic, service.getString(
@ -76,9 +79,9 @@ class ServiceNotification(
R.string.speed, Formatter.formatFileSize(service, stats.rxRateProxy) R.string.speed, Formatter.formatFileSize(service, stats.rxRateProxy)
) )
) )
setContentText(speedSimple) it.setContentText(speedSimple)
} }
setSubText( it.setSubText(
service.getString( service.getString(
R.string.traffic, R.string.traffic,
Formatter.formatFileSize(service, stats.txTotal), Formatter.formatFileSize(service, stats.txTotal),
@ -89,15 +92,19 @@ class ServiceNotification(
update() update()
} }
fun postNotificationTitle(newTitle: String) { suspend fun postNotificationTitle(newTitle: String) {
builder.setContentTitle(newTitle) useBuilder {
it.setContentTitle(newTitle)
}
update() update()
} }
fun postNotificationWakeLockStatus(acquired: Boolean) { suspend fun postNotificationWakeLockStatus(acquired: Boolean) {
updateActions() updateActions()
builder.priority = useBuilder {
if (acquired) NotificationCompat.PRIORITY_HIGH else NotificationCompat.PRIORITY_LOW it.priority =
if (acquired) NotificationCompat.PRIORITY_HIGH else NotificationCompat.PRIORITY_LOW
}
update() update()
} }
@ -113,9 +120,16 @@ class ServiceNotification(
.setCategory(NotificationCompat.CATEGORY_SERVICE) .setCategory(NotificationCompat.CATEGORY_SERVICE)
.setPriority(if (visible) NotificationCompat.PRIORITY_LOW else NotificationCompat.PRIORITY_MIN) .setPriority(if (visible) NotificationCompat.PRIORITY_LOW else NotificationCompat.PRIORITY_MIN)
private val buildLock = Mutex()
private suspend fun useBuilder(f: (NotificationCompat.Builder) -> Unit) {
buildLock.withLock {
f(builder)
}
}
init { init {
service as Context service as Context
updateActions()
Theme.apply(app) Theme.apply(app)
Theme.apply(service) Theme.apply(service)
@ -125,46 +139,40 @@ class ServiceNotification(
addAction(Intent.ACTION_SCREEN_ON) addAction(Intent.ACTION_SCREEN_ON)
addAction(Intent.ACTION_SCREEN_OFF) addAction(Intent.ACTION_SCREEN_OFF)
}) })
show()
runOnMainDispatcher {
updateActions()
show()
}
} }
private fun updateActions() { private suspend fun updateActions() {
service as Context service as Context
builder.clearActions() useBuilder {
it.clearActions()
val closeAction = NotificationCompat.Action.Builder( val closeAction = NotificationCompat.Action.Builder(
0, service.getText(R.string.stop), PendingIntent.getBroadcast( 0, service.getText(R.string.stop), PendingIntent.getBroadcast(
service, 0, Intent(Action.CLOSE).setPackage(service.packageName), flags service, 0, Intent(Action.CLOSE).setPackage(service.packageName), flags
) )
).setShowsUserInterface(false).build() ).setShowsUserInterface(false).build()
builder.addAction(closeAction) it.addAction(closeAction)
val switchAction = NotificationCompat.Action.Builder( val switchAction = NotificationCompat.Action.Builder(
0, service.getString(R.string.action_switch), PendingIntent.getActivity( 0, service.getString(R.string.action_switch), PendingIntent.getActivity(
service, 0, Intent(service, SwitchActivity::class.java), flags service, 0, Intent(service, SwitchActivity::class.java), flags
) )
).setShowsUserInterface(false).build() ).setShowsUserInterface(false).build()
builder.addAction(switchAction) it.addAction(switchAction)
val resetUpstreamAction = NotificationCompat.Action.Builder( val resetUpstreamAction = NotificationCompat.Action.Builder(
0, service.getString(R.string.reset_connections), 0, service.getString(R.string.reset_connections),
PendingIntent.getBroadcast( PendingIntent.getBroadcast(
service, 0, Intent(Action.RESET_UPSTREAM_CONNECTIONS), flags service, 0, Intent(Action.RESET_UPSTREAM_CONNECTIONS), flags
) )
).setShowsUserInterface(false).build() ).setShowsUserInterface(false).build()
builder.addAction(resetUpstreamAction) it.addAction(resetUpstreamAction)
}
// val wakeLockAction = NotificationCompat.Action.Builder(
// 0,
// service.getText(if (!wakeLockAcquired) R.string.acquire_wake_lock else R.string.release_wake_lock),
// PendingIntent.getBroadcast(
// service,
// 0,
// Intent(Action.SWITCH_WAKE_LOCK).setPackage(service.packageName),
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0
// )
// ).setShowsUserInterface(false).build()
// builder.addAction(wakeLockAction)
} }
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
@ -174,9 +182,12 @@ class ServiceNotification(
} }
private fun show() = (service as Service).startForeground(notificationId, builder.build()) private suspend fun show() =
private fun update() = useBuilder { (service as Service).startForeground(notificationId, it.build()) }
NotificationManagerCompat.from(service as Service).notify(notificationId, builder.build())
private suspend fun update() = useBuilder {
NotificationManagerCompat.from(service as Service).notify(notificationId, it.build())
}
fun destroy() { fun destroy() {
listenPostSpeed = false listenPostSpeed = false