Your message has been sent.
This article has been saved to your account.
Go to my account
This article has been emailed to your Kindle.
Send this article
Complete the form below to send this article, New Connectivity APIs – Android Beam, to a friend (or to yourself). We will never share your details (or your friend's) with anyone. For more information, read our Privacy Policy.
In this article by Murat Aydin, the author of Android 4: New features for Application Development, introduces us to new connectivity APIs with Android Ice Cream Sandwich—Android Beam, which uses the NFC hardware of the device. Android Beam allows devices to connect to each other without using a wireless access point. This article will teach us the usage of Android Beam.
The topics covered in this chapter are as follows:
-
Android Beam
-
Beaming NdefMessages
(For more resources related to this topic, see here.)
Android Beam
Devices that have NFC hardware can share data by tapping them together. This could be done with the help of the Android Beam feature. It is similar to Bluetooth, as we get seamless discovery and pairing as in a Bluetooth connection. Devices connect when they are close to each other (not more than a few centimeters). Users can share pictures, videos, contacts, and so on, using the Android Beam feature.
Beaming NdefMessages
In this section, we are going to implement a simple Android Beam application. This application will send an image to another device when two devices are tapped together. There are three methods that are introduced with Android Ice Cream Sandwich that are used in sending NdefMessages. These methods are as follows:
-
setNdefPushMessage() : This method takes an NdefMessage as a parameter and sends it to another device automatically when devices are tapped together. This is commonly used when the message is static and doesn't change.
-
setNdefPushMessageCallback() : This method is used for creating dynamic NdefMessages. When two devices are tapped together, the createNdefMessage() method is called.
-
setOnNdefPushCompleteCallback() : This method sets a callback which is called when the Android Beam is successful.
We are going to use the second method in our sample application.
Our sample application's user interface will contain a TextView component for displaying text messages and an ImageView component for displaying the received images sent from another device. The layout XML code will be as follows:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/ android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="" /> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/textView" android:layout_centerHorizontal="true" android:layout_marginTop="14dp" /> </RelativeLayout>
Now, we are going to implement, step-by-step, the Activity class of the sample application. The code of the Activity class with the onCreate() method is as follows:
public class Chapter9Activity extends Activity implements
CreateNdefMessageCallback
{
NfcAdapter mNfcAdapter;
TextView mInfoText;
ImageView imageView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imageView = (ImageView) findViewById(R.id.imageView);
mInfoText = (TextView) findViewById(R.id.textView);
// Check for available NFC Adapter
mNfcAdapter =
NfcAdapter.getDefaultAdapter(getApplicationContext());
if (mNfcAdapter == null)
{
mInfoText = (TextView) findViewById(R.id.textView);
mInfoText.setText("NFC is not available on this device.");
finish();
return;
}
// Register callback to set NDEF message
mNfcAdapter.setNdefPushMessageCallback(this, this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
As you can see in this code, we can check whether the device provides an NfcAdapter. If it does, we get an instance of NfcAdapter. Then, we call the setNdefPushMessageCallback() method to set the callback using the NfcAdapter instance. We send the Activity class as a callback parameter because the Activity class implements CreateNdefMessageCallback.In order to implement CreateNdefMessageCallback, we should override the createNdefMessage()method as shown in the following code block:
@Override
public NdefMessage createNdefMessage(NfcEvent arg0) {
Bitmap icon =
BitmapFactory.decodeResource(this.getResources(),
R.drawable.ic_launcher);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
icon.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
NdefMessage msg = new NdefMessage(new NdefRecord[] {
createMimeRecord("application/com.chapter9", byteArray)
, NdefRecord.createApplicationRecord("com.chapter9")
});
return msg;
}
public NdefRecord createMimeRecord(String mimeType, byte[]
payload) {
byte[] mimeBytes = mimeType.getBytes(Charset.forName("USASCII"));
NdefRecord mimeRecord = new
NdefRecord(NdefRecord.TNF_MIME_MEDIA,
mimeBytes, new byte[0], payload);
return mimeRecord;
}
As you can see in this code, we get a drawable, convert it to bitmap, and then to a byte array. Then we create an NdefMessage with two NdefRecords. The first record contains the mime type and the byte array. The first record is created by the createMimeRecord() method. The second record contains the Android Application Record ( AAR). The Android Application Record was introduced with Android Ice Cream Sandwich. This record contains the package name of the application and increases the certainty that your application will start when an NFC Tag is scanned. That is, the system firstly tries to match the intent filter and AAR together to start the activity. If they don't match, the activity that matches the AAR is started.
When the activity is started by an Android Beam event, we need to handle the message that is sent by the Android Beam. We handle this message in the onResume() method of the Activity class as shown in the following code block:
@Override
public void onResume() {
super.onResume();
// Check to see that the Activity started due to an Android
Beam
if (NfcAdapter.ACTION_NDEF_DISCOVERED.
equals(getIntent().getAction())) {
processIntent(getIntent());
}
}
@Override
public void onNewIntent(Intent intent) {
// onResume gets called after this to handle the intent
setIntent(intent);
}
void processIntent(Intent intent) {
Parcelable[] rawMsgs = intent
.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
// only one message sent during the beam
NdefMessage msg = (NdefMessage) rawMsgs[0];
// record 0 contains the MIME type, record 1 is the AAR
byte[] bytes = msg.getRecords()[0].getPayload();
Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0,
bytes.length);
imageView.setImageBitmap(bmp);
}
As you can see in this code, we firstly check whether the intent is ACTION_NDEF_DISCOVERED. This means the Activity class is started due to an Android Beam. If it is started due to an Android Beam, we process the intent with the processIntent() method. We firstly get NdefMessage from the intent. Then we get the first record and convert the byte array in the first record to bitmap using BitmapFactory . Remember that the second record is AAR, we do nothing with it. Finally, we set the bitmap of the ImageView component.
The AndroidManifest.xml file of the application should be as follows:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.chapter9"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.NFC"/>
<uses-feature android:name="android.hardware.nfc"
android:required="false" />
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".Chapter9Activity"
android:label="@string/title_activity_chapter9" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action
android:name="android.nfc.action.NDEF_DISCOVERED" />
<category
android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/com.chapter9" />
</intent-filter>
</activity>
</application>
</manifest>
As you can see in this code, we need to set the minimum SDK to API Level 14 or more in the AndroidManifest.xml file because these APIs are available in API Level 14 or more. Furthermore, we need to set the permissions to use NFC. We also set the uses feature in AndroidManifest.xml. The feature is set as not required. This means that our application would be available for devices that don't have NFC support. Finally, we create an intent filter for android.nfc.action.NDEF_DISCOVERED with mimeType of application/com.chapter9.
When a device sends an image using our sample application, the screen will be as follows:

Summary
In this article, we firstly learned the Android Beam feature of Android. With this feature, devices can send data using the NFC hardware. We implemented a sample Android Beam application and learned how to use Android Beam APIs.
Resources for Article :
Further resources on this subject:
- Android 3.0 Application Development: Multimedia Management [Article]
- Animating Properties and Tweening Pages in Android 3-0 [Article]
- Android User Interface Development: Animating Widgets and Layouts [Article]
About the Author :
Murat Aydin
Murat Aydin is a senior software engineer in a company that develops software technologies for defense systems, and is an enthusiastic Android developer. He has several Android applications in Google Play. He is a Sun Certified Java Developer and has eight years of experience in developing web based applications using Java technologies, and desktop and engineering applications using .Net technologies.
Murat Aydin earned his BSc degree in Computer Engineering from METU (Middle East Technical University) and his MSc degree in Software Engineering from METU.
He is a member of GDG Ankara (Google Developer Group Ankara, www.gdgankara.org), who organize several Android events in GDG Ankara, such as Android Developer Days. (www.androiddeveloperdays.com).
He is married and lives in Ankara with his wife Ülkü.
Linkedin: http://www.linkedin.com/pub/murat-ayd%C4%B1n/33/702/6a2
Twitter: @maydintr



Post new comment