Android: Broadcast sent, receiver registered, but receiver doesn’t receive broadcast

I should blog more often about things I learn about.

In a native Android app written in Kotlin, I have a LifecycleService class with below code to send a broadcast:



Based on the logcat, the broadcast is being sent.

However, below BroadcastReceiver in an Activity doesn’t receive the broadcast, even while it is visible:

The above BroadcastReceiver is registered from the Activity’s onCreate function, like so:

Attempt #1: LocalBroadcastManager – it worked, but…

After browsing the web for potential solutions I came across LocalBroadcastManager. The broadcast was successfully received by the receiver after I changed the sendBroadcast’s applicationContext and the registerBroadcast’s ContextCompat into LocalBroadcastManager.getInstance(Context).

That is, LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(eventIntent) and LocalBroadcastManager.getInstance(this).registerReceiver(customEventReceiver, filter).

The problem with this approach is that LocalBroadcastManager has been deprecated:

Important changes since 1.0.0

androidx.localbroadcastmanager has been fully deprecated. There will be no further releases of this library. Developers should replace usages of LocalBroadcastManager with other implementations of the observable pattern. Depending on the use case, suitable options may be LiveData or reactive streams.

https://developer.android.com/jetpack/androidx/releases/localbroadcastmanager

Ideally, the solution should not be a deprecated one.

As to why LocalBroadcastManager made my receiver work, I think it’s because it “bridged” 2 components that weren’t really supposed to be able to communicate. Because from the Android docs:

LocalBroadcastManager is an application-wide event bus and embraces layer violations in your app: any component may listen events from any other.

Why it works, and why it’s been deprecated, apparently have the same explanation. 😅

Attempt #2: Use applicationContext on the sender and receiver — Nope!

I reverted my code to the original, and just made sure they all used applicationContext, matching the context used in the service’s broadcast sender applicationContext.sendBroadcast(eventIntent).

So that my registration became:

Hmm… Nope! that didn’t let my receiver get the broadcast.

Attempt #3: Make it an explicit broadcast — YES, IT WORKS!

I reverted my code again to try another approach, which is to make the broadcast an explicit one.

So, in my service, I simply set the package name as shown in code below:

And with this 1 line changed in code, my BroadcastReceiver now receives the broadcast! Plus, there’s no deprecated class used here so we prevented 1 new technical debt. :3

Yeah, I think I’ll stick to the 3rd attempt’s approach!

Why does this approach work, though? It’s because starting from Android API level 26, there’s been restriction on implicit broadcasts.

As part of the Android 8.0 (API level 26) background execution limits, apps that target the API level 26 or higher can’t register broadcast receivers for implicit broadcasts in their manifest unless the broadcast is sent specifically to them. However, several broadcasts are exempted from these limitations. 

https://developer.android.com/develop/background-work/background-tasks/broadcasts/broadcast-exceptions

My original code’s broadcast Intent was an implicit one, but specifying a package name converted it into an explicit one, consequently lifting the limitation applied to implicit broadcasts!

Related Posts:

Posts that may be related to "Android: Broadcast sent, receiver registered, but receiver doesn’t receive broadcast":

Catzie

An odd human being who happens to have a variety of ever-changing interests, but right now they are programming, making up silly song/rap lyrics, K-pop, drawing, creating unique dessert/drink flavors, obsessing about finding out how some things works, automation, anime, video games... Ran online dessert shops Cookies PH and Catzie's Cakery in her past life.

Leave a Reply

Your email address will not be published. Required fields are marked *