Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

More than one BroadcastReceiver for the same Intent with contradictory doc and practice

In the documentation for Google Analytics for Android it has a note saying:

Note: Only one BroadcastReceiver class can be specified per application. Should you need to incorporate two or more BroadcastReceivers from different SDKs, you will need to create your own BroadcastReceiver class that will receive all broadcasts and call the appropriate BroadcastReceivers for each type of Broadcast.

While somewhat confusing there doesn't appear to be a single element of truth in that statement. In particular you can have multiple receivers in an application and they work just fine. Other places have interpreted this to mean that you can't have more than one receiver for a particular Intent action. However in my testing including on a Tablet/3.2 device as well as a G1/1.6 device I do see that all broadcast receivers for com.android.vending.INSTALL_REFERRER are indeed called.

I have implemented a receiver that will call others based on some config and was updating it use the PackageManager instead and get entries from the manifest, but this all appears completely unnecessary.

So what is the truth? Is the analytics doc a complete crock or is there some truth behind the note?

like image 243
Roger Binns Avatar asked Mar 14 '12 01:03

Roger Binns


People also ask

Which method will be called when intent broadcast shall be received by BroadcastReceiver?

A broadcast receiver is implemented as a subclass of BroadcastReceiver class and overriding the onReceive() method where each message is received as a Intent object parameter.

What is a BroadcastReceiver?

Android BroadcastReceiver is a dormant component of android that listens to system-wide broadcast events or intents. When any of these events occur it brings the application into action by either creating a status bar notification or performing a task.

What is intent How are they used to broadcast and receive events?

Android uses Broadcast Intents extensively to broadcast system events like battery-charging levels, network connections, and incoming calls. Broadcasting Intents is actually quite simple. Within your application component, construct the Intent you want to broadcast, and use the sendBroadcast method to send it.


2 Answers

Answering my own question. The Android system works perfectly well with multiple receivers for the same intent. It will call all of them as expected.

Android Market/Play Store/Finsky has been deliberately written to not use standard Android practise and deliberately ensures that only the first one is called. Consequently you have to do the multiplexing as described on the analytics page, and not trust referral tester tools.

This code in the onReceive method will let you find all the receivers.

// clear out classname intent.setComponent(null); // do what Market/Store/Finsky should have done in the first place List<ResolveInfo> l=context.getPackageManager().queryBroadcastReceivers(intent, 0); 

Then look in the applicationInfo in each ResolveInfo, and use the name (after checking exported and enabled), and don't call yourself.

I've updated Referral Tester to match the Market/Store behaviour and make it easier to do testing of install referrers. See https://github.com/rogerbinns/referraltester

like image 144
Roger Binns Avatar answered Oct 02 '22 10:10

Roger Binns


I'm not sure I understand what the warning in the Google Analytics SDK document is about, but I suspect they mean that you can't register the same class twice with different filters. However I know you can have multiple broadcast receivers.

So for example I don't think this works:

<receiver android:name="com.sample.myapp.MyAnalyticsReceiver" android:exported="true">   <intent-filter>     <action android:name="com.android.vending.INSTALL_REFERRER" />   </intent-filter> </receiver> <receiver android:name="com.sample.myapp.MyAnalyticsReceiver" android:exported="true">   <intent-filter>     <action android:name="android.intent.action.BOOT_COMPLETED" />   </intent-filter> </receiver> 

However I know this does:

<receiver android:name="com.sample.myapp.MyAnalyticsReceiver" android:exported="true">   <intent-filter>     <action android:name="com.android.vending.INSTALL_REFERRER" />   </intent-filter>   <intent-filter>     <action android:name="android.intent.action.BOOT_COMPLETED" />   </intent-filter> </receiver> 

This also works for installing different receivers monitoring the same broadcast events:

<receiver android:name="com.google.android.apps.analytics.AnalyticsReceiver" android:exported="true">   <intent-filter>     <action android:name="com.android.vending.INSTALL_REFERRER" />   </intent-filter> </receiver> <receiver android:name="com.sample.myapp.MyAnalyticsReceiver" android:exported="true">   <intent-filter>     <action android:name="com.android.vending.INSTALL_REFERRER" />   </intent-filter> </receiver> 

I found nothing in the Android Developer documentation that would explain the warning. The only other reason for the warning is if the INSTALL_REFERRER intent is sent as an Ordered Broadcast and the default Google Analytics Receiver aborts further broadcast, unlikely but possible - as that intent comes from the Google Market/Play app, the behavior of the INSTALL_REFERRER messages has changed with different versions.

like image 25
cistearns Avatar answered Oct 02 '22 10:10

cistearns