Loading app/src/main/AndroidManifest.xml +3 −3 Original line number Diff line number Diff line Loading @@ -44,17 +44,17 @@ </activity> <!-- Subscriber foreground service for hosts other than ntfy.sh --> <service android:name=".msg.SubscriberService"/> <service android:name=".service.SubscriberService"/> <!-- Subscriber service restart on reboot --> <receiver android:name=".msg.SubscriberService$BootStartReceiver" android:enabled="true"> <receiver android:name=".service.SubscriberService$BootStartReceiver" android:enabled="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> <!-- Subscriber service restart on destruction --> <receiver android:name=".msg.SubscriberService$AutoRestartReceiver" android:enabled="true" <receiver android:name=".service.SubscriberService$AutoRestartReceiver" android:enabled="true" android:exported="false"/> <!-- Broadcast receiver to send messages via intents --> Loading app/src/main/java/io/heckel/ntfy/msg/NotificationDispatcher.kt +1 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ class NotificationDispatcher(val context: Context, val repository: Repository) { } private fun checkNotify(subscription: Subscription, notification: Notification, muted: Boolean): Boolean { if (subscription.upAppId != "") { if (subscription.upAppId != null) { return false } val detailsVisible = repository.detailViewSubscriptionId.get() == notification.subscriptionId Loading app/src/main/java/io/heckel/ntfy/msg/SubscriberConnection.kt→app/src/main/java/io/heckel/ntfy/service/SubscriberConnection.kt +2 −1 Original line number Diff line number Diff line package io.heckel.ntfy.msg package io.heckel.ntfy.service import android.util.Log import io.heckel.ntfy.data.ConnectionState import io.heckel.ntfy.data.Notification import io.heckel.ntfy.data.Subscription import io.heckel.ntfy.msg.ApiService import io.heckel.ntfy.util.topicUrl import kotlinx.coroutines.* import okhttp3.Call Loading app/src/main/java/io/heckel/ntfy/msg/SubscriberService.kt→app/src/main/java/io/heckel/ntfy/service/SubscriberService.kt +8 −30 Original line number Diff line number Diff line package io.heckel.ntfy.msg package io.heckel.ntfy.service import android.app.* import android.content.BroadcastReceiver Loading @@ -11,8 +11,6 @@ import android.os.SystemClock import android.util.Log import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import androidx.work.OneTimeWorkRequest import androidx.work.WorkManager import androidx.work.Worker import androidx.work.WorkerParameters import io.heckel.ntfy.BuildConfig Loading @@ -20,6 +18,8 @@ import io.heckel.ntfy.R import io.heckel.ntfy.app.Application import io.heckel.ntfy.data.ConnectionState import io.heckel.ntfy.data.Subscription import io.heckel.ntfy.msg.ApiService import io.heckel.ntfy.msg.NotificationDispatcher import io.heckel.ntfy.ui.MainActivity import io.heckel.ntfy.util.topicUrl import kotlinx.coroutines.* Loading Loading @@ -70,8 +70,8 @@ class SubscriberService : Service() { val action = intent.action Log.d(TAG, "using an intent with action $action") when (action) { Actions.START.name -> startService() Actions.STOP.name -> stopService() Action.START.name -> startService() Action.STOP.name -> stopService() else -> Log.e(TAG, "This should never happen. No action in the received intent") } } else { Loading Loading @@ -259,13 +259,7 @@ class SubscriberService : Service() { class BootStartReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Log.d(TAG, "BootStartReceiver: onReceive called") if (intent.action == Intent.ACTION_BOOT_COMPLETED && readServiceState(context) == ServiceState.STARTED) { Intent(context, SubscriberService::class.java).also { it.action = Actions.START.name Log.d(TAG, "BootStartReceiver: Starting subscriber service") ContextCompat.startForegroundService(context, it) } } SubscriberServiceManager.refresh(context) } } Loading @@ -276,27 +270,11 @@ class SubscriberService : Service() { class AutoRestartReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Log.d(TAG, "AutoRestartReceiver: onReceive called") val workManager = WorkManager.getInstance(context) val startServiceRequest = OneTimeWorkRequest.Builder(AutoRestartWorker::class.java).build() workManager.enqueue(startServiceRequest) } } class AutoRestartWorker(private val context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { Log.d(TAG, "AutoRestartReceiver: doWork called for: " + this.getId()) if (readServiceState(context) == ServiceState.STARTED) { Intent(context, SubscriberService::class.java).also { it.action = Actions.START.name Log.d(TAG, "AutoRestartReceiver: Starting subscriber service") ContextCompat.startForegroundService(context, it) } } return Result.success() SubscriberServiceManager.refresh(context) } } enum class Actions { enum class Action { START, STOP } Loading app/src/main/java/io/heckel/ntfy/service/SubscriberServiceManager.kt 0 → 100644 +54 −0 Original line number Diff line number Diff line package io.heckel.ntfy.service import android.content.Context import android.content.Intent import android.util.Log import androidx.core.content.ContextCompat import androidx.work.* import io.heckel.ntfy.app.Application import io.heckel.ntfy.up.BroadcastReceiver /** * This class only manages the SubscriberService, i.e. it starts or stops it. * It's used in multiple activities. */ class SubscriberServiceManager(private val context: Context) { fun refresh() { Log.d(TAG, "Enqueuing work to refresh subscriber service") val workManager = WorkManager.getInstance(context) val startServiceRequest = OneTimeWorkRequest.Builder(RefreshWorker::class.java).build() workManager.enqueue(startServiceRequest) } class RefreshWorker(private val context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { if (context.applicationContext !is Application) { Log.d(TAG, "RefreshWorker: Failed, no application found (work ID: ${this.id})") return Result.failure() } val app = context.applicationContext as Application val subscriptionIdsWithInstantStatus = app.repository.getSubscriptionIdsWithInstantStatus() val instantSubscriptions = subscriptionIdsWithInstantStatus.toList().filter { (_, instant) -> instant }.size val action = if (instantSubscriptions > 0) SubscriberService.Action.START else SubscriberService.Action.STOP val serviceState = SubscriberService.readServiceState(context) if (serviceState == SubscriberService.ServiceState.STOPPED && action == SubscriberService.Action.STOP) { return Result.success() } Log.d(TAG, "RefreshWorker: Starting foreground service with action $action (work ID: ${this.id})") Intent(context, SubscriberService::class.java).also { it.action = action.name ContextCompat.startForegroundService(context, it) } return Result.success() } } companion object { const val TAG = "NtfySubscriberMgr" fun refresh(context: Context) { val manager = SubscriberServiceManager(context) manager.refresh() } } } Loading
app/src/main/AndroidManifest.xml +3 −3 Original line number Diff line number Diff line Loading @@ -44,17 +44,17 @@ </activity> <!-- Subscriber foreground service for hosts other than ntfy.sh --> <service android:name=".msg.SubscriberService"/> <service android:name=".service.SubscriberService"/> <!-- Subscriber service restart on reboot --> <receiver android:name=".msg.SubscriberService$BootStartReceiver" android:enabled="true"> <receiver android:name=".service.SubscriberService$BootStartReceiver" android:enabled="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> <!-- Subscriber service restart on destruction --> <receiver android:name=".msg.SubscriberService$AutoRestartReceiver" android:enabled="true" <receiver android:name=".service.SubscriberService$AutoRestartReceiver" android:enabled="true" android:exported="false"/> <!-- Broadcast receiver to send messages via intents --> Loading
app/src/main/java/io/heckel/ntfy/msg/NotificationDispatcher.kt +1 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ class NotificationDispatcher(val context: Context, val repository: Repository) { } private fun checkNotify(subscription: Subscription, notification: Notification, muted: Boolean): Boolean { if (subscription.upAppId != "") { if (subscription.upAppId != null) { return false } val detailsVisible = repository.detailViewSubscriptionId.get() == notification.subscriptionId Loading
app/src/main/java/io/heckel/ntfy/msg/SubscriberConnection.kt→app/src/main/java/io/heckel/ntfy/service/SubscriberConnection.kt +2 −1 Original line number Diff line number Diff line package io.heckel.ntfy.msg package io.heckel.ntfy.service import android.util.Log import io.heckel.ntfy.data.ConnectionState import io.heckel.ntfy.data.Notification import io.heckel.ntfy.data.Subscription import io.heckel.ntfy.msg.ApiService import io.heckel.ntfy.util.topicUrl import kotlinx.coroutines.* import okhttp3.Call Loading
app/src/main/java/io/heckel/ntfy/msg/SubscriberService.kt→app/src/main/java/io/heckel/ntfy/service/SubscriberService.kt +8 −30 Original line number Diff line number Diff line package io.heckel.ntfy.msg package io.heckel.ntfy.service import android.app.* import android.content.BroadcastReceiver Loading @@ -11,8 +11,6 @@ import android.os.SystemClock import android.util.Log import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import androidx.work.OneTimeWorkRequest import androidx.work.WorkManager import androidx.work.Worker import androidx.work.WorkerParameters import io.heckel.ntfy.BuildConfig Loading @@ -20,6 +18,8 @@ import io.heckel.ntfy.R import io.heckel.ntfy.app.Application import io.heckel.ntfy.data.ConnectionState import io.heckel.ntfy.data.Subscription import io.heckel.ntfy.msg.ApiService import io.heckel.ntfy.msg.NotificationDispatcher import io.heckel.ntfy.ui.MainActivity import io.heckel.ntfy.util.topicUrl import kotlinx.coroutines.* Loading Loading @@ -70,8 +70,8 @@ class SubscriberService : Service() { val action = intent.action Log.d(TAG, "using an intent with action $action") when (action) { Actions.START.name -> startService() Actions.STOP.name -> stopService() Action.START.name -> startService() Action.STOP.name -> stopService() else -> Log.e(TAG, "This should never happen. No action in the received intent") } } else { Loading Loading @@ -259,13 +259,7 @@ class SubscriberService : Service() { class BootStartReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Log.d(TAG, "BootStartReceiver: onReceive called") if (intent.action == Intent.ACTION_BOOT_COMPLETED && readServiceState(context) == ServiceState.STARTED) { Intent(context, SubscriberService::class.java).also { it.action = Actions.START.name Log.d(TAG, "BootStartReceiver: Starting subscriber service") ContextCompat.startForegroundService(context, it) } } SubscriberServiceManager.refresh(context) } } Loading @@ -276,27 +270,11 @@ class SubscriberService : Service() { class AutoRestartReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Log.d(TAG, "AutoRestartReceiver: onReceive called") val workManager = WorkManager.getInstance(context) val startServiceRequest = OneTimeWorkRequest.Builder(AutoRestartWorker::class.java).build() workManager.enqueue(startServiceRequest) } } class AutoRestartWorker(private val context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { Log.d(TAG, "AutoRestartReceiver: doWork called for: " + this.getId()) if (readServiceState(context) == ServiceState.STARTED) { Intent(context, SubscriberService::class.java).also { it.action = Actions.START.name Log.d(TAG, "AutoRestartReceiver: Starting subscriber service") ContextCompat.startForegroundService(context, it) } } return Result.success() SubscriberServiceManager.refresh(context) } } enum class Actions { enum class Action { START, STOP } Loading
app/src/main/java/io/heckel/ntfy/service/SubscriberServiceManager.kt 0 → 100644 +54 −0 Original line number Diff line number Diff line package io.heckel.ntfy.service import android.content.Context import android.content.Intent import android.util.Log import androidx.core.content.ContextCompat import androidx.work.* import io.heckel.ntfy.app.Application import io.heckel.ntfy.up.BroadcastReceiver /** * This class only manages the SubscriberService, i.e. it starts or stops it. * It's used in multiple activities. */ class SubscriberServiceManager(private val context: Context) { fun refresh() { Log.d(TAG, "Enqueuing work to refresh subscriber service") val workManager = WorkManager.getInstance(context) val startServiceRequest = OneTimeWorkRequest.Builder(RefreshWorker::class.java).build() workManager.enqueue(startServiceRequest) } class RefreshWorker(private val context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { if (context.applicationContext !is Application) { Log.d(TAG, "RefreshWorker: Failed, no application found (work ID: ${this.id})") return Result.failure() } val app = context.applicationContext as Application val subscriptionIdsWithInstantStatus = app.repository.getSubscriptionIdsWithInstantStatus() val instantSubscriptions = subscriptionIdsWithInstantStatus.toList().filter { (_, instant) -> instant }.size val action = if (instantSubscriptions > 0) SubscriberService.Action.START else SubscriberService.Action.STOP val serviceState = SubscriberService.readServiceState(context) if (serviceState == SubscriberService.ServiceState.STOPPED && action == SubscriberService.Action.STOP) { return Result.success() } Log.d(TAG, "RefreshWorker: Starting foreground service with action $action (work ID: ${this.id})") Intent(context, SubscriberService::class.java).also { it.action = action.name ContextCompat.startForegroundService(context, it) } return Result.success() } } companion object { const val TAG = "NtfySubscriberMgr" fun refresh(context: Context) { val manager = SubscriberServiceManager(context) manager.refresh() } } }