Hacker News new | ask | show | jobs
by bchimp 2560 days ago
This has been true for awhile once they forced apps to use API26 or higher (if you want to be listed in the Play store, and really, there is no other place if you want decent exposure.)

I had a similar experience switching from "real background" to using FCM. I understand the battery saving motivation, but the problem is that the performance of the google service is terrible. The response time of my simple notification system was nearly instantaneous, but OK google, I'll play your game. I put together something that used FCM and it can take 15 or 20 MINUTES to get even a "high priority" message from FCM.

Reading the google docs, apparently google will deprioritize notifications that are shown but "not intereacted with" in a timely manner, so that is another source of delay.

I think the crux of the matter is that notifications have multiple purposes: signaling, and advertising, etc. Google hasn't provided a way for an app to declare its use case. So, you get policies to prevent notification spam creeping in and messing with basic app signaling functionality.

In the end, I kept both my "in-house" notifications for use by older Androids, and a kluge that uses FCM in addition, with some hacks to get somewhat better FCM performance. I live with the notification in Oreo+ and just tell users to ignore it (but honestly, I don't think users care that much.)

3 comments

>The response time of my simple notification system was nearly instantaneous, but OK google, I'll play your game. I put together something that used FCM and it can take 15 or 20 MINUTES to get even a "high priority" message from FCM.

Letting your phone actually sleep is the battery saving feature. Also, you get throttled for high volume so check that as well.

If you think your messages are so important to have a constant socket open then make a foreground service. You're abusing a system that is really not suited to your needs.

Some types of messages do require immediate attention of the user, or are of highest value if delivered immediately. Instant messaging apps have been using notifications for a long time and did not require a foreground service. Expecting instant delivery of that class of messages is not abusing the system.
Even Apple, with its distaste for background processing, lets you declare an app with "VOIP" mode or something, where iOS manages the socket for you. You get access to simple server-based signaling, and as a bonus, you get to avoid the whole push-notification system.

Google just seems to have glommed everything into FCM. In the FCM console, push-notifications are really treated as a user-engagement/advertising thing. Throttling and spam prevention makes sense for that.

Maybe Android has something like the iOS VOIP mode that doesn't involve annoying the user with scary battery notifications, but I couldn't come up with anything at the time.

While it's not really possible to do this in your own background service any more, GCM still supports this use case. This is the deprioritization the grand parent is talking about. If there's already a notification showing you won't get instant follow up responses. It's a compromise to be sure but if you want to break that compromise you have to make a foreground service.
It was supposed to be possible, via standard notification mechanism and scheduler, new in 7.x. If Google starts flagging apps pinging network off the scheduler, everyone will get even more angry, as there will be a glut of foreground notifications just because they broke a use case.
For my use case, the volume of messages was not an issue. This isn't a huge app that is pushing out tons of notifications. We're talking 10's or 100's a day, maybe.

In fact, it didn't matter at all once the initial notification was visible whether follow-on notifications were displayed. Possibly the fact that I was locally dropping the notifications (because the user didn't need them), the system counted those as "notification that weren't interacted with, so I'm going to slow you down at the server."?

I have no idea, and no way to find out, since FCM is pretty opaque at this point.

15-20 minutes for a high-priority FCM message isn't normal.

Either your app is being rate limited by the server, or there's something unique about your network setup that is preventing push messages from getting through. There's not enough context here to know what's going on.

(Plenty of instant messaging apps use high-priority FCM messages, and get near instant delivery.)

I agree, it isn't normal, and I was scratching my head at the time as to why FCM would deliver the messages near instantly on older android models. The delayed delivery happened on Oreo+ phones. Oddly, I also noticed Whatsapp not delivering messages in a timely fashion (even when I had it opted out of battery saving). Background notifications in general started acting odd for Oreo+ phones.

> There's not enough context here ...

Sadly, actually getting context you can use to debug something like this from FCM is nearly impossible. The end result is you just take a WAG and hope for the best when the app gets in the field.

Signal switched to FCM about 4 months ago and I've had constant delayed-notifications issues too, usually in the 20 minute range. I can see the problem in Signal itself, the "sent" and "delivered" timestamps will be 20 minutes apart despite be actively doing stuff on my phone -- so the internet connection is there and the phone isn't sleeping. When I actually re-open the Signal app all the notifications flood in at once.

Maybe Google is assuming I don't care about Signal notifications because I don't always "interact" with them right away (I'll leave messages on unread for a bit if I'm busy), but I really wish there was a way to mark Signal and other instant messaging apps as "always high priority". Signal has battery optimizations disabled but that doesn't seem to help.

Hey! Signal dev here. We've actually seen delayed notification both before and after the switch to FCM. My guess is that newer Android versions are just becoming more and more aggressive with their battery optimizations.

We send high-priority FCM messages, but the device will still bundle them together in order to deliver them in batches. Even worse, there are times we are delivered an FCM message but network access will be invisibly restricted, further delaying our ability to retrieve the actual message content (for obvious reasons, we can't include the message content in the FCM message itself). We're continuing to try new things, but it'd be nice if there was some official guidelines on how to avoid these FCM pitfalls.

If you receive "actual contents" separately from GCM ping, you are probably being hit by Doze Mode. Doze is disabled for foreground Services, so your best bet is starting a foreground Service (via startForegroundService) _and_ taking wake lock (from within foreground Service, after your app is considered fully foreground).

Historically Android devices used to sleep by entering low-power CPU mode (sometimes complete with low-power radio and WiFi modes). In that mode all apps and kernel are heavily CPU throttled to the point when you can get network timeout because kernel TCP stack can't send packets fast enough. This is what gets disabled when you take a wake lock.

Doze Mode throttles individual apps by moving them into low-priority cgroup. In effect Linux kernel hardly ever schedules your process anymore. Doze Mode is not disabled by wake locks, only by starting a foreground Service.

Both Doze Mode and low-power CPU mode can coexist, leading to effectively 110% loss of CPU time by your process.

Interesting, so our current method is to do just what you said -- start a foreground service and acquire a wakelock. But we only do it if our network request takes longer than n seconds (to avoid always showing foreground notifications). We still hit the issue. Other Googlers have told me I may be running into some race condition that happens with foreground services and doze.

Thank you for the detailed info about how those modes work though -- it certainly de-mystifies the network problems!

Thank you for your work on Signal. Despite my griping, Signal is still my primary messaging app and I love it.

>there are times we are delivered an FCM message but network access will be invisibly restricted, further delaying our ability to retrieve the actual message content

This is new... If this is happening regularly, maybe you should display a generic "message available" notification? I assume actually opening the app un-restricts network access and everything works fine from there -- it'd be nice to know I have a message waiting in limbo.

> I put together something that used FCM and it can take 15 or 20 MINUTES to get even a "high priority" message from FCM.

(from what I remember of some android documentations) Your definition of "high priority" is different from Google's one, which is also different from the end-user's definition. Google probably favors the end-user's preferences more than the developer's preferences. If the user wants all notifications asap from a particular app, the system will do a best effort to deliver, given all the other apps notifications and the current battery level.