/* * NFCReaderTargetDetector.java * * Copyright � 1998-2011 Research In Motion Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Note: For the sake of simplicity, this sample application may not leverage * resource bundles and resource strings. However, it is STRONGLY recommended * that application developers make use of the localization features available * within the BlackBerry development platform to ensure a seamless application * experience across a variety of languages and geographies. For more information * on localizing your application, please refer to the BlackBerry Java Development * Environment Development Guide associated with this release. */ package com.rim.samples.device.nfcreaderdemo; import java.io.IOException; import javax.microedition.io.Connection; import javax.microedition.io.Connector; import net.rim.device.api.io.nfc.NFCException; import net.rim.device.api.io.nfc.NFCManager; import net.rim.device.api.io.nfc.ndef.NDEFMessage; import net.rim.device.api.io.nfc.ndef.NDEFRecord; import net.rim.device.api.io.nfc.ndef.NDEFTagConnection; import net.rim.device.api.io.nfc.readerwriter.DetectionListener; import net.rim.device.api.io.nfc.readerwriter.ISO14443Part3Connection; import net.rim.device.api.io.nfc.readerwriter.ISO14443Part4Connection; import net.rim.device.api.io.nfc.readerwriter.Target; import net.rim.device.api.ui.component.LabelField; /** * A DetectionListener class that listens for a target to come into the device's * NFC field. */ public class NFCReaderTargetDetector implements DetectionListener { private final NFCReaderScreen _screen; private final NFCManager _manager; /** * Creates a new NFCReaderTargetDetector object * * @param screen * The application's main screen * @param nfcManager * NFCManager instance */ public NFCReaderTargetDetector(final NFCReaderScreen screen, final NFCManager nfcManager) throws NFCException { if (screen == null) { throw new IllegalArgumentException("screen == null"); } _screen = screen; if (nfcManager == null) { throw new IllegalArgumentException("_manager == null"); } _manager = nfcManager; } /** * @see net.rim.device.api.io.nfc.readerwriter.DetectionListener#onTargetDetected(Target) */ public void onTargetDetected(final Target target) { String uri = null; // Try to determine out what type of target was detected // and read it if possible. if (target.isType(Target.NDEF_TAG)) // NDEF Target { _screen.addTargetInfo("Target Type: NDEF Tag"); uri = target.getUri(Target.NDEF_TAG); readNDEF(uri); } else if (target.isType(Target.ISO_14443_4)) // ISO 14443 4 target { _screen.deleteFields(); _screen.addTargetInfo("Target Type: ISO 14443 Part 4"); uri = target.getUri(Target.ISO_14443_4); readISO14443Target(uri, target); } else if (target.isType(Target.ISO_14443_3)) // ISO 14443 3 target { _screen.deleteFields(); _screen.addTargetInfo("Target Type: ISO 14443 Part 3"); uri = target.getUri(Target.ISO_14443_3); readISO14443Part3(uri, target); } else // Unknown type of target was found { _screen.addTargetInfo("Unknown target type found... " + target.getProperty("Type")); } } /** * Reads the contents of a detected ISO 14443 3 target * * @param uri * The detected ISO 14443 3's URI * @param target * The ISO 14443 3 target that has been detected */ public void readISO14443Part3(final String uri, final Target target) { _screen.addTargetInfo("URI: " + uri); ISO14443Part3Connection c = null; // Try to open a connection to the tag and send it a command try { c = (ISO14443Part3Connection) Connector.open(uri); // Get some metadata about the tag so we can determine // what command set to use on it. _screen.addTargetInfo("Name: " + target.getProperty("Name")); // Note: For the sake of this demo, we are hardcoding the request // that we will send the tag as the "Capability Container Select" // command. // Capability Container select command final byte[] response = c.transceive(new byte[] { (byte) 0x00, (byte) 0xA4, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0xE1, (byte) 0x03 }); // Parse the response bytes to see if the // command was a success or not. parseISO14443Part3Response(response); // Play sound once the read operation is complete _manager.playNFCOperationSuccessSound(); } catch (final IOException e) { _manager.playNFCOperationFailureSound(); _screen.add(new LabelField("Error: " + e.toString())); } finally { closeConnection(c); } } /** * Parses the response bytes from a ISO 14443 3 target and displays them on * the screen. * * @param response * Response to ISO14443Part3Connection.transceive() */ public void parseISO14443Part3Response(final byte[] response) { // Note: You need to determine what type of tag you are dealing with // and what the command set for that tag type is. Once you know that // information you can parse the response appropriately. // Response that we are looking for final byte[] ccSelectResponse = new byte[] { (byte) 0x09, (byte) 0x00 }; // Make sure that the response is the same length as the response we are // looking for if (ccSelectResponse.length == response.length) { // If the first byte in the response is not 0x09, it is not the // response we want if (response[0] != (byte) 0x09) { _screen.addResponseStatus("Not capability container select command was not successful..."); } // Otherwise it was 0x09, and if the 2nd byte is 0x00, it is the // response we are looking for else if (response[1] == (byte) 0x00) { _screen.addResponseStatus("The capability container select command was successful!"); } } } /** * Reads an ISO 14443 4 target * * @param uri * Detected ISO 14443 4 target's URI * @param target * The detected ISO 14443 4 tag */ public void readISO14443Target(final String uri, final Target target) { _screen.addTargetInfo("URI: " + uri); ISO14443Part4Connection c = null; // Try to open a connection to the tag and send it a command try { c = (ISO14443Part4Connection) Connector.open(uri); // Get some metadata about the tag to determine what type // of tag it is and what command set to use on it. _screen.addTargetInfo("Name: " + target.getProperty("Name")); // Note: not a real command. Command bytes need // to be determined based on type of tag detected. // Note: For the sake of this demo, we are hardcoding the request // that we will send the tag as the "Capability Container Select" // command. // Capability Container select command final byte[] response = c.transceive(new byte[] { (byte) 0x00, (byte) 0xA4, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0xE1, (byte) 0x03 }); parseISO14443Response(response); // Play sound once the read operation is complete _manager.playNFCOperationSuccessSound(); } catch (final IOException e) { _manager.playNFCOperationFailureSound(); _screen.add(new LabelField("Error: " + e.toString())); } finally { closeConnection(c); } } /** * Parses the response bytes from an ISO 14443 4 tag and displays them on * the screen. * * @param response * Response to ISO1443_4Connection.send() */ public void parseISO14443Response(final byte[] response) { // Note: Need to determine what type of tag you are dealing with // and what the command set for that tag type is. Once you know // that information you can parse the response appropriately. // Response that we are looking for final byte[] ccSelectResponse = new byte[] { (byte) 0x09, (byte) 0x00 }; // Make sure that the response is the same length as the response we are // looking for if (ccSelectResponse.length == response.length) { // If the first byte in the response is not 0x09, it is not the // response we want if (response[0] != (byte) 0x09) { _screen.addResponseStatus("Not capability container select command was not successful..."); } // Otherwise it was 0x09, and if the 2nd byte is 0x00, it is the // response we are looking for else if (response[1] == (byte) 0x00) { _screen.addResponseStatus("The capability container select command was successful!"); } } } /** * Read the detected NDEF target. Currently only handles NDEFRecords of type * "text/plain". * * @param uri * Detected NDEF target's URI */ public void readNDEF(final String uri) { _screen.addTargetInfo("URI: " + uri); NDEFTagConnection c = null; String payload; final StringBuffer sb = new StringBuffer(); // Try to open a connection to the NDEF tag and read its content try { c = (NDEFTagConnection) Connector.open(uri); final NDEFMessage ndefMessage = c.read(); final NDEFRecord[] ndefRecords = ndefMessage.getRecords(); // Go through all the NDEFRecords in the NDEFMessage for (int i = 0; i < ndefMessage.getNumberOfRecords(); i++) { final String type = ndefRecords[i].getType(); sb.append("Type for record "); sb.append((i + 1)); sb.append(" : "); sb.append(type); _screen.addResponseStatus(sb.toString()); sb.delete(0, sb.length()); if (!type.equals("text/plain")) // Unhandled type { _screen.addResponseStatus("Unhandled record type: " + type); } // Display the recordType and the String version of the payload payload = new String(ndefRecords[i].getPayload()); sb.append("\tPayload for "); sb.append((i + 1)); sb.append(" : "); sb.append(payload); _screen.addResponseStatus(sb.toString()); sb.delete(0, sb.length()); } // Play sound once the read operation is complete _manager.playNFCOperationSuccessSound(); } catch (final IOException e) { _manager.playNFCOperationFailureSound(); _screen.add(new LabelField("Error: " + e.toString())); } finally { closeConnection(c); } } /** * Closes the connection * * @param conn * The connection object to be closed */ public void closeConnection(final Connection conn) { try { if (conn != null) { conn.close(); } } catch (final IOException e) { _manager.playNFCOperationFailureSound(); _screen.add(new LabelField("Error: " + e.toString())); } } }