Processing Ordered Broadcasts

One of the things that I find most interesting and powerful about Android is the concept of broadcasts and their use through the BroadcastReceiver class (from now on, we will call implementations of this class “receivers”). As this document is about a very specific usage scenario for broadcasts, I will not go into detail about how they work in general, so I recommend reading the documentation about them in the Android developer site. For the purpose of this document, it is enough to know that broadcasts are generated whenever something interesting happens in the system (connectivity changes, for example) and you can register to be notified whenever one (or more) of those broadcasts are generated.

While developing Right Number, I noticed that some developers who create receivers for ordered broadcasts do not seem to be fully aware of what is the correct way to do it. This suggests that the documentation could be improved; in any case, things often still work(although it is mostly by chance than anything else).

Non-ordered vs. Ordered Broadcasts

In non-ordered mode, broadcasts are sent to all interested receivers “at the same time”. This basically means that one receiver can not interfere in any way with what other receivers will do neither can it prevent other receivers from being executed. One example of such broadcast is the ACTION_BATTERY_LOW one.

In ordered mode, broadcasts are sent to each receiver in order (controlled by the android:priority attribute for the intent-filter element in the manifest file that is related to your receiver) and one receiver is able to abort the broadcast so that receivers with a lower priority would not receive it (thus never execute). An example of this type of broadcast (and one that will be discussing in this document) is the ACTION_NEW_OUTGOING_CALL one.

Ordered Broadcast Usage

As mentioned earlier in this document, the ACTION_NEW_OUTGOING_CALL broadcast is an ordered one. This broadcast is sent whenever the user tries to initiate a phone call. There are several reasons that one would want to be notified about this, but we will focus on only 2:

  • To be able to reject an outgoing call;
  • To be able to rewrite the number before it is dialed.

In the first case, an app may want to control what numbers can be dialed or what time of the day numbers can be dialed. Right Number does what is described in the second case so it can be sure that a number is always dialed correctly no matter where in the world you are.

A naive BroadcastReceiver implementation would be something like this (note that you should associate this receiver with the ACTION_NEW_OUTGOING_CALL broadcast in the manifest file for your application):

public class CallReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Original phone number is in the EXTRA_PHONE_NUMBER Intent extra.
    String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);

    if (shouldCancel(phoneNumber)) {
      // Cancel our call.
      setResultData(null);
    } else {
      // Use rewritten number as the result data.
      setResultData(reformatNumber(phoneNumber));
  }
}

The receiver either cancels the broadcast (and the call) or reformats the number to be dialed. If this is the only receiver that is active for the ACTION_NEW_OUTGOING_CALL broadcast, this will work exactly as expected. The problem arrises when you have, for example, a receiver that runs before the one above (has a higher priority) and that also changes the number as instead of looking at previous results of other receivers, we are just using the original (unmodified) number!

Doing It Right

With the above in mind, here is how the code should have been written in the first place:

public class CallReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Try to read the phone number from previous receivers.
    String phoneNumber = getResultData();

    if (phoneNumber == null) {
      // We could not find any previous data. Use the original phone number in this case.
      phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
    }

    if (shouldCancel(phoneNumber)) {
      // Cancel our call.
      setResultData(null);
    } else {
      // Use rewritten number as the result data.
      setResultData(reformatNumber(phoneNumber));
  }
}

We first check if we have any previous result data (which would be generated by a receiver with a higher priority) and only if we can not find it we use the phone number in the EXTRA_PHONE_NUMBER intent extra.

How Big Is The Problem?

We have actually observed phones with a priority 0 receiver for the NEW_OUTGOING_CALL intent installed out of the box (this will be the last one that is called after all others) that completely ignores previous result data which means that, in effect, they disable any useful processing of ACTION_NEW_OUTGOING_CALL (other than canceling the call, which would still work). The only workaround for this is to also run your receiver at priority 0, which works due to particularities of running 2 receivers at the same priority but, by doing that, you break one of the few explicit rules for processing outgoing calls:

“For consistency, any receiver whose purpose is to prohibit phone calls should have a priority of 0, to ensure it will see the final phone number to be dialed. Any receiver whose purpose is to rewrite phone numbers to be called should have a positive priority. Negative priorities are reserved for the system for this broadcast; using them may cause problems.”

Conclusion

There are programs out there that do not play well with others. Urge any developers of such programs to read this post and fix their code. This will make Android better for both developers and users.

Notes About Priorities

  • For the NEW_OUTGOING_CALL intent, priority 0 should only be used by receivers that want to reject calls. This is so it can see changes from other receivers before deciding to reject the call or not.
  • Receivers that have the same priority will also be executed in order, but the order in this case is undefined.
  • Use non-negative priorities only. Negative ones are valid but will result in weird behavior most of the time.

Google Places Tidbits and Quirks

1. Top Contributor EHG reported in the Google Places forums yesterday that the “Report a Problem” Link has disappeared from the bottom of your Google Places Page. It is still MIA this AM:

2. Some readers reported here and on Twitter that Google was no longer allowing them to verify via phone and could only verify by postcards. When I attempted to do so yesterday, I was allowed to verify by postcard. Several possibilities:
– Google is becoming more stringent on who is allowed to phone verify in an effort to increase trust level
– Google is changing the procedure to post card verification only and certain users are seeing the changes first

Are you experiencing this limitation?

3. Several Twitter commenters (@mktgbill (Bill Allen), @DavidKyle & @KiwiMarketing) noted that they were seeing “a shift to the 7 pack + organic and away from Places/Organic mix?” As Matt McGee has pointed out there has been no discernible rhyme or reason as to which shows when and there is an increasing variety of displays. It has been so volatile that I just haven’t lost any sleep over it. I have not been tracking specific search results either so I can’t verify the observations.

Are you seeing more old style 7-Packs showing?

4. TripAdvisor Reviews are reported as once again missing in action by readers and posters to the forums. For those of you that missed the Google TripAdvisor Kerfuffle in December see this article.

Gib Olander

Gib Olander currently serves as Director of Business Development for Localeze and frequent speaker at search marketing conferences. Localeze is a leading provider of merchant content management services, which includes; collection, organization, validation and distribution of merchant content. This content is widely used in the local ecosystems and the data is the foundation of place information at a large number of sites including Bing, Facebook and Twitter amongst others.

From this vantage point, Gib sees the industry dynamics from the inside out, providing useful insights to many in the industry.

***

2010 was a transformative year, I struggle with calling it a year of convergence or a year of fragmentation. Convergence because everywhere we looked a local component was added, we’ve had: social local, mobile local, local search, local commerce, mobile Local search, social mobile search, ETC. Or was it a year for fragmentation with traffic being driven to businesses from a wider variety of sources than ever before, I don’t think 2010 answered many questions but it certainly built the infrastructure for where the space is going in the future, it’s never been a better time to be involved in the Local search ecosystem.

This early in the year article set the tone for the change taking place in the internet space in general. In February you heard major Local publishers declare that Facebook was the leading source for traffic to their site over Google with Facebook growing at an incredible rate it was only natural that they launch a local initiative.

By 2011 it’s expected that 80% of mobile devices are going to be GPS enabled which changes everything. This location based service patent by Apple is an example of the innovation going on in mobile. There are now more than 6000 Location based or at least location aware apps for the iPhone alone. 2010 was the year of Mobile & Local with great innovation from companies like Foodspotting and in the advertising world of Local & Mobile new initiatives like Where Ads were launched creating a new revenue models to fuel the growth.

With foursquare usage continuing to grow and dozens of services, games, applications, networks adding check in functionality it is a trend to watch. One of the most impactful presentation’s I witnessed this year was from Michael Metcalf from Yahoo, he really gave me an understanding of how important our personal Location History and our Spatial Network are, it’s about so much more than the next badge you are going to win, it’s just a matter of time before the value gets unlocked to its fullest.

Local as an important layer of context really emerged, Twitter embraced that concept with their places announcement showing that the context of a clearly defined place is a powerful tool.

Google as friend or foe became a hot topic again in 2010 first with Yelp then with TripAdvisor,  resulting in Google launching its own service/platform to create the content it wants.

Google continued to amaze with the amount of innovation they rolled out during the year with the most notable being the self-described search refinement of Google Place Search resulting in the ever increasing importance of establishing, monitoring and managing your business identity with a standard and consistent Name, Address and Phone Number (NAP)

From the Localeze perspective I felt like we had an amazing year of progress  Here is a list of our press releases in 2010

Thanks for a great year, I can’t wait to see how things emerge in 2011!