Ordered broadcast tips

From Android Wiki

Jump to: navigation, searcha

A broadcast is just about the simplest way to transfer information between two apps. A broadcast can be unordered, which means the transfer is one-way (a notification e.g. that the clock has changed or the phone is waking from sleep), or ordered, which means receivers of the broadcast can return information in response to it. This article will talk about ordered broadcasts.

A broadcast is received by registering a BroadcastReceiver. This can be done either statically, via a <receiver> tag in the manifest, or dynamically, using one of the Context.registerReceiver calls. The former allows the receiver to run separately from the rest of the application, while the latter requires action from the application, which means it must already be started; choose whichever is appropriate for your purposes.

Sending An Ordered Broadcast

Sending an ordered broadcast can be done with one of the Context.sendOrderedBroadcast calls.

The documentation for the calls that include a resultReceiver argument say it “allows you to receive data back from the broadcast ... by supplying your own BroadcastReceiver when calling, which will be treated as a final receiver at the end of the broadcast -- its onReceive(Context, Intent) method will be called with the result values collected from the other receivers”. However, I could not get this to work—at least, not for communication with a broadcast receiver in another app. Every time I specified a resultReceiver, it would get the broadcast, but the receiver in the other app would not (this was in Android 2.2).

In the end, I had to use the simplest version of sendOrderedBroadcast. But first I registered my own receiver, and made sure it would be at the end of the chain by giving it the lowest allowable non-system receiver priority:

   final android.content.IntentFilter WhatIWant =
       new android.content.IntentFilter(MY_CUSTOM_ACTION_KEY);
   WhatIWant.setPriority(android.content.IntentFilter.SYSTEM_LOW_PRIORITY + 1);
   registerReceiver
     (
       /*receiver =*/ MyResultReceiver,
       /*filter =*/ WhatIWant
     );

Then my activity could send the request, and be assured the other app would get it, put a result into it, and then pass it on to MyResultReceiver:

   sendOrderedBroadcast
     (
       /*intent =*/ new android.content.Intent(MY_CUSTOM_ACTION_KEY),
       /*receiverPermission =*/ null
     );

Of course, don’t forget to unregister your receiver when you don’t need it any more. I did this in my activity’s onDestroy handler:

   unregisterReceiver(MyResultReceiver);

Responding To An Ordered Broadcast

The app that returns data to the ordered broadcast declares its receiver statically or dynamically, as described above. It’s worthwhile checking that the broadcast really is ordered, otherwise your broadcast receiver will crash trying to return data. E.g.

   public class MyResponder extends android.content.BroadcastReceiver
     {
   
       @Override
       public void onReceive
         (
           android.content.Context Ctx,
           android.content.Intent What
         )
         {
           if (isOrderedBroadcast())
             {
               String Action = What.getAction();
               if (Action != null)
                 {
                   Action = Action.intern();
                 } /*if*/
               if (Action == MY_CUSTOM_ACTION_KEY)
                 {
                   final android.os.Bundle Result = getResultExtras(true);
                   ... put data into Result ...
                   setResultCode(android.app.Activity.RESULT_OK);
                 }
               else
                 {
                   System.err.printf("MyResponder received unexpected action %s! Ignoring\n", Action); /* debug */
                 } /*if*/
             }
           else
             {
               System.err.println("MyResponder received unordered broadcast! Ignoring"); /* debug */
             } /*if*/
         } /*onReceive*/
   
     } /*MyResponder*/

Receiver Limitations

The system gives a broadcast receiver a maximum of 10 seconds to respond to the broadcast. Also, the onReceive method is called on your UI thread, which prevents you from being responsive to user events while it is running.

In Android 3.0 (Honeycomb) and later, it is possible to call goAsync to defer responding to the broadcast until later, to avoid holding up your UI thread at least (the time limit for responding still applies). But this option is not available pre-Honeycomb.

Personal tools