I have 2 services in my app that sometimes communicate with each other via broadcast intents. The time between an intent being sent and getting delivered on Android 13 is 1-2ms (tested on a Pixel 4XL). The time on Android 14 is ~500ms (tested on a Pixel 6 Pro)!
The slow intent delivery is causing a lag in my app that wasn't there before. I know about the context-registered broadcasts being queued while apps are cached as of Android 14, but this is between an actively running foreground service and an Accessibility service. Are all intents slowed down on Android 14?
Does anyone know what may be causing this performance issue?
EDIT: Upon further testing, it looks like intents are delayed 500ms when there is no activity in the foreground. There is no delay while there IS an activity in the foreground. The delay appears as soon as you leave the app, even without killing it.
So it appears that intents are slowed down even between foreground services, if there is no activity in the foreground. Is this documented?
Is there anything I can do to prevent this? I'm using a dynamically registered receiver:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(broadcastReceiverInternal, intentFilter, RECEIVER_NOT_EXPORTED);
} else {
registerReceiver(broadcastReceiverInternal, intentFilter);
}
Setting it to exported does not make a difference.
EDIT 2: This does not seem to affect Samsung's Android 14 as tested on a Samsung A15 5G with Android 14. It is still an issue on a Pixel 8 Pro with Android 15.
you were correct, there is no added delay if the intent is delivered to a manfiest-registered receiver, although it is a bit slower (~10ms instead of 1-3ms)
That suggests that your ~500ms slowdown was due to the new queuing system seen on Android 14. It's possible they might improve that someday, but I wouldn't count on it.
How do I use this static receiver (now in its own class) in my service which was supposed to receive the message?
At a high level, you would use it the same way as you did your dynamic receiver. They receive broadcasts and act upon them.
Ideally, your service has very little actual business logic. While book examples (👋) will tend to have services do real work, that's to keep the examples simple. A service should be focused purely on setting itself up (e.g., displaying the foreground notification) and handling whatever lower-level communication it needs to (e.g., implementing the API surface for accessibility). Everything else should reside elsewhere, such as in an object that gets injected into the service. That way, the "elsewhere" can be tested in isolation.
If you have that architecture, having the static receiver also get the "elsewhere" injected and calling methods on it is not significantly different than having the dynamic receiver call methods on the one injected into the service itself. The receiver, like the service, should do next to nothing on its own, other than pass relevant information to the "elsewhere", which does the real work.
If you want to try to get rid of the ~10ms latency, you could experiment with a bound connection between the services, getting rid of the broadcast entirely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With