e-ntfy-android/app/src/main/java/io/heckel/ntfy/up/BroadcastReceiver.kt

114 lines
4.9 KiB
Kotlin
Raw Normal View History

2021-12-29 20:33:17 +01:00
package io.heckel.ntfy.up
import android.content.Context
import android.content.Intent
import android.util.Log
2021-12-31 01:34:25 +01:00
import androidx.preference.PreferenceManager
2021-12-29 20:33:17 +01:00
import io.heckel.ntfy.R
import io.heckel.ntfy.app.Application
import io.heckel.ntfy.data.Subscription
import io.heckel.ntfy.service.SubscriberServiceManager
import io.heckel.ntfy.util.randomString
import io.heckel.ntfy.util.topicUrlUp
2021-12-29 20:33:17 +01:00
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.util.*
import kotlin.random.Random
2021-12-31 15:30:49 +01:00
/**
* This is the UnifiedPush broadcast receiver to handle the distributor actions REGISTER and UNREGISTER.
* See https://unifiedpush.org/spec/android/ for details.
*/
2021-12-29 20:33:17 +01:00
class BroadcastReceiver : android.content.BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
2021-12-30 14:23:47 +01:00
if (context == null || intent == null) {
return
}
when (intent.action) {
ACTION_REGISTER -> register(context, intent)
ACTION_UNREGISTER -> unregister(context, intent)
}
}
private fun register(context: Context, intent: Intent) {
val appId = intent.getStringExtra(EXTRA_APPLICATION) ?: return
val connectorToken = intent.getStringExtra(EXTRA_TOKEN) ?: return
val app = context.applicationContext as Application
val repository = app.repository
val distributor = Distributor(app)
Log.d(TAG, "REGISTER received for app $appId (connectorToken=$connectorToken)")
2021-12-31 01:34:25 +01:00
if (!repository.getUnifiedPushEnabled() || appId.isBlank()) {
Log.w(TAG, "Refusing registration: UnifiedPush disabled or empty application")
2021-12-30 14:23:47 +01:00
distributor.sendRegistrationRefused(appId, connectorToken)
return
}
GlobalScope.launch(Dispatchers.IO) {
val existingSubscription = repository.getSubscriptionByConnectorToken(connectorToken)
if (existingSubscription != null) {
if (existingSubscription.upAppId == appId) {
val endpoint = topicUrlUp(existingSubscription.baseUrl, existingSubscription.topic)
Log.d(TAG, "Subscription with connectorToken $connectorToken exists. Sending endpoint $endpoint.")
distributor.sendEndpoint(appId, connectorToken, endpoint)
2021-12-30 14:23:47 +01:00
} else {
Log.d(TAG, "Subscription with connectorToken $connectorToken exists for a different app. Refusing registration.")
distributor.sendRegistrationRefused(appId, connectorToken)
2021-12-29 20:33:17 +01:00
}
2021-12-30 14:23:47 +01:00
return@launch
2021-12-29 20:33:17 +01:00
}
// Add subscription
2021-12-31 01:34:25 +01:00
val baseUrl = repository.getUnifiedPushBaseUrl() ?: context.getString(R.string.app_base_url)
val topic = UP_PREFIX + randomString(TOPIC_RANDOM_ID_LENGTH)
2021-12-30 14:23:47 +01:00
val endpoint = topicUrlUp(baseUrl, topic)
val subscription = Subscription(
id = Random.nextLong(),
baseUrl = baseUrl,
topic = topic,
instant = true, // No Firebase, always instant!
mutedUntil = 0,
upAppId = appId,
upConnectorToken = connectorToken,
totalCount = 0,
newCount = 0,
lastActive = Date().time/1000
)
Log.d(TAG, "Adding subscription with for app $appId (connectorToken $connectorToken): $subscription")
repository.addSubscription(subscription)
distributor.sendEndpoint(appId, connectorToken, endpoint)
// Refresh (and maybe start) foreground service
SubscriberServiceManager.refresh(app)
2021-12-30 14:23:47 +01:00
}
}
private fun unregister(context: Context, intent: Intent) {
val connectorToken = intent.getStringExtra(EXTRA_TOKEN) ?: return
val app = context.applicationContext as Application
val repository = app.repository
val distributor = Distributor(app)
Log.d(TAG, "UNREGISTER received (connectorToken=$connectorToken)")
GlobalScope.launch(Dispatchers.IO) {
val existingSubscription = repository.getSubscriptionByConnectorToken(connectorToken)
if (existingSubscription == null) {
Log.d(TAG, "Subscription with connectorToken $connectorToken does not exist. Ignoring.")
return@launch
2021-12-29 20:33:17 +01:00
}
2021-12-30 14:23:47 +01:00
// Remove subscription
Log.d(TAG, "Removing subscription ${existingSubscription.id} with connectorToken $connectorToken")
repository.removeSubscription(existingSubscription.id)
existingSubscription.upAppId?.let { appId -> distributor.sendUnregistered(appId, connectorToken) }
// Refresh (and maybe stop) foreground service
SubscriberServiceManager.refresh(context)
2021-12-29 20:33:17 +01:00
}
}
companion object {
private const val TAG = "NtfyUpBroadcastRecv"
2021-12-30 14:23:47 +01:00
private const val UP_PREFIX = "up"
2021-12-31 01:34:25 +01:00
private const val TOPIC_RANDOM_ID_LENGTH = 12
2021-12-29 20:33:17 +01:00
}
}