Pages

Jumat, 27 April 2012

An Android coder’s introduction to broadcast receivers


Takeaway: Android’s version of a party line is its BroadcastReceiver class. This demo shows how to create, register, and use a broadcast receiver to listen for device orientation changes.

When I was a kid, we lived out in the sticks, and our phone service was what was known as a party line. I suspect some of you reading this blog have no idea what a party line is, so both to educate and date myself let me quickly explain. A party line was a phone line that you shared with one or more of your neighbors.
In our case, we shared a phone line with Mrs. Stump, the elderly woman who owned an apple orchard across the street. When you wanted to make a call, you picked up the receiver, but before dialing (on a real honest to goodness rotary dial), you had to first listen and see if Mrs. Stump was already on the phone. If she was, the polite thing to do was hang up. (Mrs. Stump seemed ancient to me back then, but she had very sharp hearing and I assure you if you did not do the polite thing later that day Mrs. Stump would have a chat with your mother.)
What does any of this have to do with Android development? Well, the Android operating system has an internal mechanism called a broadcast/receiver model that works a bit like the old party phone lines. The operating system and even other applications periodically broadcast messages about things that are happening, such as the battery status changed, the Wi-Fi came on, or the phone’s orientation changed. These are all things that are being announced in real time, and if you know how to pick up the phone and listen, your code can react accordingly without the overhead of unnecessarily polling for the state that interests you.
You can read Google’s official explanation of a BroadcastReceiver. If like me though you prefer a code sample, I’ve created a short demonstration of how to create, register, and utilize a broadcast receiver to listen for device orientation changes. You can follow along with the tutorial, ordownload the entire project and import it into your workspace directly.
1. Create a new Android project in Eclipse. Target the SDK for Android 1.6 or greater. Be sure to change the startup file to Main.java.
2. In our /res/layout folder we will want to define the layout for our Main.java file. Open main.xml and add a couple of text views.
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=http://schemas.android.com/apk/res/android
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#00ff00"
android:textSize="20dip"
android:text="Broadcast Receiver Demo" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="(rotate the phone to activate receiver)" />
</LinearLayout>
3. Let’s take a look at the Main.java file in our /src folder. To start with, we will want to declare a new broadcast receiver. I’ve done this inline, though if you don’t prefer Java’s inline syntax, you can always extend BroadcastReceiver with your own custom class.
Main.java
package com.authorwjf.broadcast_receiver;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.os.Bundle;
import android.widget.Toast;
public class Main extends Activity {
private BroadcastReceiver the_receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context c, Intent i) {
int orientation = getBaseContext().getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
Toast.makeText(getBaseContext(), "I'm still standing.", Toast.LENGTH_SHORT).show();
} else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(getBaseContext(), "Help! I've fallen and I can't get up.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getBaseContext(), "?!#$%!?", Toast.LENGTH_SHORT).show();
}
}
};
private IntentFilter filter = new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED);
}
4. With the receiver defined and a couple actions in place for handling a receive, what’s left is to handle the registering and unregistering of the receiver. It’s possible to register your broadcast receiver in the Android manifest for the activity; you can find an example of doing this on the Google’s official documentation site. I prefer to register my broadcast receivers in code, largely because it gives me the ability to dynamically connect and disconnect them as I choose.
Main.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onResume() {
this.registerReceiver(the_receiver, filter);
super.onResume();
}
@Override
protected void onPause() {
this.unregisterReceiver(the_receiver);
super.onPause();
}
That does it. Load the code to your device or Emulator and then rotate your phone (Ctrl F12 on the emulator). When the broadcast is received, the receiver displays an appropriate toast message (Figure A).
Figure A
See, it’s Android’s version of a party line. I find broadcast receivers simple and extremely useful. Just remember to “hang up” when you are done listening using the unregister receiver call; otherwise, Google might send someone over to chat with your mother!