Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1cca29df authored by Philipp Heckel's avatar Philipp Heckel
Browse files

Refactor subscriber manager (service starter)

parent 4efdce54
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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 -->
+1 −1
Original line number Diff line number Diff line
@@ -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
+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
+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
@@ -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
@@ -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.*
@@ -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 {
@@ -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)
        }
    }

@@ -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
    }
+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