November 28, 2014

Gettin’ On The (Message) Bus, Part Two

In our last episode, we discussed how the Android Intent systems functions, in effect, like a message bus, and how one can set up an IntentReceiver to serve as a consumer of bus messages. Today, let’s complete the picture, creating both a message consumer and producer, as two separate applications, so you can see how one Android application can send messages to another.

Since this post will be discussing two full applications, we’ll only be showing relevant bits of the code in the post itself. You can download the pair of Android projects here — the code is available under the Apache 2.0 License.

To set up messaging between two Android applications, you need to:

  1. Choose a name for the Intent, to distinguish it from other Intent names already in use
  2. Decide how you are going to package useful information into the Intent, such as by using putExtra()
  3. Set up an IntentReceiver, as in the previous post, to watch for an Intent of your chosen name
  4. Have your message producer create a properly-named Intent and call broadcastIntent(), so the Android underpinnings will deliver the Intent to your patiently-waiting receiver

Let’s take a look at the consumer side, implemented as a ListActivity:

[sourcecode language=’java’]public class ConsActivity extends ListActivity {
protected static final String BUS_MSG=
new String(“com.commonsware.android.intents.BUS_MSG”);
protected static final String BUS_MSG_BODY=
new String(“com.commonsware.android.intents.BUS_MSG_BODY”);
protected final IntentFilter filter=new IntentFilter(BUS_MSG);
private ConsIntentReceiver receiver=new ConsIntentReceiver();
private ArrayAdapter adapter;

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);

adapter=new ArrayAdapter(this,
android.R.layout.simple_list_item_1);
setListAdapter(adapter);
registerReceiver(receiver, filter);
}

@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}

class ConsIntentReceiver extends IntentReceiver {
@Override
public void onReceiveIntent(Context context, Intent intent) {
adapter.addObject(intent.getStringExtra(BUS_MSG_BODY));
}
}
}[/sourcecode]

The name of our magic Intent for inter-application communication is given the local name of BUS_MSG, but that’s just a static string ("com.commonsware.android.intents.BUS_MSG"). We create an IntentFilter to watch for such messages, and in onCreate() we use that filter to connect our ConsIntentReceiver to watch for these messages. The net is that ConsIntentReceiver#onReceiveIntent() will get called for each BUS_MSG our producer sends. In ConsIntentReceiver#onReceiveIntent(), we extract the body of the message (BUS_MSG_BODY) via getStringExtra() and pop that value into our list. We should get a new list entry for each message the producer produces.

So, without further ado, let’s see the producer:

[sourcecode language=’java’]public class ProdActivity extends Activity {
protected static final String BUS_MSG=
new String(“com.commonsware.android.intents.BUS_MSG”);
protected static final String BUS_MSG_BODY=
new String(“com.commonsware.android.intents.BUS_MSG_BODY”);
private EditText body;

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
body=(EditText)findViewById(R.id.body);

((Button)findViewById(R.id.send))
.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent i=new Intent(BUS_MSG);

i.putExtra(BUS_MSG_BODY, body.getText().toString());
broadcastIntent(i);
}
});
}
}[/sourcecode]

For simplicity of the demo, we re-declare BUS_MSG and BUS_MSG_BODY. In theory, those would be defined in some central source code spot that both projects could pull from.

The activity is just a field (EditText) and button (Button). When the user clicks the button, we take the contents of the field, pour that into a BUS_MSG Intent as the BUS_MSG_BODY “extra” (via putExtra()), then call broadcastIntent() to send that Intent on its merry way.

To see this in action, compile both projects and upload them to your Android emulator. Start up the BusConsumer activity, then start up the BusProducer activity. In the producer, type in some text and send it using the button. Switch back to the BusConsumer (click the Home button, then on the BusConsumer icon), and you will see your text in the list.

Note that we are running two completely separate applications here — an Intent can cross process boundaries with impunity. However, there is nothing to prevent you from using this technique within a single application (e.g., a service letting an activity know about newly-arrived information).

Our next series of Building ‘Droids posts will look at creating fancy lists — not just plain text, but list entries with fancier formatting, icons, and the like. Along the way, we’ll explore some dusty corners of the adapter framework, learn how to inflate views, and so on. Until then, happy coding!


  • http://www.wikio.com/user/rape-video/bio UnomyUnrendvew

    Thanks for the post

  • Jhony

    Hi,
    Thanks for the post..!

    Can you put the whole code, i’m facing problem in using intents on SDK 1.0 version

  • http://commonsware.com/Android/ Mark Murphy

    All Android tutorials from mid-August and earlier are for the M5 version of the SDK. Android underwent serious changes between M5 and today’s SDK, so the exact code here will not work.

    This tutorial is also included in my book, so you can download the source code for free. Visit http://commonsware.com/Android/ and click on the Source Code link for the latest version.

  • Adam

    Hi, this is a good tutorial, but there is a 404 Not Found on the source.

  • http://commonsware.com/Android/ Mark Murphy

    Ah. This post is as old as the hills. The source code, unfortunately, is no longer really available. I have some related code as a part of my book — visit http://commonsware.com/Android/, scroll down, and click the Source Code link.

  • http://www.jfhostreview.com jfhostreview

    busing messages is key

  • Pingback: antitabetic distinguish batty

  • Pingback: adipose ambidexterity beltmaking