Quantcast
Channel: Envato Tuts+ Code - Mobile Development
Viewing all articles
Browse latest Browse all 1836

Sharing Files With NFC on Android

$
0
0

In this tutorial, you will learn the basics of P2P (peer-to-peer) communication and create an application to share large files, such as images and videos, from one device to another using NFC (near field communication) on Android.

1. Introduction

NFC or Near Field Communication is a set of short-range wireless technologies. It enables the exchange of data between an NFC tag and an NFC-enabled device, or between NFC-enabled devices within a distance of no more than 4 cm.

There are three modes of NFC operation:

  • Reading and writing contactless tags: These tags are generally very small and do not require any battery power. They can be embedded in all sorts of objects, such as movie posters, products, stickers, and so on.
  • Card emulation mode: Think smart credit cards. This allows an Android device to act like a smart card. The obvious benefit of this is that your device can act like one card and then act like a different one at the touch of a button. This is one way an Android device can replace your wallet. Whatever credit card, bus pass, or ticket you're using, your Android device could impersonate—securely, of course—that item. The reader on the other side of the transaction thinks that it's interacting with that item, when in fact, it's dealing with an Android device.
  • Peer-to-peer communication: Each side recognizes that it's talking to another device and not just a tag. The protocol has been developed by Google and allows two devices to send messages back and forth.

The peer-to-peer (P2P) data exchange feature was added to Android in API level 14 (Android 4.0, Ice Cream Sandwich) and is called Android Beam. It enables rapid short-range exchange of data between two NFC-enabled Android devices.

2. P2P Communication With Android Beam

The Android Beam data exchange feature has two APIs, the NDEF transfer API and the file transfer API.

NDEF Transfer API

This API was introduced in API level 14 (Android 4.0, Ice Cream Sandwich) and enables the transfer of small amounts of data like URLs, contacts, etc. The data to be transferred must be formatted in NDEF (NFC Data Exchange Format) and is sent as an NDEF message.

File Transfer API

The file transfer API was introduced in API level 16 (Android 4.1, Jelly Bean) and enables the transfer of large files, such as images, videos, etc.

There are some caveats though. Android Beam only works when the application sending the data is running in the foreground and the device receiving the data is unlocked.

The Android Beam file transfer API has two additional requirements:

  • The files that need to be transferred must be located in external storage.
  • The files that need to be transferred must be world-readable.

In this tutorial, we will use the Android Beam file transfer API of the Android SDK to create an application that enables users to share files between devices.

3. Requirements

Due to the limitations of the emulator, the application needs to be tested with two physical NFC-enabled Android devices running Android 4.1 or higher.

4. Getting Started

Using Eclipse, create a new Android application project and name it NFCDemo

Project Settings

Since Android Beam file transfer is only available on devices running Android 4.1+, we need to set Minimum Required SDK to API 16: Android 4.1 (Jelly Bean).

5. Configuring Manifest File

To use NFC in an Android app, we have to declare the NFC permission in the manifest file as shown below.

<uses-permission 
    android:name="android.permission.NFC" />

In addition, to read files from external storage, declare the READ_EXTERNAL_STORAGE permission as shown below.

<uses-permission 
    android:name="android.permission.READ_EXTERNAL_STORAGE" /> 

Not every Android device supports NFC. To make sure that our app only shows up in Google Play for those devices that support NFC, add the <uses-feature> element to the manifest file.

<uses-feature 
    android:name="android.hardware.nfc" 
    android:required="true" />

If NFC is an optional feature of your app, then you can omit the <uses-feature> element from the manifest file and set the minimum SDK version to a lower API level. In that case, you need to check if the device supports NFC and the Android Beam API, and update the user interface accordingly.

6. Creating Layouts

Open the activity_main.xml layout file and add a Button as shown below. As you can see, we've added a Button that the user can tap to initiate the transfer of a file.

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp" ><Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"
        android:text="Send File"
        android:onClick="sendFile" /></RelativeLayout>

7. Implementing File Transfer

Open the MainActivity class and replace the current implementation with the one shown below. Don't worry about the implementation for now. I'll explain every step in a moment.

package com.tutsplus.nfcdemo;

import java.io.File;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.nfc.NfcAdapter;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {
    
	private NfcAdapter nfcAdapter;	

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		PackageManager pm = this.getPackageManager();
		// Check whether NFC is available on device		
        if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
        	// NFC is not available on the device.
            Toast.makeText(this, "The device does not has NFC hardware.", 
            				Toast.LENGTH_SHORT).show();           
        } 
        // Check whether device is running Android 4.1 or higher 
        else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            // Android Beam feature is not supported.            
        	Toast.makeText(this, "Android Beam is not supported.", 
        					Toast.LENGTH_SHORT).show();                     
        }         
        else {
        	// NFC and Android Beam file transfer is supported.        	
        	Toast.makeText(this, "Android Beam is supported on your device.", 
        					Toast.LENGTH_SHORT).show();
        }
	}			
	public void sendFile(View view) {
		nfcAdapter = NfcAdapter.getDefaultAdapter(this);  
		// Check whether NFC is enabled on device
        if(!nfcAdapter.isEnabled()){
        	// NFC is disabled, show the settings UI
        	// to enable NFC
        	Toast.makeText(this, "Please enable NFC.", 
                            Toast.LENGTH_SHORT).show(); 
        	startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));
        }        
        // Check whether Android Beam feature is enabled on device
        else if(!nfcAdapter.isNdefPushEnabled()) {
        	// Android Beam is disabled, show the settings UI
        	// to enable Android Beam 
        	Toast.makeText(this, "Please enable Android Beam.", 
        					Toast.LENGTH_SHORT).show();
        	startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS));
        }
        else {
        	// NFC and Android Beam both are enabled 
        	// File to be transferred    
        	// For the sake of this tutorial I've placed an image 
        	// named 'wallpaper.png' in the 'Pictures' directory
        	String fileName = "wallpaper.png";
        	// Retrieve the path to the user's public pictures directory 
        	File fileDirectory = Environment
                                    .getExternalStoragePublicDirectory(
                                            Environment.DIRECTORY_PICTURES);
        	// Create a new file using the specified directory and name
        	File fileToTransfer = new File(fileDirectory, fileName);
        	fileToTransfer.setReadable(true, false);
        	nfcAdapter.setBeamPushUris(
                            new Uri[]{Uri.fromFile(fileToTransfer)}, this);		        
        }               	
	}
}

8. Testing the App

Before we dive into the code, let's see what steps we need to take to transfer a file from one device to another.

Step 1

Connect one of the two Android devices to your development workstation via USB with USB debugging enabled. Let's refer to that device as the sender.

Step 2

Enable NFC and Android Beam on the sender. Press F11 to debug the application. This will install and launch NFCDemo on the sender.

Step 3

Enable NFC on the second device, the receiver.

Step 4

Tap the Send File button and position the devices close together to let NFC do its work. You should see a Touch to beam message appear on the sender. Tap the screen to initiate the transfer.

The Touch to beam UI as displayed on the Sender

Step 5

The receiver should show a notification in the status bar to indicate the progress of the file transfer.

Incoming beam notification as displayed on Receiver  

Step 6

If the file transfer is completed successfully, a Beam complete message is displayed to the user.

Beam complete notification as displayed on Receiver

9. Decoding the Code

Let's take a look at the code that makes all this possible.

Determine Device Capabilities

As mentioned earlier, if NFC is an optional feature of our app we should check for NFC and Android Beam support. This check can be performed anywhere in our app. In this example, I've put the code in the onCreate method of the MainActivity class.

Step 1

Obtain a reference to the PackageManager.

PackageManager pm = this.getPackageManager();

The PackageManager class holds information about all the packages installed on the device.

Step 2

Call the hasSystemFeature method on the PackageManager object to determine if the device has NFC support. This method returns trueif the desired feature is supported by the device.

if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
  // NFC is not available on the device.
}
else {
  // NFC is available on the device.
}

Step 3

If the device has NFC support, then we have to check the device's Android version. The Android version (API level) running on a device is available via  android.os.Build.VERSION.SDK_INT. If the version is greater than or equal to 16, Build.VERSION_CODES.JELLY_BEAN, then the device supports Android Beam file transfer.

if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
  // NFC is not available on the device.
}
// Check whether device is running Android 4.1 or higher 
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
    // Android Beam feature is not supported.            
}         
else {
  // NFC and Android Beam file transfer is supported.         
}

Initiate File Transfer

Once we have determined that the device has the required capabilities, we can initiate the file transfer using Android Beam.

Step 1

Obtain a reference to the NfcAdapter.

nfcAdapter = NfcAdapter.getDefaultAdapter(this); 

The job of the NfcAdapter is to manage the exchange of data between an NFC tag and a NFC-enabled device or between two NFC-enabled devices.

Step 2

The adapter can be enabled or disabled. To determine whether the adapter is enabled, call the isEnabled method on the NfcAdapter object.

// Check whether NFC is enabled on device
if (!nfcAdapter.isEnabled()) {
  // NFC is disabled, show the settings UI to enable NFC
}        
else {
  // NFC is enabled
}

This method returns true if NFC is enabled on the device. If NFC is disabled, we prompt the user to enable it and show the NFC settings user interface. 

startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));

Step 3

Similarly, the Android Beam feature can also be enabled or disabled. To check its state, call the isNdefPushEnabled method on the NfcAdapter object.

// Check whether NFC is enabled on device
if (!nfcAdapter.isEnabled()) {
  // NFC is disabled, show the settings UI to enable NFC
}        
// Check whether Android Beam feature is enabled on device
else if (!nfcAdapter.isNdefPushEnabled()) {
  // Android Beam is disabled, show the settings UI to enable Android Beam 
}
else {
  // NFC and Android Beam both are enabled 
}

If this method returns false, we prompt the user to enable it and show the Android Beam settings user interface.

startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS));
NFC Settings UI

If both NFC and Android Beam are enabled, we can proceed with the file transfer.

Step 4

Create a new File using the directory where the file is located on the device and the name of the file. To test the file transfer, I've added an image named wallpaper.png in the Pictures directory in the external storage.

// Create a new file using the specified directory and name
File fileToTransfer = new File(fileDirectory, fileName);

Step 5

Call the setBeamPushUris method on the NfcAdapter object and pass the URI of the file to be transferred.

nfcAdapter.setBeamPushUris(new Uri[]{Uri.fromFile(fileToTransfer)}, 
                            this);

The setBeamPushUris method accepts an array of Uri objects. If you want to send more than one file, you can pass multiple URIs to the adapter.

The URIs passed to the setBeamPushUris method are queued by the adapter and are transferred to the receiving device as soon as it comes in close proximity of the sending device.

Conclusion

In this tutorial, you learned about the basics of NFC on Android. You've also learned how to restrict access to an app by unsupported devices using the manifest file and determine device capabilities at runtime. To send files using NFC, we made use of the NfcAdapter class.

While I've tried to cover the basics of working with the Android Beam file transfer API to help you get started, there is still more explore. If you like to learn more, then I encourage you to visit the Android developer portal for more information.

2014-11-19T15:50:18.000Z2014-11-19T15:50:18.000ZAvinash Gupta

Viewing all articles
Browse latest Browse all 1836

Trending Articles