nfty: Remove firebase support and rating
This commit is contained in:
parent
31eadd9768
commit
3486333c2a
13 changed files with 10 additions and 353 deletions
|
@ -41,14 +41,7 @@ android {
|
|||
|
||||
flavorDimensions "store"
|
||||
productFlavors {
|
||||
play {
|
||||
buildConfigField 'boolean', 'FIREBASE_AVAILABLE', 'true'
|
||||
buildConfigField 'boolean', 'RATE_APP_AVAILABLE', 'true'
|
||||
buildConfigField 'boolean', 'INSTALL_PACKAGES_AVAILABLE', 'false'
|
||||
}
|
||||
fdroid {
|
||||
buildConfigField 'boolean', 'FIREBASE_AVAILABLE', 'false'
|
||||
buildConfigField 'boolean', 'RATE_APP_AVAILABLE', 'false'
|
||||
buildConfigField 'boolean', 'INSTALL_PACKAGES_AVAILABLE', 'true'
|
||||
}
|
||||
}
|
||||
|
@ -110,9 +103,6 @@ dependencies {
|
|||
// OkHttp (HTTP library)
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
|
||||
|
||||
// Firebase, sigh ... (only Google Play)
|
||||
playImplementation 'com.google.firebase:firebase-messaging:23.1.2'
|
||||
|
||||
// RecyclerView
|
||||
implementation "androidx.recyclerview:recyclerview:1.3.0"
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
package io.heckel.ntfy.firebase
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
class FirebaseMessenger {
|
||||
fun subscribe(topic: String) {
|
||||
// Dummy to keep F-Droid flavor happy
|
||||
}
|
||||
|
||||
fun unsubscribe(topic: String) {
|
||||
// Dummy to keep F-Droid flavor happy
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package io.heckel.ntfy.firebase
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
|
||||
// Dummy to keep F-Droid flavor happy
|
||||
class FirebaseService : Service() {
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
return null
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ import com.google.gson.stream.JsonReader
|
|||
import io.heckel.ntfy.R
|
||||
import io.heckel.ntfy.app.Application
|
||||
import io.heckel.ntfy.db.Repository
|
||||
import io.heckel.ntfy.firebase.FirebaseMessenger
|
||||
import io.heckel.ntfy.msg.NotificationService
|
||||
import io.heckel.ntfy.util.Log
|
||||
import io.heckel.ntfy.util.topicUrl
|
||||
|
@ -18,7 +17,6 @@ class Backuper(val context: Context) {
|
|||
private val gson = Gson()
|
||||
private val resolver = context.applicationContext.contentResolver
|
||||
private val repository = (context.applicationContext as Application).repository
|
||||
private val messenger = FirebaseMessenger()
|
||||
private val notifier = NotificationService(context)
|
||||
|
||||
suspend fun backup(uri: Uri, withSettings: Boolean = true, withSubscriptions: Boolean = true, withUsers: Boolean = true) {
|
||||
|
@ -114,11 +112,6 @@ class Backuper(val context: Context) {
|
|||
)
|
||||
repository.addSubscription(subscription)
|
||||
|
||||
// Subscribe to Firebase topics
|
||||
if (s.baseUrl == appBaseUrl) {
|
||||
messenger.subscribe(s.topic)
|
||||
}
|
||||
|
||||
// Create dedicated channels
|
||||
if (s.dedicatedChannels) {
|
||||
notifier.createSubscriptionNotificationChannels(subscription)
|
||||
|
|
|
@ -90,11 +90,7 @@ class SubscriberService : Service() {
|
|||
Log.d(TAG, "Subscriber service has been created")
|
||||
|
||||
val title = getString(R.string.channel_subscriber_notification_title)
|
||||
val text = if (BuildConfig.FIREBASE_AVAILABLE) {
|
||||
getString(R.string.channel_subscriber_notification_instant_text)
|
||||
} else {
|
||||
getString(R.string.channel_subscriber_notification_noinstant_text)
|
||||
}
|
||||
val text = getString(R.string.channel_subscriber_notification_noinstant_text)
|
||||
notificationManager = createNotificationChannel()
|
||||
serviceNotification = createNotification(title, text)
|
||||
|
||||
|
@ -221,18 +217,7 @@ class SubscriberService : Service() {
|
|||
// Update foreground service notification popup
|
||||
if (connections.size > 0) {
|
||||
val title = getString(R.string.channel_subscriber_notification_title)
|
||||
val text = if (BuildConfig.FIREBASE_AVAILABLE) {
|
||||
when (instantSubscriptions.size) {
|
||||
1 -> getString(R.string.channel_subscriber_notification_instant_text_one)
|
||||
2 -> getString(R.string.channel_subscriber_notification_instant_text_two)
|
||||
3 -> getString(R.string.channel_subscriber_notification_instant_text_three)
|
||||
4 -> getString(R.string.channel_subscriber_notification_instant_text_four)
|
||||
5 -> getString(R.string.channel_subscriber_notification_instant_text_five)
|
||||
6 -> getString(R.string.channel_subscriber_notification_instant_text_six)
|
||||
else -> getString(R.string.channel_subscriber_notification_instant_text_more, instantSubscriptions.size)
|
||||
}
|
||||
} else {
|
||||
when (instantSubscriptions.size) {
|
||||
val text = when (instantSubscriptions.size) {
|
||||
1 -> getString(R.string.channel_subscriber_notification_noinstant_text_one)
|
||||
2 -> getString(R.string.channel_subscriber_notification_noinstant_text_two)
|
||||
3 -> getString(R.string.channel_subscriber_notification_noinstant_text_three)
|
||||
|
@ -241,7 +226,6 @@ class SubscriberService : Service() {
|
|||
6 -> getString(R.string.channel_subscriber_notification_noinstant_text_six)
|
||||
else -> getString(R.string.channel_subscriber_notification_noinstant_text_more, instantSubscriptions.size)
|
||||
}
|
||||
}
|
||||
serviceNotification = createNotification(title, text)
|
||||
notificationManager?.notify(NOTIFICATION_SERVICE_ID, serviceNotification)
|
||||
}
|
||||
|
|
|
@ -114,10 +114,7 @@ class AddFragment : DialogFragment() {
|
|||
// Set foreground description text
|
||||
subscribeForegroundDescription.text = getString(R.string.add_dialog_foreground_description, shortUrl(appBaseUrl))
|
||||
|
||||
// Show/hide based on flavor (faster shortcut for validateInputSubscribeView, which can only run onShow)
|
||||
if (!BuildConfig.FIREBASE_AVAILABLE) {
|
||||
subscribeInstantDeliveryBox.visibility = View.GONE
|
||||
}
|
||||
subscribeInstantDeliveryBox.visibility = View.GONE
|
||||
|
||||
// Add baseUrl auto-complete behavior
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
|
@ -291,16 +288,6 @@ class AddFragment : DialogFragment() {
|
|||
private fun validateInputSubscribeView() {
|
||||
if (!this::positiveButton.isInitialized) return // As per crash seen in Google Play
|
||||
|
||||
// Show/hide things: This logic is intentionally kept simple. Do not simplify "just because it's pretty".
|
||||
val instantToggleAllowed = if (!BuildConfig.FIREBASE_AVAILABLE) {
|
||||
false
|
||||
} else if (subscribeUseAnotherServerCheckbox.isChecked && subscribeBaseUrlText.text.toString() == appBaseUrl) {
|
||||
true
|
||||
} else if (!subscribeUseAnotherServerCheckbox.isChecked && defaultBaseUrl == null) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
if (subscribeUseAnotherServerCheckbox.isChecked) {
|
||||
subscribeUseAnotherServerDescription.visibility = View.VISIBLE
|
||||
subscribeBaseUrlLayout.visibility = View.VISIBLE
|
||||
|
@ -308,15 +295,9 @@ class AddFragment : DialogFragment() {
|
|||
subscribeUseAnotherServerDescription.visibility = View.GONE
|
||||
subscribeBaseUrlLayout.visibility = View.GONE
|
||||
}
|
||||
if (instantToggleAllowed) {
|
||||
subscribeInstantDeliveryBox.visibility = View.VISIBLE
|
||||
subscribeInstantDeliveryDescription.visibility = if (subscribeInstantDeliveryCheckbox.isChecked) View.VISIBLE else View.GONE
|
||||
subscribeForegroundDescription.visibility = View.GONE
|
||||
} else {
|
||||
subscribeInstantDeliveryBox.visibility = View.GONE
|
||||
subscribeInstantDeliveryDescription.visibility = View.GONE
|
||||
subscribeForegroundDescription.visibility = if (BuildConfig.FIREBASE_AVAILABLE) View.VISIBLE else View.GONE
|
||||
}
|
||||
subscribeInstantDeliveryBox.visibility = View.GONE
|
||||
subscribeInstantDeliveryDescription.visibility = View.GONE
|
||||
subscribeForegroundDescription.visibility = View.GONE
|
||||
|
||||
// Enable/disable "Subscribe" button
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
|
@ -356,7 +337,7 @@ class AddFragment : DialogFragment() {
|
|||
activity.runOnUiThread {
|
||||
val topic = subscribeTopicText.text.toString()
|
||||
val baseUrl = getBaseUrl()
|
||||
val instant = !BuildConfig.FIREBASE_AVAILABLE || baseUrl != appBaseUrl || subscribeInstantDeliveryCheckbox.isChecked
|
||||
val instant = baseUrl != appBaseUrl || subscribeInstantDeliveryCheckbox.isChecked
|
||||
subscribeListener.onSubscribe(topic, baseUrl, instant)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import io.heckel.ntfy.app.Application
|
|||
import io.heckel.ntfy.db.Notification
|
||||
import io.heckel.ntfy.db.Repository
|
||||
import io.heckel.ntfy.db.Subscription
|
||||
import io.heckel.ntfy.firebase.FirebaseMessenger
|
||||
import io.heckel.ntfy.util.Log
|
||||
import io.heckel.ntfy.msg.ApiService
|
||||
import io.heckel.ntfy.msg.NotificationService
|
||||
|
@ -47,7 +46,6 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
|||
}
|
||||
private val repository by lazy { (application as Application).repository }
|
||||
private val api = ApiService()
|
||||
private val messenger = FirebaseMessenger()
|
||||
private var notifier: NotificationService? = null // Context-dependent
|
||||
private var appBaseUrl: String? = null // Context-dependent
|
||||
|
||||
|
@ -127,12 +125,6 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
|||
)
|
||||
repository.addSubscription(subscription)
|
||||
|
||||
// Subscribe to Firebase topic if ntfy.sh (even if instant, just to be sure!)
|
||||
if (baseUrl == appBaseUrl) {
|
||||
Log.d(TAG, "Subscribing to Firebase topic $topic")
|
||||
messenger.subscribe(topic)
|
||||
}
|
||||
|
||||
// Fetch cached messages
|
||||
try {
|
||||
val user = repository.getUser(subscription.baseUrl) // May be null
|
||||
|
@ -529,14 +521,8 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
|||
val appBaseUrl = getString(R.string.app_base_url)
|
||||
val enableInstantItem = menu.findItem(R.id.detail_menu_enable_instant)
|
||||
val disableInstantItem = menu.findItem(R.id.detail_menu_disable_instant)
|
||||
val allowToggleInstant = BuildConfig.FIREBASE_AVAILABLE && subscriptionBaseUrl == appBaseUrl
|
||||
if (allowToggleInstant) {
|
||||
enableInstantItem?.isVisible = !subscriptionInstant
|
||||
disableInstantItem?.isVisible = subscriptionInstant
|
||||
} else {
|
||||
enableInstantItem?.isVisible = false
|
||||
disableInstantItem?.isVisible = false
|
||||
}
|
||||
enableInstantItem?.isVisible = false
|
||||
disableInstantItem?.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -608,9 +594,6 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
|
|||
GlobalScope.launch(Dispatchers.IO) {
|
||||
repository.removeAllNotifications(subscriptionId)
|
||||
repository.removeSubscription(subscriptionId)
|
||||
if (subscriptionBaseUrl == appBaseUrl) {
|
||||
messenger.unsubscribe(subscriptionTopic)
|
||||
}
|
||||
}
|
||||
finish()
|
||||
}
|
||||
|
|
|
@ -114,7 +114,6 @@ class DetailSettingsActivity : AppCompatActivity() {
|
|||
|
||||
private fun loadView() {
|
||||
if (subscription.upAppId == null) {
|
||||
loadInstantPref()
|
||||
loadMutedUntilPref()
|
||||
loadMinPriorityPref()
|
||||
loadAutoDeletePref()
|
||||
|
@ -134,29 +133,6 @@ class DetailSettingsActivity : AppCompatActivity() {
|
|||
loadTopicUrlPref()
|
||||
}
|
||||
|
||||
private fun loadInstantPref() {
|
||||
val appBaseUrl = getString(R.string.app_base_url)
|
||||
val prefId = context?.getString(R.string.detail_settings_notifications_instant_key) ?: return
|
||||
val pref: SwitchPreference? = findPreference(prefId)
|
||||
pref?.isVisible = BuildConfig.FIREBASE_AVAILABLE && subscription.baseUrl == appBaseUrl
|
||||
pref?.isChecked = subscription.instant
|
||||
pref?.preferenceDataStore = object : PreferenceDataStore() {
|
||||
override fun putBoolean(key: String?, value: Boolean) {
|
||||
save(subscription.copy(instant = value), refresh = true)
|
||||
}
|
||||
override fun getBoolean(key: String?, defValue: Boolean): Boolean {
|
||||
return subscription.instant
|
||||
}
|
||||
}
|
||||
pref?.summaryProvider = Preference.SummaryProvider<SwitchPreference> { preference ->
|
||||
if (preference.isChecked) {
|
||||
getString(R.string.detail_settings_notifications_instant_summary_on)
|
||||
} else {
|
||||
getString(R.string.detail_settings_notifications_instant_summary_off)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadDedicatedChannelsPrefs() {
|
||||
val prefId = context?.getString(R.string.detail_settings_notifications_dedicated_channels_key) ?: return
|
||||
val pref: SwitchPreference? = findPreference(prefId)
|
||||
|
|
|
@ -34,7 +34,6 @@ import io.heckel.ntfy.R
|
|||
import io.heckel.ntfy.app.Application
|
||||
import io.heckel.ntfy.db.Repository
|
||||
import io.heckel.ntfy.db.Subscription
|
||||
import io.heckel.ntfy.firebase.FirebaseMessenger
|
||||
import io.heckel.ntfy.msg.ApiService
|
||||
import io.heckel.ntfy.msg.DownloadManager
|
||||
import io.heckel.ntfy.msg.DownloadType
|
||||
|
@ -57,7 +56,6 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
|||
}
|
||||
private val repository by lazy { (application as Application).repository }
|
||||
private val api = ApiService()
|
||||
private val messenger = FirebaseMessenger()
|
||||
|
||||
// UI elements
|
||||
private lateinit var menu: Menu
|
||||
|
@ -199,9 +197,6 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
|||
// Create notification channels right away, so we can configure them immediately after installing the app
|
||||
dispatcher?.init()
|
||||
|
||||
// Subscribe to control Firebase channel (so we can re-start the foreground service if it dies)
|
||||
messenger.subscribe(ApiService.CONTROL_TOPIC)
|
||||
|
||||
// Darrkkkk mode
|
||||
AppCompatDelegate.setDefaultNightMode(repository.getDarkMode())
|
||||
|
||||
|
@ -349,10 +344,6 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
|||
}
|
||||
val mutedUntilSeconds = repository.getGlobalMutedUntil()
|
||||
runOnUiThread {
|
||||
// Show/hide in-app rate widget
|
||||
val rateAppItem = menu.findItem(R.id.main_menu_rate)
|
||||
rateAppItem.isVisible = BuildConfig.RATE_APP_AVAILABLE
|
||||
|
||||
// Pause notification icons
|
||||
val notificationsEnabledItem = menu.findItem(R.id.main_menu_notifications_enabled)
|
||||
val notificationsDisabledUntilItem = menu.findItem(R.id.main_menu_notifications_disabled_until)
|
||||
|
@ -389,14 +380,6 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
|||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.main_menu_report_bug_url))))
|
||||
true
|
||||
}
|
||||
R.id.main_menu_rate -> {
|
||||
try {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=$packageName")))
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=$packageName")))
|
||||
}
|
||||
true
|
||||
}
|
||||
R.id.main_menu_donate -> {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.main_menu_donate_url))))
|
||||
true
|
||||
|
@ -466,12 +449,6 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
|
|||
)
|
||||
viewModel.add(subscription)
|
||||
|
||||
// Subscribe to Firebase topic if ntfy.sh (even if instant, just to be sure!)
|
||||
if (baseUrl == appBaseUrl) {
|
||||
Log.d(TAG, "Subscribing to Firebase topic $topic")
|
||||
messenger.subscribe(topic)
|
||||
}
|
||||
|
||||
// Fetch cached messages
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
|
|
|
@ -105,7 +105,7 @@ class MainAdapter(private val repository: Repository, private val onClick: (Subs
|
|||
dateView.visibility = if (isUnifiedPush) View.GONE else View.VISIBLE
|
||||
notificationDisabledUntilImageView.visibility = if (showMutedUntilIcon) View.VISIBLE else View.GONE
|
||||
notificationDisabledForeverImageView.visibility = if (showMutedForeverIcon) View.VISIBLE else View.GONE
|
||||
instantImageView.visibility = if (subscription.instant && BuildConfig.FIREBASE_AVAILABLE) View.VISIBLE else View.GONE
|
||||
instantImageView.visibility = View.GONE
|
||||
if (isUnifiedPush || subscription.newCount == 0) {
|
||||
newItemsView.visibility = View.GONE
|
||||
} else {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
app:showAsAction="ifRoom" android:icon="@drawable/ic_notifications_off_white_outline_24dp"/>
|
||||
<item android:id="@+id/main_menu_settings" android:title="@string/main_menu_settings_title"/>
|
||||
<item android:id="@+id/main_menu_docs" android:title="@string/main_menu_docs_title"/>
|
||||
<item android:id="@+id/main_menu_rate" android:title="@string/main_menu_rate_title"/>
|
||||
<item android:id="@+id/main_menu_donate" android:title="@string/main_menu_donate_title"/>
|
||||
<item android:id="@+id/main_menu_report_bug" android:title="@string/main_menu_report_bug_title"/>
|
||||
</menu>
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
package io.heckel.ntfy.firebase
|
||||
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import io.heckel.ntfy.util.Log
|
||||
|
||||
class FirebaseMessenger {
|
||||
fun subscribe(topic: String) {
|
||||
val firebase = maybeInstance() ?: return
|
||||
firebase
|
||||
.subscribeToTopic(topic)
|
||||
.addOnCompleteListener {
|
||||
Log.d(TAG, "Subscribing to topic $topic complete: result=${it.result}, exception=${it.exception}, successful=${it.isSuccessful}")
|
||||
}
|
||||
.addOnFailureListener { e ->
|
||||
Log.e(TAG, "Subscribing to topic $topic failed: ${e.message}", e)
|
||||
}
|
||||
}
|
||||
|
||||
fun unsubscribe(topic: String) {
|
||||
val firebase = maybeInstance() ?: return
|
||||
firebase.unsubscribeFromTopic(topic)
|
||||
}
|
||||
|
||||
private fun maybeInstance(): FirebaseMessaging? {
|
||||
return try {
|
||||
FirebaseMessaging.getInstance()
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Firebase instance unavailable: ${e.message}", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "NtfyFirebase"
|
||||
}
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
package io.heckel.ntfy.firebase
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.work.*
|
||||
import com.google.firebase.messaging.FirebaseMessagingService
|
||||
import com.google.firebase.messaging.RemoteMessage
|
||||
import io.heckel.ntfy.R
|
||||
import io.heckel.ntfy.app.Application
|
||||
import io.heckel.ntfy.db.Attachment
|
||||
import io.heckel.ntfy.db.Icon
|
||||
import io.heckel.ntfy.db.Notification
|
||||
import io.heckel.ntfy.util.Log
|
||||
import io.heckel.ntfy.msg.ApiService
|
||||
import io.heckel.ntfy.msg.NotificationDispatcher
|
||||
import io.heckel.ntfy.msg.NotificationParser
|
||||
import io.heckel.ntfy.service.SubscriberService
|
||||
import io.heckel.ntfy.util.nullIfZero
|
||||
import io.heckel.ntfy.util.toPriority
|
||||
import io.heckel.ntfy.util.topicShortUrl
|
||||
import io.heckel.ntfy.work.PollWorker
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.random.Random
|
||||
|
||||
class FirebaseService : FirebaseMessagingService() {
|
||||
private val repository by lazy { (application as Application).repository }
|
||||
private val dispatcher by lazy { NotificationDispatcher(this, repository) }
|
||||
private val job = SupervisorJob()
|
||||
private val messenger = FirebaseMessenger()
|
||||
private val parser = NotificationParser()
|
||||
|
||||
override fun onMessageReceived(remoteMessage: RemoteMessage) {
|
||||
// Init log (this is done in all entrypoints)
|
||||
Log.init(this)
|
||||
|
||||
// We only process data messages
|
||||
if (remoteMessage.data.isEmpty()) {
|
||||
Log.d(TAG, "Discarding unexpected message (1): from=${remoteMessage.from}")
|
||||
return
|
||||
}
|
||||
|
||||
// Dispatch event
|
||||
val data = remoteMessage.data
|
||||
when (data["event"]) {
|
||||
ApiService.EVENT_MESSAGE -> handleMessage(remoteMessage)
|
||||
ApiService.EVENT_KEEPALIVE -> handleKeepalive(remoteMessage)
|
||||
ApiService.EVENT_POLL_REQUEST -> handlePollRequest(remoteMessage)
|
||||
else -> Log.d(TAG, "Discarding unexpected message (2): from=${remoteMessage.from}, data=${data}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleKeepalive(remoteMessage: RemoteMessage) {
|
||||
Log.d(TAG, "Keepalive received, sending auto restart broadcast for foregrounds service")
|
||||
sendBroadcast(Intent(this, SubscriberService.AutoRestartReceiver::class.java)) // Restart it if necessary!
|
||||
val topic = remoteMessage.data["topic"]
|
||||
if (topic != ApiService.CONTROL_TOPIC) {
|
||||
Log.d(TAG, "Keepalive on non-control topic $topic received, subscribing to control topic ${ApiService.CONTROL_TOPIC}")
|
||||
messenger.subscribe(ApiService.CONTROL_TOPIC)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handlePollRequest(remoteMessage: RemoteMessage) {
|
||||
val baseUrl = getString(R.string.app_base_url) // Everything from Firebase comes from main service URL!
|
||||
val topic = remoteMessage.data["topic"] ?: return
|
||||
val constraints = Constraints.Builder()
|
||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||
.build()
|
||||
val workName = "${PollWorker.WORK_NAME_ONCE_SINGE_PREFIX}_${baseUrl}_${topic}"
|
||||
val workManager = WorkManager.getInstance(this)
|
||||
val workRequest = OneTimeWorkRequest.Builder(PollWorker::class.java)
|
||||
.setInputData(workDataOf(
|
||||
PollWorker.INPUT_DATA_BASE_URL to baseUrl,
|
||||
PollWorker.INPUT_DATA_TOPIC to topic
|
||||
))
|
||||
.setConstraints(constraints)
|
||||
.build()
|
||||
Log.d(TAG, "Poll request for ${topicShortUrl(baseUrl, topic)} received, scheduling unique poll worker with name $workName")
|
||||
|
||||
workManager.enqueueUniqueWork(workName, ExistingWorkPolicy.REPLACE, workRequest)
|
||||
}
|
||||
|
||||
private fun handleMessage(remoteMessage: RemoteMessage) {
|
||||
val data = remoteMessage.data
|
||||
val id = data["id"]
|
||||
val timestamp = data["time"]?.toLongOrNull()
|
||||
val topic = data["topic"]
|
||||
val title = data["title"]
|
||||
val message = data["message"]
|
||||
val priority = data["priority"]?.toIntOrNull()
|
||||
val tags = data["tags"]
|
||||
val click = data["click"]
|
||||
val iconUrl = data["icon"]
|
||||
val actions = data["actions"] // JSON array as string, sigh ...
|
||||
val encoding = data["encoding"]
|
||||
val attachmentName = data["attachment_name"] ?: "attachment.bin"
|
||||
val attachmentType = data["attachment_type"]
|
||||
val attachmentSize = data["attachment_size"]?.toLongOrNull()?.nullIfZero()
|
||||
val attachmentExpires = data["attachment_expires"]?.toLongOrNull()?.nullIfZero()
|
||||
val attachmentUrl = data["attachment_url"]
|
||||
val truncated = (data["truncated"] ?: "") == "1"
|
||||
if (id == null || topic == null || message == null || timestamp == null) {
|
||||
Log.d(TAG, "Discarding unexpected message: from=${remoteMessage.from}, fcmprio=${remoteMessage.priority}, fcmprio_orig=${remoteMessage.originalPriority}, data=${data}")
|
||||
return
|
||||
}
|
||||
Log.d(TAG, "Received message: from=${remoteMessage.from}, fcmprio=${remoteMessage.priority}, fcmprio_orig=${remoteMessage.originalPriority}, data=${data}")
|
||||
|
||||
CoroutineScope(job).launch {
|
||||
val baseUrl = getString(R.string.app_base_url) // Everything from Firebase comes from main service URL!
|
||||
|
||||
// Check if notification was truncated and discard if it will (or likely already did) arrive via instant delivery
|
||||
val subscription = repository.getSubscription(baseUrl, topic) ?: return@launch
|
||||
if (truncated && subscription.instant) {
|
||||
Log.d(TAG, "Discarding truncated message that did/will arrive via instant delivery: from=${remoteMessage.from}, fcmprio=${remoteMessage.priority}, fcmprio_orig=${remoteMessage.originalPriority}, data=${data}")
|
||||
return@launch
|
||||
}
|
||||
|
||||
// Add notification
|
||||
val attachment = if (attachmentUrl != null) {
|
||||
Attachment(
|
||||
name = attachmentName,
|
||||
type = attachmentType,
|
||||
size = attachmentSize,
|
||||
expires = attachmentExpires,
|
||||
url = attachmentUrl,
|
||||
)
|
||||
} else null
|
||||
val icon: Icon? = if (iconUrl != null && iconUrl != "") Icon(url = iconUrl) else null
|
||||
val notification = Notification(
|
||||
id = id,
|
||||
subscriptionId = subscription.id,
|
||||
timestamp = timestamp,
|
||||
title = title ?: "",
|
||||
message = message,
|
||||
encoding = encoding ?: "",
|
||||
priority = toPriority(priority),
|
||||
tags = tags ?: "",
|
||||
click = click ?: "",
|
||||
icon = icon,
|
||||
actions = parser.parseActions(actions),
|
||||
attachment = attachment,
|
||||
notificationId = Random.nextInt(),
|
||||
deleted = false
|
||||
)
|
||||
if (repository.addNotification(notification)) {
|
||||
Log.d(TAG, "Dispatching notification: from=${remoteMessage.from}, fcmprio=${remoteMessage.priority}, fcmprio_orig=${remoteMessage.originalPriority}, data=${data}")
|
||||
dispatcher.dispatch(subscription, notification)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNewToken(token: String) {
|
||||
// Called if the FCM registration token is updated
|
||||
// We don't actually use or care about the token, since we're using topics
|
||||
Log.d(TAG, "Registration token was updated: $token")
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "NtfyFirebase"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue