Beaming messages with NFC

NFC stands for Near Field Communication and allows NFC-equipped owners to exchange data by contact (or near contact) of their phones. In Android, we can use NFC through Beam. Using Beam, users can exchange a small amount of data, such as web bookmarks, contact info, directions, YouTube videos links, and so on. NFC is more convenient than other wireless technologies, such as Bluetooth or Wi-Fi for quickly sending data as no pairing or authentication is required.

Tip

The minimum SDK version to use NFC is level 10.

Getting ready

Create a new Solution named Beam_Project. To test this recipe, you'll need to deploy your application on two different NFC-enabled phones, as the emulator doesn't support NFC. Also, we will need to add the NFC permission.

How to do it...

To complete this recipe, you need to perform the following steps:

  1. Import the NFC APIs by adding using Android.Nfc at the top of the MainActivity.cs file.
  2. Import text capacities by adding the System.Text element at the top of the MainActivity.cs file.
  3. In the MainActivity.cs file, implement the NfcAdapter.ICreateNdefMessageCallback and NfcAdapter.IOnNdefPushCompleteCallback interfaces, as shown in the following code:
    public class MainActivity : Activity, NfcAdapter.ICreateNdefMessageCallback, NfcAdapter.IOnNdefPushCompleteCallback
  4. Add a TextView element in the Main.axml file and create a reference to it in your OnCreate() method:
    TextView textView =  FindViewById<TextView> (Resource.Id.mytextView);
  5. Test if the device is NFC enabled by adding the following snippet in the OnCreate() method of your MainActivity class:
    NfcAdapter nfcAdapter = NfcAdapter.GetDefaultAdapter(this);
    if (nfcAdapter == null) {
      Console.WriteLine ("Not NFC enabled");
      textView.Text = "Not NFC";
    }
    else {
      textView.Text = "NFC OK";
      nfcAdapter.SetNdefPushMessageCallback (this, this);
      nfcAdapter.SetOnNdefPushCompleteCallback (this, this);
    }
  6. Create a private constant named message_id and assign its value as 1:
    private const int message_id = 1; 
  7. Implement the OnNdefPushComplete() method defined by the NfcAdapter.IOnNdefPushCompleteCallback interface as follows:
    public void OnNdefPushComplete (NfcEvent myNfcEvent) {
      Handler myHandler = new Handler ();
      myHandler.ObtainMessage (message_id).SendToTarget ();
    }
  8. Implement the CreateNdefMessage() method defined by the NfcAdapter.ICreateNdefMessageCallback interface as follows:
    public NdefMessage CreateNdefMessage (NfcEvent myNfcEvent) {
      String myBeamText = ("MyAwesomeBeamMessage");
    
      byte [] mimeBytes = Encoding.UTF8.GetBytes ("application/com.example.android.beam");
    
      NdefRecord ndefRecord = new NdefRecord (
        NdefRecord.TnfMimeMedia, mimeBytes, new byte [0], Encoding.UTF8.GetBytes (myBeamText));
    
      NdefMessage myBeamMessage = new NdefMessage (new NdefRecord[]{ ndefRecord  });
    
      return myBeamMessage;
    }
  9. Create a displayMessage() method that takes an Intent object as an argument:
    protected void displayMessage (Intent intent) {
      IParcelable [] parcelMessage = intent.GetParcelableArrayExtra (NfcAdapter.ExtraNdefMessages);
    
      NdefMessage msg = (NdefMessage) parcelMessage [0];
    
      TextView textView =  FindViewById<TextView> (Resource.Id.mytextView);
    
      textView.Text = Encoding.UTF8.GetString (msg.GetRecords () [0].GetPayload ());
    }
  10. Override the OnResume() and OnNewIntent() methods as follows:
    protected override void OnResume () {
      base.OnResume ();
      if (NfcAdapter.ActionNdefDiscovered == Intent.Action) {
        displayMessage (Intent);
      }
    }
    
    protected override void OnNewIntent (Intent intent) {
      Intent = intent;
    }
  11. Deploy your application and two different phones, launch the application on those phones, and then put their NFC chips close to each other. You'll receive a New Tag Collected message that contains the name of your APK.

Tip

Ensure that both phones have their NFC sharing settings set to activate and that you have to request the NFC permission in your manifest.xml file. Finally, both screens must be unlocked.

How it works...

Android Beam allows us to beam messages from one phone to another as long as they are close enough to each other (almost in contact) and own an NFC chip. The messages that can be sent via beam are NFC Data Exchange Format Message (NdefMessage), which are composed of one or more NdefRecords. This is a convenient way to encapsulate data in a binary format for NFC transfer. NdefRecords have the following four attributes:

  • Tnf: This is a type of data
  • Type: This is the type of application that should receive the message
  • Id: This is the ID of the message
  • Playload: This is the actual content

The name of the attributes can be confusing. The Tnf attribute defines what the type of data is. For example, we can use TnfMimeMedia or TnfAbsoluteUri, which are public constants of the NdefRecord class. The Type attribute refers to the application that should handle your message, such as application/com.example.android.beam.

To build our NdefRecords() method we used the following constructor:

public NdefRecord (short tnf, byte[] type, byte[] id, byte[] payload)

Also, we used the following code:

byte [] type = Encoding.UTF8.GetBytes ("application/com.example.android.beam");

NdefRecord mimeRecord = new NdefRecord (
  ndefRecord.TnfMimeMedia, type , new byte [0], Encoding.UTF8.GetBytes (myBeamText));

In this snippet, we first create an array of the byte representing "application/com.example.android.beam". This array will be used as the Type argument of the NdefRecords() method. Then, we call the constructor with NdefRecord.TnfMimeMedia as the Tnf argument, our newly created array of bytes named type, and MyAwesomeBeamMessage is also transformed into bytes by means of the Encoding helper.

We now have every piece required to construct our NdefMessage() method with the following:

NdefMessage myBeamMessage = new NdefMessage (new NdefRecord[]{ ndefRecord });

In order to receive beam messages, we created the displayMessage() method that takes an Intent as an argument:

protected void displayMessage (Intent intent) {
  IParcelable [] parcelMessage = intent.GetParcelableArrayExtra (NfcAdapter.ExtraNdefMessages);

  NdefMessage msg = (NdefMessage) parcelMessage [0];

  TextView textView =  FindViewById<TextView> (Resource.Id.mytextView);

  textView.Text = Encoding.UTF8.GetString (msg.GetRecords () [0].GetPayload ());
}

Then, the displayMessage() method is called by the OnResume() method if our application is resumed by an NFC call:

protected override void OnResume () {
  base.OnResume ();
  if (NfcAdapter.ActionNdefDiscovered == Intent.Action) {
    displayMessage (Intent);
  }
}

In the displayMessage() method, we first get an array of the parcelable object and cast the first one as NdefMessage. Indeed, this method will be called only in case of beam contact, and we can only send one beam message at a time. Therefore, we can safely execute (NdefMessage) parcelMessage [0]. Finally, we assign our textview text with the Payload argument of the first record of our message.

The activity we created is able to send and receive beam messages because it implements the related interface and will register itself as a beam application.

See also

You can also visit the following links:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.136.154.103