I was implementing push notification into the Activity Filter Android app, and noticed that they were not working having previously encountered completely different issues when implementing them on the iOS app.

Given that (similar to my iOS setup) both the Training Plan and Activity Filter apps were using the same code for push notification functionality I went ahead and checked if notifications were working in the Training Plan app. They were not bangs head.

I utilise Amazon Pinpoint for managing push notifications and I have a little test node script for testing if things are working correctly. One of the functions I have written lists all the endpoints for a given user ID. It essentially lists all the iOS/Android devices and email addresses associated with a given user.

Amazon Pinpoint endpoint response

The response I was getting looked correct, and the OptOut property that I'd been having issues with on iOS was correctly set to NONE.

On thing that did look untoward was the Address property which looked like a stringified representation of an object rather than a.. string.

I checked the output for an iOS device which was indeed a string. This looked like the issue, but I stupidly made the assumption that Pinpoint wouldn't allow you to set an invalid device token.

Debugging

I found what I believed to be the offending code, and immediately noticed that Task<InstallationResult> was being passed to the closure.

The offending code

I was calling registerDeviceToken with a stringified representation of the result property. This looked wrong.

I remember a while ago I updated the versions of my various Firebase dependencies. The result of this update was some changed APIs. I remember having to rewrite this code, and my thought process was "These methods have the word token in them, i'll just stringify that".

It's just ashamedly bad. Pure incompetence by me. Testing.. pft. Nah.

Fix

So.. whilst the InstallationTokenResult does have a token property associated with it it.result.token is not what I should have been passing to registerDeviceToken anyway facepalm.

What you actually want to use is the FirebaseMessaging token which can be accessed by attaching a listener to a call to FirebaseMessaging.getInstance().token.

Pass the correct token to registerDeviceToken and all of a sudden everything is working.

Conclusion

I blame Google. They drastically changed their APIs and don't update their documentation.

I am definitely not to blame /s