New Connectivity APIs – Android Beam

Exclusive offer: get 50% off this eBook here
Android 4: New Features for Application Development

Android 4: New Features for Application Development — Save 50%

Develop Android applications using the new features of Android Ice Cream Sandwich with this book and ebook.

$14.99    $7.50
by Murat Aydin | January 2013 | Open Source

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 4: New Features for Application Development Develop Android applications using the new features of Android Ice Cream Sandwich with this book and ebook.
Published: December 2012
eBook Price: $14.99
Book Price: $29.99
See more
Select your format and quantity:

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

Books From Packt


 Android NDK Beginner’s Guide
Android NDK Beginner’s Guide

 Android Application Testing Guide
Android Application Testing Guide

Android 3.0 Animations: Beginner’s Guide
Android 3.0 Animations: Beginner’s Guide

 Flash Development for Android Cookbook
Flash Development for Android Cookbook

Android Database Programming
Android Database Programming

 Android 3.0 Application Development Cookbook
Android 3.0 Application Development Cookbook

 Android Fragmentation Management How-to
Android Fragmentation Management How-to

 Android User Interface Development: Beginner's Guide
Android User Interface Development: Beginner's Guide


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
A
x
v
1
u
G
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software