1590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/* 2590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Copyright (C) 2010 The Android Open Source Project 3590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * 4590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 5590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * you may not use this file except in compliance with the License. 6590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * You may obtain a copy of the License at 7590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * 8590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * http://www.apache.org/licenses/LICENSE-2.0 9590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * 10590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Unless required by applicable law or agreed to in writing, software 11590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 12590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * See the License for the specific language governing permissions and 14590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * limitations under the License. 15590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 16590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 174e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamiltonpackage android.nfc.tech; 18590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 196be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.ErrorCodes; 206be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.FormatException; 214e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamiltonimport android.nfc.INfcTag; 226be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.NdefMessage; 236be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.NfcAdapter; 246be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.Tag; 2574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pellyimport android.nfc.TagLostException; 266be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.os.Bundle; 27590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.os.RemoteException; 283dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pellyimport android.util.Log; 296be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton 306be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport java.io.IOException; 31590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 32590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/** 3374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Provides access to NDEF content and operations on a {@link Tag}. 346be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * 3574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Acquire a {@link Ndef} object using {@link #get}. 3674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 3774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>NDEF is an NFC Forum data format. The data formats are implemented in 3874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link android.nfc.NdefMessage} and 3974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link android.nfc.NdefRecord}. This class provides methods to 4074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * retrieve and modify the {@link android.nfc.NdefMessage} 4174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * on a tag. 4274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 4374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>There are currently four NFC Forum standardized tag types that can be 4474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * formatted to contain NDEF data. 4574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <ul> 4674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <li>NFC Forum Type 1 Tag ({@link #NFC_FORUM_TYPE_1}), such as the Innovision Topaz 4739cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * <li>NFC Forum Type 2 Tag ({@link #NFC_FORUM_TYPE_2}), such as the NXP MIFARE Ultralight 4874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <li>NFC Forum Type 3 Tag ({@link #NFC_FORUM_TYPE_3}), such as Sony Felica 4974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <li>NFC Forum Type 4 Tag ({@link #NFC_FORUM_TYPE_4}), such as NXP MIFARE Desfire 5074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * </ul> 5174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * It is mandatory for all Android devices with NFC to correctly enumerate 5274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link Ndef} on NFC Forum Tag Types 1-4, and implement all NDEF operations 5374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * as defined in this class. 5474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 5574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Some vendors have there own well defined specifications for storing NDEF data 5674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * on tags that do not fall into the above categories. Android devices with NFC 5774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * should enumerate and implement {@link Ndef} under these vendor specifications 5874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * where possible, but it is not mandatory. {@link #getType} returns a String 5974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * describing this specification, for example {@link #MIFARE_CLASSIC} is 6074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <code>com.nxp.ndef.mifareclassic</code>. 6174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 6274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Android devices that support MIFARE Classic must also correctly 6374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * implement {@link Ndef} on MIFARE Classic tags formatted to NDEF. 6474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 6574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>For guaranteed compatibility across all Android devices with NFC, it is 6674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * recommended to use NFC Forum Types 1-4 in new deployments of NFC tags 6774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * with NDEF payload. Vendor NDEF formats will not work on all Android devices. 686be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * 6939cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * <p class="note"><strong>Note:</strong> Methods that perform I/O operations 7039cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * require the {@link android.Manifest.permission#NFC} permission. 71590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 726be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonpublic final class Ndef extends BasicTagTechnology { 733dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly private static final String TAG = "NFC"; 743dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly 753300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen /** @hide */ 763300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen public static final int NDEF_MODE_READ_ONLY = 1; 773300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen /** @hide */ 783300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen public static final int NDEF_MODE_READ_WRITE = 2; 793300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen /** @hide */ 803300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen public static final int NDEF_MODE_UNKNOWN = 3; 81590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 8272df4ea8300ad345eb256cf43d8dae35eef39ba2Martijn Coenen /** @hide */ 8372df4ea8300ad345eb256cf43d8dae35eef39ba2Martijn Coenen public static final String EXTRA_NDEF_MSG = "ndefmsg"; 8472df4ea8300ad345eb256cf43d8dae35eef39ba2Martijn Coenen 856d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen /** @hide */ 866d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen public static final String EXTRA_NDEF_MAXLENGTH = "ndefmaxlength"; 876d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen 883300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen /** @hide */ 893300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen public static final String EXTRA_NDEF_CARDSTATE = "ndefcardstate"; 903300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen 91d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen /** @hide */ 92d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen public static final String EXTRA_NDEF_TYPE = "ndeftype"; 93d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen 94f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly /** @hide */ 95f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final int TYPE_OTHER = -1; 96f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly /** @hide */ 97f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final int TYPE_1 = 1; 98f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly /** @hide */ 99f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final int TYPE_2 = 2; 100f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly /** @hide */ 101f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final int TYPE_3 = 3; 102f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly /** @hide */ 103f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final int TYPE_4 = 4; 104f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly /** @hide */ 105f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final int TYPE_MIFARE_CLASSIC = 101; 1065644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton /** @hide */ 1075644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton public static final int TYPE_ICODE_SLI = 102; 108f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly 109f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly /** @hide */ 110f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final String UNKNOWN = "android.ndef.unknown"; 111f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly 11274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly /** NFC Forum Tag Type 1 */ 113f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final String NFC_FORUM_TYPE_1 = "org.nfcforum.ndef.type1"; 11474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly /** NFC Forum Tag Type 2 */ 115f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final String NFC_FORUM_TYPE_2 = "org.nfcforum.ndef.type2"; 11674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly /** NFC Forum Tag Type 4 */ 117f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final String NFC_FORUM_TYPE_3 = "org.nfcforum.ndef.type3"; 11874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly /** NFC Forum Tag Type 4 */ 119f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final String NFC_FORUM_TYPE_4 = "org.nfcforum.ndef.type4"; 12074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly /** NDEF on MIFARE Classic */ 121f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public static final String MIFARE_CLASSIC = "com.nxp.ndef.mifareclassic"; 1225644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton /** 1235644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton * NDEF on iCODE SLI 1245644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton * @hide 1255644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton */ 1265644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton public static final String ICODE_SLI = "com.nxp.ndef.icodesli"; 127d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen 1283300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen private final int mMaxNdefSize; 1293300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen private final int mCardState; 130e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen private final NdefMessage mNdefMsg; 131d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen private final int mNdefType; 1326d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen 133590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /** 13474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Get an instance of {@link Ndef} for the given tag. 13574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 13674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Returns null if {@link Ndef} was not enumerated in {@link Tag#getTechList}. 13774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * This indicates the tag is not NDEF formatted, or that this tag 13874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * is NDEF formatted but under a vendor specification that this Android 13974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * device does not implement. 1404e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton * 14174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Does not cause any RF activity and does not block. 14274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 1430bec15ebed8b8639076cba184af3235e17f48718Martijn Coenen * @param tag an NDEF compatible tag 1440bec15ebed8b8639076cba184af3235e17f48718Martijn Coenen * @return Ndef object 1454e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton */ 1464e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton public static Ndef get(Tag tag) { 1474e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton if (!tag.hasTech(TagTechnology.NDEF)) return null; 1484e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton try { 1494e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton return new Ndef(tag); 1504e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton } catch (RemoteException e) { 1514e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton return null; 1524e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton } 1534e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton } 1544e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton 1554e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton /** 156590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Internal constructor, to be used by NfcAdapter 157590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * @hide 158590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 1594e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton public Ndef(Tag tag) throws RemoteException { 1604e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton super(tag, TagTechnology.NDEF); 1614e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton Bundle extras = tag.getTechExtras(TagTechnology.NDEF); 1626d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen if (extras != null) { 1633300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen mMaxNdefSize = extras.getInt(EXTRA_NDEF_MAXLENGTH); 1643300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen mCardState = extras.getInt(EXTRA_NDEF_CARDSTATE); 165e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen mNdefMsg = extras.getParcelable(EXTRA_NDEF_MSG); 166d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen mNdefType = extras.getInt(EXTRA_NDEF_TYPE); 1676d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen } else { 1683300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen throw new NullPointerException("NDEF tech extras are null."); 1696d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen } 1703300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen 1716be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton } 172a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau 1736be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton /** 17474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Get the {@link NdefMessage} that was read from the tag at discovery time. 17574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 17674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>If the NDEF Message is modified by an I/O operation then it 17774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * will not be updated here, this function only returns what was discovered 17874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * when the tag entered the field. 179a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen * <p>Note that this method may return null if the tag was in the 180a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen * INITIALIZED state as defined by NFC Forum, as in this state the 181a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen * tag is formatted to support NDEF but does not contain a message yet. 18274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Does not cause any RF activity and does not block. 183a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen * @return NDEF Message read from the tag at discovery time, can be null 1846be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton */ 185e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen public NdefMessage getCachedNdefMessage() { 186e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen return mNdefMsg; 187a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau } 188a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau 189a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau /** 19074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Get the NDEF tag type. 19174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 192ddbb2c997b8462d7242b50ea1689a53122d4fce4Nick Pelly * <p>Returns one of {@link #NFC_FORUM_TYPE_1}, {@link #NFC_FORUM_TYPE_2}, 193ddbb2c997b8462d7242b50ea1689a53122d4fce4Nick Pelly * {@link #NFC_FORUM_TYPE_3}, {@link #NFC_FORUM_TYPE_4}, 19474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link #MIFARE_CLASSIC} or another NDEF tag type that has not yet been 19574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * formalized in this Android API. 19674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 19774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Does not cause any RF activity and does not block. 19874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 19974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @return a string representing the NDEF tag type 200d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen */ 201f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public String getType() { 202f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly switch (mNdefType) { 203f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly case TYPE_1: 204f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly return NFC_FORUM_TYPE_1; 205f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly case TYPE_2: 206f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly return NFC_FORUM_TYPE_2; 207f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly case TYPE_3: 208f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly return NFC_FORUM_TYPE_3; 209f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly case TYPE_4: 210f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly return NFC_FORUM_TYPE_4; 211f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly case TYPE_MIFARE_CLASSIC: 212f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly return MIFARE_CLASSIC; 2135644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton case TYPE_ICODE_SLI: 2145644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton return ICODE_SLI; 215f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly default: 216f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly return UNKNOWN; 217f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly } 218d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen } 219d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen 220d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen /** 22174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Get the maximum NDEF message size in bytes. 22274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 22374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Does not cause any RF activity and does not block. 22474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 22574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @return size in bytes 2266be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton */ 2273300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen public int getMaxSize() { 2283300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen return mMaxNdefSize; 2296be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton } 2306be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton 2316be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton /** 23274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Determine if the tag is writable. 23374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 23474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>NFC Forum tags can be in read-only or read-write states. 23574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 23674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Does not cause any RF activity and does not block. 23774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 238e47150e933e6f610546f57183477f324566e521eNick Pelly * <p>Requires {@link android.Manifest.permission#NFC} permission. 23974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 24074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @return true if the tag is writable 241590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 2423300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen public boolean isWritable() { 2433300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen return (mCardState == NDEF_MODE_READ_WRITE); 244590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 245590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 246590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /** 24774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Read the current {@link android.nfc.NdefMessage} on this tag. 24874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 24974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>This always reads the current NDEF Message stored on the tag. 25074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 251a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen * <p>Note that this method may return null if the tag was in the 252a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen * INITIALIZED state as defined by NFC Forum, as in that state the 253a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen * tag is formatted to support NDEF but does not contain a message yet. 254a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen * 25574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>This is an I/O operation and will block until complete. It must 25674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * not be called from the main application thread. A blocked call will be canceled with 25774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link IOException} if {@link #close} is called from another thread. 25874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 2596c65344fcf5aa1499dafe1cad1d1ba5c66293776Martijn Coenen * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 2606c65344fcf5aa1499dafe1cad1d1ba5c66293776Martijn Coenen * 261a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen * @return the NDEF Message, can be null 26274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @throws TagLostException if the tag leaves the field 26374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @throws IOException if there is an I/O failure, or the operation is canceled 26474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @throws FormatException if the NDEF Message on the tag is malformed 265e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen */ 266e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen public NdefMessage getNdefMessage() throws IOException, FormatException { 2674049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen checkConnected(); 2684049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen 269e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen try { 2704e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton INfcTag tagService = mTag.getTagService(); 27123fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen if (tagService == null) { 27223fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen throw new IOException("Mock tags don't support this operation."); 27323fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen } 274e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen int serviceHandle = mTag.getServiceHandle(); 2754e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton if (tagService.isNdef(serviceHandle)) { 2764e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton NdefMessage msg = tagService.ndefRead(serviceHandle); 277a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen if (msg == null && !tagService.isPresent(serviceHandle)) { 278a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen throw new TagLostException(); 279e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen } 280e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen return msg; 281e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen } else { 282e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen return null; 283e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen } 284e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen } catch (RemoteException e) { 2853dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly Log.e(TAG, "NFC service dead", e); 286e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen return null; 287e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen } 288e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen } 2893ce86481cbde92e2cb6fe3a46cbedd8b2a5c4b48Jeff Hamilton 290e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen /** 29174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Overwrite the {@link NdefMessage} on this tag. 29274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 29374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>This is an I/O operation and will block until complete. It must 29474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * not be called from the main application thread. A blocked call will be canceled with 29574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link IOException} if {@link #close} is called from another thread. 29674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 29739cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 29839cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * 29974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @param msg the NDEF Message to write, must not be null 30074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @throws TagLostException if the tag leaves the field 30174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @throws IOException if there is an I/O failure, or the operation is canceled 30274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @throws FormatException if the NDEF Message to write is malformed 303590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 3046be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException { 3054049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen checkConnected(); 3064049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen 307590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly try { 3084e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton INfcTag tagService = mTag.getTagService(); 30923fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen if (tagService == null) { 31023fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen throw new IOException("Mock tags don't support this operation."); 31123fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen } 31201d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen int serviceHandle = mTag.getServiceHandle(); 3134e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton if (tagService.isNdef(serviceHandle)) { 3144e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton int errorCode = tagService.ndefWrite(serviceHandle, msg); 31501d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen switch (errorCode) { 31601d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen case ErrorCodes.SUCCESS: 31701d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen break; 31801d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen case ErrorCodes.ERROR_IO: 31901d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen throw new IOException(); 32001d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen case ErrorCodes.ERROR_INVALID_PARAM: 32101d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen throw new FormatException(); 32201d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen default: 32301d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen // Should not happen 32401d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen throw new IOException(); 32501d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen } 32601d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen } 32701d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen else { 32801d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen throw new IOException("Tag is not ndef"); 329590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 330590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } catch (RemoteException e) { 3313dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly Log.e(TAG, "NFC service dead", e); 332590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 333590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 334590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 335590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /** 33674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Indicates whether a tag can be made read-only with {@link #makeReadOnly()}. 33774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 33874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Does not cause any RF activity and does not block. 33974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 34074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @return true if it is possible to make this tag read-only 34125be53652167300183282d170a00a6df576523f5Martijn Coenen */ 342f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public boolean canMakeReadOnly() { 343faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen INfcTag tagService = mTag.getTagService(); 34423fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen if (tagService == null) { 34523fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen return false; 34623fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen } 347faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen try { 348faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen return tagService.canMakeReadOnly(mNdefType); 349faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen } catch (RemoteException e) { 350faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen Log.e(TAG, "NFC service dead", e); 35125be53652167300183282d170a00a6df576523f5Martijn Coenen return false; 35225be53652167300183282d170a00a6df576523f5Martijn Coenen } 35325be53652167300183282d170a00a6df576523f5Martijn Coenen } 35425be53652167300183282d170a00a6df576523f5Martijn Coenen 35525be53652167300183282d170a00a6df576523f5Martijn Coenen /** 35674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Make a tag read-only. 35774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 35874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>This sets the CC field to indicate the tag is read-only, 35974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * and where possible permanently sets the lock bits to prevent 36074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * any further modification of the memory. 36174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>This is a one-way process and cannot be reverted! 36274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 36374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>This is an I/O operation and will block until complete. It must 36474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * not be called from the main application thread. A blocked call will be canceled with 36574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link IOException} if {@link #close} is called from another thread. 36674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 36739cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 36839cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * 36974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @return true on success, false if it is not possible to make this tag read-only 37074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @throws TagLostException if the tag leaves the field 37174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @throws IOException if there is an I/O failure, or the operation is canceled 372590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 373f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly public boolean makeReadOnly() throws IOException { 3744049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen checkConnected(); 3754049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen 376590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly try { 3774e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton INfcTag tagService = mTag.getTagService(); 37823fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen if (tagService == null) { 37923fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen return false; 38023fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen } 3814e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton if (tagService.isNdef(mTag.getServiceHandle())) { 3824e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton int errorCode = tagService.ndefMakeReadOnly(mTag.getServiceHandle()); 38307e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen switch (errorCode) { 38407e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen case ErrorCodes.SUCCESS: 38507e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen return true; 38607e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen case ErrorCodes.ERROR_IO: 38707e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen throw new IOException(); 38807e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen case ErrorCodes.ERROR_INVALID_PARAM: 38907e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen return false; 39007e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen default: 39107e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen // Should not happen 39207e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen throw new IOException(); 39307e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen } 39407e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen } 39507e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen else { 39607e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen throw new IOException("Tag is not ndef"); 39707e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen } 398590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } catch (RemoteException e) { 3993dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly Log.e(TAG, "NFC service dead", e); 400590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return false; 401590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 402590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 4036be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton} 404