Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2010 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 17 | package android.nfc.tech; |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 18 | |
| 19 | import android.nfc.ErrorCodes; |
| 20 | import android.nfc.FormatException; |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 21 | import android.nfc.INfcTag; |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 22 | import android.nfc.NdefMessage; |
| 23 | import android.nfc.NfcAdapter; |
| 24 | import android.nfc.Tag; |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 25 | import android.nfc.TagLostException; |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 26 | import android.os.Bundle; |
| 27 | import android.os.RemoteException; |
Nick Pelly | 3dd6c45 | 2011-01-10 18:14:41 +1100 | [diff] [blame] | 28 | import android.util.Log; |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 29 | |
| 30 | import java.io.IOException; |
| 31 | |
| 32 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 33 | * Provides access to NDEF content and operations on a {@link Tag}. |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 34 | * |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 35 | * <p>Acquire a {@link Ndef} object using {@link #get}. |
| 36 | * |
| 37 | * <p>NDEF is an NFC Forum data format. The data formats are implemented in |
| 38 | * {@link android.nfc.NdefMessage} and |
| 39 | * {@link android.nfc.NdefRecord}. This class provides methods to |
| 40 | * retrieve and modify the {@link android.nfc.NdefMessage} |
| 41 | * on a tag. |
| 42 | * |
| 43 | * <p>There are currently four NFC Forum standardized tag types that can be |
| 44 | * formatted to contain NDEF data. |
| 45 | * <ul> |
| 46 | * <li>NFC Forum Type 1 Tag ({@link #NFC_FORUM_TYPE_1}), such as the Innovision Topaz |
Nick Pelly | 39cf3a4 | 2011-02-07 17:04:21 +0900 | [diff] [blame] | 47 | * <li>NFC Forum Type 2 Tag ({@link #NFC_FORUM_TYPE_2}), such as the NXP MIFARE Ultralight |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 48 | * <li>NFC Forum Type 3 Tag ({@link #NFC_FORUM_TYPE_3}), such as Sony Felica |
| 49 | * <li>NFC Forum Type 4 Tag ({@link #NFC_FORUM_TYPE_4}), such as NXP MIFARE Desfire |
| 50 | * </ul> |
| 51 | * It is mandatory for all Android devices with NFC to correctly enumerate |
| 52 | * {@link Ndef} on NFC Forum Tag Types 1-4, and implement all NDEF operations |
| 53 | * as defined in this class. |
| 54 | * |
| 55 | * <p>Some vendors have there own well defined specifications for storing NDEF data |
| 56 | * on tags that do not fall into the above categories. Android devices with NFC |
| 57 | * should enumerate and implement {@link Ndef} under these vendor specifications |
| 58 | * where possible, but it is not mandatory. {@link #getType} returns a String |
| 59 | * describing this specification, for example {@link #MIFARE_CLASSIC} is |
| 60 | * <code>com.nxp.ndef.mifareclassic</code>. |
| 61 | * |
| 62 | * <p>Android devices that support MIFARE Classic must also correctly |
| 63 | * implement {@link Ndef} on MIFARE Classic tags formatted to NDEF. |
| 64 | * |
| 65 | * <p>For guaranteed compatibility across all Android devices with NFC, it is |
| 66 | * recommended to use NFC Forum Types 1-4 in new deployments of NFC tags |
| 67 | * with NDEF payload. Vendor NDEF formats will not work on all Android devices. |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 68 | * |
Nick Pelly | 39cf3a4 | 2011-02-07 17:04:21 +0900 | [diff] [blame] | 69 | * <p class="note"><strong>Note:</strong> Methods that perform I/O operations |
| 70 | * require the {@link android.Manifest.permission#NFC} permission. |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 71 | */ |
| 72 | public final class Ndef extends BasicTagTechnology { |
Nick Pelly | 3dd6c45 | 2011-01-10 18:14:41 +1100 | [diff] [blame] | 73 | private static final String TAG = "NFC"; |
| 74 | |
Martijn Coenen | 3300e4c | 2010-12-08 23:23:47 -0800 | [diff] [blame] | 75 | /** @hide */ |
| 76 | public static final int NDEF_MODE_READ_ONLY = 1; |
| 77 | /** @hide */ |
| 78 | public static final int NDEF_MODE_READ_WRITE = 2; |
| 79 | /** @hide */ |
| 80 | public static final int NDEF_MODE_UNKNOWN = 3; |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 81 | |
Martijn Coenen | 72df4ea | 2010-12-06 21:05:17 -0800 | [diff] [blame] | 82 | /** @hide */ |
| 83 | public static final String EXTRA_NDEF_MSG = "ndefmsg"; |
| 84 | |
Martijn Coenen | 6d9fc7e | 2010-12-07 14:04:28 -0800 | [diff] [blame] | 85 | /** @hide */ |
| 86 | public static final String EXTRA_NDEF_MAXLENGTH = "ndefmaxlength"; |
| 87 | |
Martijn Coenen | 3300e4c | 2010-12-08 23:23:47 -0800 | [diff] [blame] | 88 | /** @hide */ |
| 89 | public static final String EXTRA_NDEF_CARDSTATE = "ndefcardstate"; |
| 90 | |
Martijn Coenen | d27ebf1 | 2010-12-22 13:51:51 +0100 | [diff] [blame] | 91 | /** @hide */ |
| 92 | public static final String EXTRA_NDEF_TYPE = "ndeftype"; |
| 93 | |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 94 | /** @hide */ |
| 95 | public static final int TYPE_OTHER = -1; |
| 96 | /** @hide */ |
| 97 | public static final int TYPE_1 = 1; |
| 98 | /** @hide */ |
| 99 | public static final int TYPE_2 = 2; |
| 100 | /** @hide */ |
| 101 | public static final int TYPE_3 = 3; |
| 102 | /** @hide */ |
| 103 | public static final int TYPE_4 = 4; |
| 104 | /** @hide */ |
| 105 | public static final int TYPE_MIFARE_CLASSIC = 101; |
Jeff Hamilton | 5644d0e | 2011-02-24 21:59:52 -0600 | [diff] [blame] | 106 | /** @hide */ |
| 107 | public static final int TYPE_ICODE_SLI = 102; |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 108 | |
| 109 | /** @hide */ |
| 110 | public static final String UNKNOWN = "android.ndef.unknown"; |
| 111 | |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 112 | /** NFC Forum Tag Type 1 */ |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 113 | public static final String NFC_FORUM_TYPE_1 = "org.nfcforum.ndef.type1"; |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 114 | /** NFC Forum Tag Type 2 */ |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 115 | public static final String NFC_FORUM_TYPE_2 = "org.nfcforum.ndef.type2"; |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 116 | /** NFC Forum Tag Type 4 */ |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 117 | public static final String NFC_FORUM_TYPE_3 = "org.nfcforum.ndef.type3"; |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 118 | /** NFC Forum Tag Type 4 */ |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 119 | public static final String NFC_FORUM_TYPE_4 = "org.nfcforum.ndef.type4"; |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 120 | /** NDEF on MIFARE Classic */ |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 121 | public static final String MIFARE_CLASSIC = "com.nxp.ndef.mifareclassic"; |
Jeff Hamilton | 5644d0e | 2011-02-24 21:59:52 -0600 | [diff] [blame] | 122 | /** |
| 123 | * NDEF on iCODE SLI |
| 124 | * @hide |
| 125 | */ |
| 126 | public static final String ICODE_SLI = "com.nxp.ndef.icodesli"; |
Martijn Coenen | d27ebf1 | 2010-12-22 13:51:51 +0100 | [diff] [blame] | 127 | |
Martijn Coenen | 3300e4c | 2010-12-08 23:23:47 -0800 | [diff] [blame] | 128 | private final int mMaxNdefSize; |
| 129 | private final int mCardState; |
Martijn Coenen | e3f6336 | 2010-12-13 16:18:41 +0100 | [diff] [blame] | 130 | private final NdefMessage mNdefMsg; |
Martijn Coenen | d27ebf1 | 2010-12-22 13:51:51 +0100 | [diff] [blame] | 131 | private final int mNdefType; |
Martijn Coenen | 6d9fc7e | 2010-12-07 14:04:28 -0800 | [diff] [blame] | 132 | |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 133 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 134 | * Get an instance of {@link Ndef} for the given tag. |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 135 | * |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 136 | * <p>Returns null if {@link Ndef} was not enumerated in {@link Tag#getTechList}. |
| 137 | * This indicates the tag is not NDEF formatted, or that this tag |
| 138 | * is NDEF formatted but under a vendor specification that this Android |
| 139 | * device does not implement. |
| 140 | * |
| 141 | * <p>Does not cause any RF activity and does not block. |
| 142 | * |
Martijn Coenen | 0bec15e | 2012-09-23 16:33:59 -0700 | [diff] [blame] | 143 | * @param tag an NDEF compatible tag |
| 144 | * @return Ndef object |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 145 | */ |
| 146 | public static Ndef get(Tag tag) { |
| 147 | if (!tag.hasTech(TagTechnology.NDEF)) return null; |
| 148 | try { |
| 149 | return new Ndef(tag); |
| 150 | } catch (RemoteException e) { |
| 151 | return null; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | /** |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 156 | * Internal constructor, to be used by NfcAdapter |
| 157 | * @hide |
| 158 | */ |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 159 | public Ndef(Tag tag) throws RemoteException { |
| 160 | super(tag, TagTechnology.NDEF); |
| 161 | Bundle extras = tag.getTechExtras(TagTechnology.NDEF); |
Martijn Coenen | 6d9fc7e | 2010-12-07 14:04:28 -0800 | [diff] [blame] | 162 | if (extras != null) { |
Martijn Coenen | 3300e4c | 2010-12-08 23:23:47 -0800 | [diff] [blame] | 163 | mMaxNdefSize = extras.getInt(EXTRA_NDEF_MAXLENGTH); |
| 164 | mCardState = extras.getInt(EXTRA_NDEF_CARDSTATE); |
Martijn Coenen | e3f6336 | 2010-12-13 16:18:41 +0100 | [diff] [blame] | 165 | mNdefMsg = extras.getParcelable(EXTRA_NDEF_MSG); |
Martijn Coenen | d27ebf1 | 2010-12-22 13:51:51 +0100 | [diff] [blame] | 166 | mNdefType = extras.getInt(EXTRA_NDEF_TYPE); |
Martijn Coenen | 6d9fc7e | 2010-12-07 14:04:28 -0800 | [diff] [blame] | 167 | } else { |
Martijn Coenen | 3300e4c | 2010-12-08 23:23:47 -0800 | [diff] [blame] | 168 | throw new NullPointerException("NDEF tech extras are null."); |
Martijn Coenen | 6d9fc7e | 2010-12-07 14:04:28 -0800 | [diff] [blame] | 169 | } |
Martijn Coenen | 3300e4c | 2010-12-08 23:23:47 -0800 | [diff] [blame] | 170 | |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 171 | } |
| 172 | |
| 173 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 174 | * Get the {@link NdefMessage} that was read from the tag at discovery time. |
| 175 | * |
| 176 | * <p>If the NDEF Message is modified by an I/O operation then it |
| 177 | * will not be updated here, this function only returns what was discovered |
| 178 | * when the tag entered the field. |
Martijn Coenen | a032783 | 2012-03-29 10:53:08 -0700 | [diff] [blame] | 179 | * <p>Note that this method may return null if the tag was in the |
| 180 | * INITIALIZED state as defined by NFC Forum, as in this state the |
| 181 | * tag is formatted to support NDEF but does not contain a message yet. |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 182 | * <p>Does not cause any RF activity and does not block. |
Martijn Coenen | a032783 | 2012-03-29 10:53:08 -0700 | [diff] [blame] | 183 | * @return NDEF Message read from the tag at discovery time, can be null |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 184 | */ |
Martijn Coenen | e3f6336 | 2010-12-13 16:18:41 +0100 | [diff] [blame] | 185 | public NdefMessage getCachedNdefMessage() { |
| 186 | return mNdefMsg; |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 187 | } |
| 188 | |
| 189 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 190 | * Get the NDEF tag type. |
| 191 | * |
Nick Pelly | ddbb2c9 | 2011-01-04 17:29:14 +1100 | [diff] [blame] | 192 | * <p>Returns one of {@link #NFC_FORUM_TYPE_1}, {@link #NFC_FORUM_TYPE_2}, |
| 193 | * {@link #NFC_FORUM_TYPE_3}, {@link #NFC_FORUM_TYPE_4}, |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 194 | * {@link #MIFARE_CLASSIC} or another NDEF tag type that has not yet been |
| 195 | * formalized in this Android API. |
| 196 | * |
| 197 | * <p>Does not cause any RF activity and does not block. |
| 198 | * |
| 199 | * @return a string representing the NDEF tag type |
Martijn Coenen | d27ebf1 | 2010-12-22 13:51:51 +0100 | [diff] [blame] | 200 | */ |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 201 | public String getType() { |
| 202 | switch (mNdefType) { |
| 203 | case TYPE_1: |
| 204 | return NFC_FORUM_TYPE_1; |
| 205 | case TYPE_2: |
| 206 | return NFC_FORUM_TYPE_2; |
| 207 | case TYPE_3: |
| 208 | return NFC_FORUM_TYPE_3; |
| 209 | case TYPE_4: |
| 210 | return NFC_FORUM_TYPE_4; |
| 211 | case TYPE_MIFARE_CLASSIC: |
| 212 | return MIFARE_CLASSIC; |
Jeff Hamilton | 5644d0e | 2011-02-24 21:59:52 -0600 | [diff] [blame] | 213 | case TYPE_ICODE_SLI: |
| 214 | return ICODE_SLI; |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 215 | default: |
| 216 | return UNKNOWN; |
| 217 | } |
Martijn Coenen | d27ebf1 | 2010-12-22 13:51:51 +0100 | [diff] [blame] | 218 | } |
| 219 | |
| 220 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 221 | * Get the maximum NDEF message size in bytes. |
| 222 | * |
| 223 | * <p>Does not cause any RF activity and does not block. |
| 224 | * |
| 225 | * @return size in bytes |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 226 | */ |
Martijn Coenen | 3300e4c | 2010-12-08 23:23:47 -0800 | [diff] [blame] | 227 | public int getMaxSize() { |
| 228 | return mMaxNdefSize; |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 229 | } |
| 230 | |
| 231 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 232 | * Determine if the tag is writable. |
| 233 | * |
| 234 | * <p>NFC Forum tags can be in read-only or read-write states. |
| 235 | * |
| 236 | * <p>Does not cause any RF activity and does not block. |
| 237 | * |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 238 | * <p>Requires {@link android.Manifest.permission#NFC} permission. |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 239 | * |
| 240 | * @return true if the tag is writable |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 241 | */ |
Martijn Coenen | 3300e4c | 2010-12-08 23:23:47 -0800 | [diff] [blame] | 242 | public boolean isWritable() { |
| 243 | return (mCardState == NDEF_MODE_READ_WRITE); |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 244 | } |
| 245 | |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 246 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 247 | * Read the current {@link android.nfc.NdefMessage} on this tag. |
| 248 | * |
| 249 | * <p>This always reads the current NDEF Message stored on the tag. |
| 250 | * |
Martijn Coenen | a032783 | 2012-03-29 10:53:08 -0700 | [diff] [blame] | 251 | * <p>Note that this method may return null if the tag was in the |
| 252 | * INITIALIZED state as defined by NFC Forum, as in that state the |
| 253 | * tag is formatted to support NDEF but does not contain a message yet. |
| 254 | * |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 255 | * <p>This is an I/O operation and will block until complete. It must |
| 256 | * not be called from the main application thread. A blocked call will be canceled with |
| 257 | * {@link IOException} if {@link #close} is called from another thread. |
| 258 | * |
Martijn Coenen | 6c65344 | 2012-03-29 15:31:13 -0700 | [diff] [blame] | 259 | * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. |
| 260 | * |
Martijn Coenen | a032783 | 2012-03-29 10:53:08 -0700 | [diff] [blame] | 261 | * @return the NDEF Message, can be null |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 262 | * @throws TagLostException if the tag leaves the field |
| 263 | * @throws IOException if there is an I/O failure, or the operation is canceled |
| 264 | * @throws FormatException if the NDEF Message on the tag is malformed |
Martijn Coenen | e3f6336 | 2010-12-13 16:18:41 +0100 | [diff] [blame] | 265 | */ |
| 266 | public NdefMessage getNdefMessage() throws IOException, FormatException { |
Martijn Coenen | 4049f9d0 | 2010-12-14 16:58:27 +0100 | [diff] [blame] | 267 | checkConnected(); |
| 268 | |
Martijn Coenen | e3f6336 | 2010-12-13 16:18:41 +0100 | [diff] [blame] | 269 | try { |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 270 | INfcTag tagService = mTag.getTagService(); |
Martijn Coenen | 23fc93a | 2011-11-28 10:43:14 -0800 | [diff] [blame] | 271 | if (tagService == null) { |
| 272 | throw new IOException("Mock tags don't support this operation."); |
| 273 | } |
Martijn Coenen | e3f6336 | 2010-12-13 16:18:41 +0100 | [diff] [blame] | 274 | int serviceHandle = mTag.getServiceHandle(); |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 275 | if (tagService.isNdef(serviceHandle)) { |
| 276 | NdefMessage msg = tagService.ndefRead(serviceHandle); |
Martijn Coenen | a032783 | 2012-03-29 10:53:08 -0700 | [diff] [blame] | 277 | if (msg == null && !tagService.isPresent(serviceHandle)) { |
| 278 | throw new TagLostException(); |
Martijn Coenen | e3f6336 | 2010-12-13 16:18:41 +0100 | [diff] [blame] | 279 | } |
| 280 | return msg; |
| 281 | } else { |
| 282 | return null; |
| 283 | } |
| 284 | } catch (RemoteException e) { |
Nick Pelly | 3dd6c45 | 2011-01-10 18:14:41 +1100 | [diff] [blame] | 285 | Log.e(TAG, "NFC service dead", e); |
Martijn Coenen | e3f6336 | 2010-12-13 16:18:41 +0100 | [diff] [blame] | 286 | return null; |
| 287 | } |
| 288 | } |
Jeff Hamilton | 3ce86481 | 2010-12-18 16:39:37 -0600 | [diff] [blame] | 289 | |
Martijn Coenen | e3f6336 | 2010-12-13 16:18:41 +0100 | [diff] [blame] | 290 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 291 | * Overwrite the {@link NdefMessage} on this tag. |
| 292 | * |
| 293 | * <p>This is an I/O operation and will block until complete. It must |
| 294 | * not be called from the main application thread. A blocked call will be canceled with |
| 295 | * {@link IOException} if {@link #close} is called from another thread. |
| 296 | * |
Nick Pelly | 39cf3a4 | 2011-02-07 17:04:21 +0900 | [diff] [blame] | 297 | * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. |
| 298 | * |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 299 | * @param msg the NDEF Message to write, must not be null |
| 300 | * @throws TagLostException if the tag leaves the field |
| 301 | * @throws IOException if there is an I/O failure, or the operation is canceled |
| 302 | * @throws FormatException if the NDEF Message to write is malformed |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 303 | */ |
| 304 | public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException { |
Martijn Coenen | 4049f9d0 | 2010-12-14 16:58:27 +0100 | [diff] [blame] | 305 | checkConnected(); |
| 306 | |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 307 | try { |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 308 | INfcTag tagService = mTag.getTagService(); |
Martijn Coenen | 23fc93a | 2011-11-28 10:43:14 -0800 | [diff] [blame] | 309 | if (tagService == null) { |
| 310 | throw new IOException("Mock tags don't support this operation."); |
| 311 | } |
Martijn Coenen | 01d159a | 2010-12-16 22:39:20 +0100 | [diff] [blame] | 312 | int serviceHandle = mTag.getServiceHandle(); |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 313 | if (tagService.isNdef(serviceHandle)) { |
| 314 | int errorCode = tagService.ndefWrite(serviceHandle, msg); |
Martijn Coenen | 01d159a | 2010-12-16 22:39:20 +0100 | [diff] [blame] | 315 | switch (errorCode) { |
| 316 | case ErrorCodes.SUCCESS: |
| 317 | break; |
| 318 | case ErrorCodes.ERROR_IO: |
| 319 | throw new IOException(); |
| 320 | case ErrorCodes.ERROR_INVALID_PARAM: |
| 321 | throw new FormatException(); |
| 322 | default: |
| 323 | // Should not happen |
| 324 | throw new IOException(); |
| 325 | } |
| 326 | } |
| 327 | else { |
| 328 | throw new IOException("Tag is not ndef"); |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 329 | } |
| 330 | } catch (RemoteException e) { |
Nick Pelly | 3dd6c45 | 2011-01-10 18:14:41 +1100 | [diff] [blame] | 331 | Log.e(TAG, "NFC service dead", e); |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 332 | } |
| 333 | } |
| 334 | |
| 335 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 336 | * Indicates whether a tag can be made read-only with {@link #makeReadOnly()}. |
| 337 | * |
| 338 | * <p>Does not cause any RF activity and does not block. |
| 339 | * |
| 340 | * @return true if it is possible to make this tag read-only |
Martijn Coenen | 25be536 | 2011-01-10 16:12:52 +0100 | [diff] [blame] | 341 | */ |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 342 | public boolean canMakeReadOnly() { |
Martijn Coenen | faca12a | 2011-08-19 14:07:52 +0200 | [diff] [blame] | 343 | INfcTag tagService = mTag.getTagService(); |
Martijn Coenen | 23fc93a | 2011-11-28 10:43:14 -0800 | [diff] [blame] | 344 | if (tagService == null) { |
| 345 | return false; |
| 346 | } |
Martijn Coenen | faca12a | 2011-08-19 14:07:52 +0200 | [diff] [blame] | 347 | try { |
| 348 | return tagService.canMakeReadOnly(mNdefType); |
| 349 | } catch (RemoteException e) { |
| 350 | Log.e(TAG, "NFC service dead", e); |
Martijn Coenen | 25be536 | 2011-01-10 16:12:52 +0100 | [diff] [blame] | 351 | return false; |
| 352 | } |
| 353 | } |
| 354 | |
| 355 | /** |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 356 | * Make a tag read-only. |
| 357 | * |
| 358 | * <p>This sets the CC field to indicate the tag is read-only, |
| 359 | * and where possible permanently sets the lock bits to prevent |
| 360 | * any further modification of the memory. |
| 361 | * <p>This is a one-way process and cannot be reverted! |
| 362 | * |
| 363 | * <p>This is an I/O operation and will block until complete. It must |
| 364 | * not be called from the main application thread. A blocked call will be canceled with |
| 365 | * {@link IOException} if {@link #close} is called from another thread. |
| 366 | * |
Nick Pelly | 39cf3a4 | 2011-02-07 17:04:21 +0900 | [diff] [blame] | 367 | * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. |
| 368 | * |
Nick Pelly | 74fe6c6 | 2011-02-02 22:37:40 -0800 | [diff] [blame] | 369 | * @return true on success, false if it is not possible to make this tag read-only |
| 370 | * @throws TagLostException if the tag leaves the field |
| 371 | * @throws IOException if there is an I/O failure, or the operation is canceled |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 372 | */ |
Nick Pelly | f003e26 | 2011-01-31 23:27:37 -0800 | [diff] [blame] | 373 | public boolean makeReadOnly() throws IOException { |
Martijn Coenen | 4049f9d0 | 2010-12-14 16:58:27 +0100 | [diff] [blame] | 374 | checkConnected(); |
| 375 | |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 376 | try { |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 377 | INfcTag tagService = mTag.getTagService(); |
Martijn Coenen | 23fc93a | 2011-11-28 10:43:14 -0800 | [diff] [blame] | 378 | if (tagService == null) { |
| 379 | return false; |
| 380 | } |
Jeff Hamilton | 4e21e1d | 2011-01-21 01:13:06 -0600 | [diff] [blame] | 381 | if (tagService.isNdef(mTag.getServiceHandle())) { |
| 382 | int errorCode = tagService.ndefMakeReadOnly(mTag.getServiceHandle()); |
Martijn Coenen | 07e6f61 | 2011-01-14 16:26:45 +0100 | [diff] [blame] | 383 | switch (errorCode) { |
| 384 | case ErrorCodes.SUCCESS: |
| 385 | return true; |
| 386 | case ErrorCodes.ERROR_IO: |
| 387 | throw new IOException(); |
| 388 | case ErrorCodes.ERROR_INVALID_PARAM: |
| 389 | return false; |
| 390 | default: |
| 391 | // Should not happen |
| 392 | throw new IOException(); |
| 393 | } |
| 394 | } |
| 395 | else { |
| 396 | throw new IOException("Tag is not ndef"); |
| 397 | } |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 398 | } catch (RemoteException e) { |
Nick Pelly | 3dd6c45 | 2011-01-10 18:14:41 +1100 | [diff] [blame] | 399 | Log.e(TAG, "NFC service dead", e); |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 400 | return false; |
| 401 | } |
| 402 | } |
Jeff Hamilton | 6be655c | 2010-11-12 12:28:16 -0600 | [diff] [blame] | 403 | } |