From 1cd4eb330b513fce3ecd037c8043fb87ffbbc540 Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Sat, 13 Jun 2026 09:04:58 +0700 Subject: [PATCH] allow user stop service --- .../src/androidMain/AndroidManifest.xml | 4 +-- .../su/reya/coop/NostrForegroundService.kt | 27 +++++++++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/composeApp/src/androidMain/AndroidManifest.xml b/composeApp/src/androidMain/AndroidManifest.xml index b396cd3..58fb629 100644 --- a/composeApp/src/androidMain/AndroidManifest.xml +++ b/composeApp/src/androidMain/AndroidManifest.xml @@ -8,7 +8,7 @@ - + @@ -59,7 +59,7 @@ android:name=".NostrForegroundService" android:enabled="true" android:exported="false" - android:foregroundServiceType="dataSync" /> + android:foregroundServiceType="remoteMessaging" /> \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/NostrForegroundService.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/NostrForegroundService.kt index add9fb2..abb13ad 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/NostrForegroundService.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/NostrForegroundService.kt @@ -22,6 +22,8 @@ import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import java.io.File +private const val GROUP_KEY_MESSAGES = "su.reya.coop.MESSAGES" + class NostrForegroundService : Service() { private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) private val nostr by lazy { NostrManager.instance } @@ -29,10 +31,6 @@ class NostrForegroundService : Service() { override fun onBind(intent: Intent?): IBinder? = null - private fun isUserInApp(): Boolean { - return ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) - } - override fun onCreate() { super.onCreate() createNotificationChannel() @@ -40,6 +38,13 @@ class NostrForegroundService : Service() { } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + if (intent?.action == "STOP_SERVICE") { + stopForeground(STOP_FOREGROUND_REMOVE) + stopSelf() + return START_NOT_STICKY + } + + // Start the nostr service in the foreground startAsForeground() // Check if the service is already running @@ -90,15 +95,25 @@ class NostrForegroundService : Service() { return START_STICKY } + private fun isUserInApp(): Boolean { + return ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) + } + private fun startAsForeground() { val notification = createNotification() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - startForeground(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC) + startForeground(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING) } else { startForeground(1, notification) } } + private fun getStopServicePendingIntent(): PendingIntent { + val intent = Intent(this, NostrForegroundService::class.java).apply { + action = "STOP_SERVICE" + } + return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_IMMUTABLE) + } private fun createNotificationChannel() { val manager = getSystemService(NotificationManager::class.java) @@ -122,10 +137,12 @@ class NostrForegroundService : Service() { private fun createNotification(content: String? = null): Notification { val builder = NotificationCompat.Builder(this, "nostr_service") + .setGroup(GROUP_KEY_MESSAGES) .setSmallIcon(R.drawable.ic_notification) .setOngoing(true) .setPriority(NotificationCompat.PRIORITY_MIN) .setCategory(Notification.CATEGORY_SERVICE) + .addAction(R.drawable.ic_notification, "Stop", getStopServicePendingIntent()) if (content != null) { builder.setContentTitle("Coop")