From 8600d4dfc3e3288f97afd34ed9b5b618e8ae92c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20W=C3=BCrl?= Date: Sat, 30 Aug 2025 21:49:24 +0100 Subject: [PATCH 1/2] create separate notification channels --- .../app/controller/NotificationHandler.kt | 56 +++++++++++++------ app/src/main/res/values/strings.xml | 4 ++ 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/blitzortung/android/app/controller/NotificationHandler.kt b/app/src/main/java/org/blitzortung/android/app/controller/NotificationHandler.kt index 8a2f3ad87..1be76c314 100644 --- a/app/src/main/java/org/blitzortung/android/app/controller/NotificationHandler.kt +++ b/app/src/main/java/org/blitzortung/android/app/controller/NotificationHandler.kt @@ -22,10 +22,12 @@ package org.blitzortung.android.app.controller import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager +import android.app.NotificationManager.IMPORTANCE_HIGH import android.app.NotificationManager.IMPORTANCE_LOW import android.app.PendingIntent import android.content.Context import android.content.Intent +import android.media.AudioAttributes import android.os.Build import androidx.annotation.RequiresApi @@ -41,11 +43,11 @@ open class NotificationHandler @Inject constructor( init { if (isAtLeast(Build.VERSION_CODES.O)) { - createNotificationChannel() + createNotificationChannels() // Renamed from createNotificationChannel } } - fun sendNotification(notificationText: String) { + fun sendNotification(notificationText: String, isCloseAlarm: Boolean) { // Added isCloseAlarm parameter val intent = Intent(context, Main::class.java).apply { action = Intent.ACTION_MAIN flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK @@ -59,7 +61,7 @@ open class NotificationHandler @Inject constructor( val notification = when { isAtLeast(Build.VERSION_CODES.O) -> { - createNotification(contentIntent, notificationText) + createNotification(contentIntent, notificationText, isCloseAlarm) // Pass isCloseAlarm } else -> { @@ -71,8 +73,9 @@ open class NotificationHandler @Inject constructor( } @RequiresApi(Build.VERSION_CODES.O) - private fun createNotification(contentIntent: PendingIntent?, notificationText: String): Notification { - return Notification.Builder(context, CHANNEL_ID) + private fun createNotification(contentIntent: PendingIntent?, notificationText: String, isCloseAlarm: Boolean): Notification { + val channelId = if (isCloseAlarm) CLOSE_CHANNEL_ID else DISTANT_CHANNEL_ID + return Notification.Builder(context, channelId) // Use dynamic channelId .setSmallIcon(R.drawable.icon) .setContentTitle(context.resources.getText(R.string.app_name)) .setContentText(notificationText) @@ -98,22 +101,41 @@ open class NotificationHandler @Inject constructor( return builder.build() } - private fun createNotificationChannel() { - // Create the NotificationChannel, but only on API 26+ because - // the NotificationChannel class is new and not in the support library - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val name = context.getString(R.string.notification_channel_name) - val importance = NotificationManager.IMPORTANCE_DEFAULT - val channel = NotificationChannel(CHANNEL_ID, name, importance).apply { - setImportance(IMPORTANCE_LOW) - } - // Register the channel with the system - notificationManager.createNotificationChannel(channel) + @RequiresApi(Build.VERSION_CODES.O) + private fun createNotificationChannels() { // Renamed method + // Create the "distant" channel + val distantName = context.getString(R.string.notification_channel_distant_name) + val distantChannel = NotificationChannel(DISTANT_CHANNEL_ID, distantName, IMPORTANCE_LOW).apply { + description = context.getString(R.string.notification_channel_distant_description) + enableLights(false) + enableVibration(false) + setSound(null, null) // No sound + // setBypassDnd(false) // Default is false, explicitly state for clarity if desired + } + notificationManager.createNotificationChannel(distantChannel) + + // Create the "close" channel + val closeName = context.getString(R.string.notification_channel_close_name) + val closeChannel = NotificationChannel(CLOSE_CHANNEL_ID, closeName, IMPORTANCE_HIGH).apply { + description = context.getString(R.string.notification_channel_close_description) + enableLights(true) + enableVibration(true) + // Default sound and vibration will be used for IMPORTANCE_HIGH, + // or you can set a custom sound if needed. + val audioAttributes = AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) + .build() + setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI, audioAttributes) + // setBypassDnd(false) // Default is false, explicitly state for clarity if desired } + notificationManager.createNotificationChannel(closeChannel) } companion object { - const val CHANNEL_ID = "channel" + const val DISTANT_CHANNEL_ID = "blitzortung_alert_distant_channel" // New ID + const val CLOSE_CHANNEL_ID = "blitzortung_alert_close_channel" // New ID + // const val CHANNEL_ID = "channel" // This old constant can be removed after all usages are replaced } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 573f79fa7..072e2f39e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -385,4 +385,8 @@ Russian by Ivan Karev (karev.ivan@gmail.com)\n Enable post notification permission if notification alerts are desired. Background alert symbol Default alarm sound + Distant lightning + Close lightning + Notification channel for alerts for distant lightning activity + Notification channel for alerts for close lightning activity From 21d02e74a9950ecc27d0f66129ec4e30db988c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20W=C3=BCrl?= Date: Sat, 30 Aug 2025 22:06:19 +0100 Subject: [PATCH 2/2] re-add background notification channel --- .../android/alert/handler/AlertHandler.kt | 28 +++++++++++++------ .../org/blitzortung/android/app/AppService.kt | 4 +-- .../app/controller/NotificationHandler.kt | 20 +++++++++---- app/src/main/res/values/strings.xml | 2 ++ 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/org/blitzortung/android/alert/handler/AlertHandler.kt b/app/src/main/java/org/blitzortung/android/alert/handler/AlertHandler.kt index 5bd959e29..e35c6d420 100644 --- a/app/src/main/java/org/blitzortung/android/alert/handler/AlertHandler.kt +++ b/app/src/main/java/org/blitzortung/android/alert/handler/AlertHandler.kt @@ -21,6 +21,7 @@ package org.blitzortung.android.alert.handler import android.content.Context import android.content.SharedPreferences import android.location.Location +import android.os.Build import android.util.Log import org.blitzortung.android.alert.AlertParameters import org.blitzortung.android.alert.AlertResult @@ -41,6 +42,7 @@ import org.blitzortung.android.location.LocationHandler import org.blitzortung.android.protocol.ConsumerContainer import org.blitzortung.android.protocol.Event import org.blitzortung.android.util.MeasurementSystem +import org.blitzortung.android.util.isAtLeast import javax.inject.Inject import javax.inject.Singleton @@ -213,7 +215,12 @@ class AlertHandler @Inject constructor( val signalingLatestTimestamp = alertDataHandler.getLatestTimstampWithin(signalingDistanceLimit, alertResult) if (signalingLatestTimestamp > signalingLastTimestamp + signalingThresholdTime) { Log.d(Main.LOG_TAG, "AlertHandler.alertSignal() signal ${signalingLatestTimestamp / 1000}") - alertSignal.emitSignal() + if (isAtLeast(Build.VERSION_CODES.O)) { + sendNotification(alertResult, true) + } else { + alertSignal.emitSignal() + } + signalingLastTimestamp = signalingLatestTimestamp } else { Log.d( @@ -228,13 +235,7 @@ class AlertHandler @Inject constructor( alertDataHandler.getLatestTimstampWithin(notificationDistanceLimit, alertResult) if (notificationLatestTimestamp > notificationLastTimestamp) { Log.d(Main.LOG_TAG, "AlertHandler.alertNotification() notification ${notificationLatestTimestamp / 1000}") - notificationHandler.sendNotification( - context.resources.getString(R.string.activity) + ": " + alertDataHandler.getTextMessage( - alertResult, - notificationDistanceLimit, - context.resources - ) - ) + sendNotification(alertResult, false) notificationLastTimestamp = notificationLatestTimestamp } else { Log.d( @@ -244,6 +245,17 @@ class AlertHandler @Inject constructor( } } + private fun sendNotification(alertResult: AlertResult, isCloseAlarm: Boolean) { + notificationHandler.sendNotification( + context.resources.getString(R.string.activity) + ": " + alertDataHandler.getTextMessage( + alertResult, + notificationDistanceLimit, + context.resources + ), + isCloseAlarm + ) + } + fun requestUpdates(alertEventConsumer: (AlertEvent) -> Unit) { alertConsumerContainer.addConsumer(alertEventConsumer) } diff --git a/app/src/main/java/org/blitzortung/android/app/AppService.kt b/app/src/main/java/org/blitzortung/android/app/AppService.kt index 7dbd1aa81..96ae5fcdb 100644 --- a/app/src/main/java/org/blitzortung/android/app/AppService.kt +++ b/app/src/main/java/org/blitzortung/android/app/AppService.kt @@ -34,7 +34,7 @@ import androidx.annotation.RequiresApi import androidx.core.app.ServiceCompat import dagger.android.AndroidInjection import org.blitzortung.android.alert.handler.AlertHandler -import org.blitzortung.android.app.controller.NotificationHandler.Companion.CHANNEL_ID +import org.blitzortung.android.app.controller.NotificationHandler.Companion.BACKGROUND_CHANNEL_ID import org.blitzortung.android.app.view.OnSharedPreferenceChangeListener import org.blitzortung.android.app.view.PreferenceKey import org.blitzortung.android.app.view.get @@ -150,7 +150,7 @@ class AppService : Service(), OnSharedPreferenceChangeListener { @RequiresApi(Build.VERSION_CODES.Q) private fun startForeground(contentIntent: PendingIntent?) { - val notification = Notification.Builder(this, CHANNEL_ID) + val notification = Notification.Builder(this, BACKGROUND_CHANNEL_ID) .setSmallIcon(R.drawable.icon) .setContentTitle(this.resources.getText(R.string.app_name)) .setContentText("bla") diff --git a/app/src/main/java/org/blitzortung/android/app/controller/NotificationHandler.kt b/app/src/main/java/org/blitzortung/android/app/controller/NotificationHandler.kt index 1be76c314..c1c8824b8 100644 --- a/app/src/main/java/org/blitzortung/android/app/controller/NotificationHandler.kt +++ b/app/src/main/java/org/blitzortung/android/app/controller/NotificationHandler.kt @@ -43,7 +43,7 @@ open class NotificationHandler @Inject constructor( init { if (isAtLeast(Build.VERSION_CODES.O)) { - createNotificationChannels() // Renamed from createNotificationChannel + createNotificationChannels() } } @@ -103,7 +103,16 @@ open class NotificationHandler @Inject constructor( @RequiresApi(Build.VERSION_CODES.O) private fun createNotificationChannels() { // Renamed method - // Create the "distant" channel + val backgroundName = context.getString(R.string.notification_channel_background_name) + val backgroundChannel = NotificationChannel(BACKGROUND_CHANNEL_ID, backgroundName, IMPORTANCE_LOW).apply { + description = context.getString(R.string.notification_channel_background_description) + enableLights(false) + enableVibration(false) + setSound(null, null) // No sound + // setBypassDnd(false) // Default is false, explicitly state for clarity if desired + } + notificationManager.createNotificationChannel(backgroundChannel) + val distantName = context.getString(R.string.notification_channel_distant_name) val distantChannel = NotificationChannel(DISTANT_CHANNEL_ID, distantName, IMPORTANCE_LOW).apply { description = context.getString(R.string.notification_channel_distant_description) @@ -114,7 +123,6 @@ open class NotificationHandler @Inject constructor( } notificationManager.createNotificationChannel(distantChannel) - // Create the "close" channel val closeName = context.getString(R.string.notification_channel_close_name) val closeChannel = NotificationChannel(CLOSE_CHANNEL_ID, closeName, IMPORTANCE_HIGH).apply { description = context.getString(R.string.notification_channel_close_description) @@ -133,9 +141,9 @@ open class NotificationHandler @Inject constructor( } companion object { - const val DISTANT_CHANNEL_ID = "blitzortung_alert_distant_channel" // New ID - const val CLOSE_CHANNEL_ID = "blitzortung_alert_close_channel" // New ID - // const val CHANNEL_ID = "channel" // This old constant can be removed after all usages are replaced + const val BACKGROUND_CHANNEL_ID = "blitzortung_background_channel" + const val DISTANT_CHANNEL_ID = "blitzortung_alert_distant_channel" + const val CLOSE_CHANNEL_ID = "blitzortung_alert_close_channel" } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 072e2f39e..e50e4ab3c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -389,4 +389,6 @@ Russian by Ivan Karev (karev.ivan@gmail.com)\n Close lightning Notification channel for alerts for distant lightning activity Notification channel for alerts for close lightning activity + Background operation + Channel for background operation notifications