pusher / push-notifications-android

Android SDK for Pusher Beams
https://www.pusher.com/beams
MIT License
21 stars 21 forks source link

IllegalStateException in onMessageReceived for only data payload notifications #133

Open franciscohanna92 opened 2 years ago

franciscohanna92 commented 2 years ago

I have integrated Pusher Beams into an Android app following the docs. I have setup a service to process data notifications (only payload data).

When my app is fully closed (not in the background), the service throws the following exception:

022-02-25 12:14:09.509 16880-26719/com.staffcom.watch E/AndroidRuntime: FATAL EXCEPTION: Firebase-Messaging-Intent-Handle
    Process: com.staffcom.watch, PID: 16880
    java.lang.IllegalStateException: PushNotifications.start must have been called before
        at com.pusher.pushnotifications.PushNotifications.getDeviceInterests(PushNotifications.java:159)
        at com.staffcom.watch.pusher.beams.NotificationsMessagingService.onMessageReceived(NotificationsMessagingService.kt:28)
        at com.pusher.pushnotifications.fcm.MessagingService$underlyingService$1.invoke(MessagingService.kt:90)
        at com.pusher.pushnotifications.fcm.MessagingService$underlyingService$1.invoke(MessagingService.kt:15)
        at com.pusher.pushnotifications.fcm.MessagingService$WrappedFirebaseMessagingService.onMessageReceived(MessagingService.kt:57)
        at com.google.firebase.messaging.FirebaseMessagingService.dispatchMessage(com.google.firebase:firebase-messaging@@20.2.3:85)
        at com.google.firebase.messaging.FirebaseMessagingService.passMessageIntentToSdk(com.google.firebase:firebase-messaging@@20.2.3:55)
        at com.google.firebase.messaging.FirebaseMessagingService.handleMessageIntent(com.google.firebase:firebase-messaging@@20.2.3:34)
        at com.google.firebase.messaging.FirebaseMessagingService.handleIntent(com.google.firebase:firebase-messaging@@20.2.3:23)
        at com.google.firebase.messaging.EnhancedIntentService.lambda$processIntent$0$EnhancedIntentService(com.google.firebase:firebase-messaging@@20.2.3:43)
        at com.google.firebase.messaging.EnhancedIntentService$$Lambda$0.run(Unknown Source:6)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at com.google.android.gms.common.util.concurrent.zza.run(Unknown Source:6)
        at java.lang.Thread.run(Thread.java:923)

This is my service implementation:

class NotificationsMessagingService : MessagingService() {
    private val json = Json { ignoreUnknownKeys = true }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        val messagePayload = remoteMessage.data["payload"]

        if (messagePayload != null) {
            val event = json.decodeFromString<Event>(messagePayload)
            val interests = PushNotifications.getDeviceInterests()
            when (event.eventName) {
                "added" -> {
                    val eventWithPayload = json.decodeFromString<EventWithPayload<UserTeamEventPayload>>(messagePayload)
                    interests.add("team-${eventWithPayload.data.id}")
                }
                "removed" -> {
                    val eventWithPayload = json.decodeFromString<EventWithPayload<UserTeamEventPayload>>(messagePayload)
                    interests.remove("team-${eventWithPayload.data.id}")
                }
            }
            PushNotifications.setDeviceInterests(interests.toSet())
            Log.i("NotificationsService", event.eventName)
        }
    }
}

The error makes sense, since PushNotifications.start is only called when my MainActivity is constructed and in the service I'm trying to update the device interests (wich need Pusher to be initialized). How can I initialize it for this service? I don't have access to the application context to do it. Could I check if the PushNotifications instance has been instantiated before handling the notifications in the service?

benw-pusher commented 2 years ago

As you say, this error makes sense as the app is completely closed and so no PushNotifications instance currently exists. As you are not able to initialise the instance then you may need to store the new interest values and then update the interests the next time the mainActivity starts.

As an aside, it looks as though you may be managing device <> interest associations on your server sideL detecting when the interest needs to change and then sending a background notification to get the device to carry out the notification. You may consider using Authenticated Users which would allow you to manage user <> topic associations at your server (without the need for these background notifications) and then when you come to publish a notification you can lookup which users should be targeted.

franciscohanna92 commented 2 years ago

Thanks for your answer! That's exactly what I'm doing.

Will the device receive push notifications even when the app is fully closed using the Authenticated Users feature? If so, I'll redesign my solution and implement it.