NfcAdapter.java revision fdf9086e24f4720ee9fbc852b980041f126aa3c2
1/* 2 * Copyright (C) 2010 The Android Open Source Project Licensed under the Apache 3 * License, Version 2.0 (the "License"); you may not use this file except in 4 * compliance with the License. You may obtain a copy of the License at 5 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law 6 * or agreed to in writing, software distributed under the License is 7 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 8 * KIND, either express or implied. See the License for the specific language 9 * governing permissions and limitations under the License. 10 */ 11 12package android.nfc; 13 14import java.lang.UnsupportedOperationException; 15 16import android.annotation.SdkConstant; 17import android.annotation.SdkConstant.SdkConstantType; 18import android.app.ActivityThread; 19import android.content.Context; 20import android.content.pm.IPackageManager; 21import android.content.pm.PackageManager; 22import android.nfc.INfcAdapter; 23import android.os.IBinder; 24import android.os.RemoteException; 25import android.os.ServiceManager; 26import android.util.Log; 27 28/** 29 * Represents the device's local NFC adapter. 30 * <p> 31 * Use the static {@link #getDefaultAdapter} method to get the default NFC 32 * Adapter for this Android device. Most Android devices will have only one NFC 33 * Adapter, and {@link #getDefaultAdapter} returns the singleton object. 34 * <p> 35 * {@link NfcAdapter} can be used to create {@link RawTagConnection} or 36 * {@link NdefTagConnection} connections to modify or perform low level access 37 * to NFC Tags. 38 * <p class="note"> 39 * <strong>Note:</strong> Some methods require the 40 * {@link android.Manifest.permission#NFC} permission. 41 */ 42public final class NfcAdapter { 43 /** 44 * Intent to start an activity when a non-NDEF tag is discovered. 45 * TODO(npelly) finalize decision on using CATEGORY or DATA URI to provide a 46 * hint for applications to filter the tag type. 47 * TODO(npelly) probably combine these two intents since tags aren't that simple 48 */ 49 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 50 public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; 51 52 /** 53 * Intent to start an activity when a NDEF tag is discovered. TODO(npelly) 54 * finalize decision on using CATEGORY or DATA URI to provide a hint for 55 * applications to filter the tag type. 56 */ 57 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 58 public static final String ACTION_NDEF_TAG_DISCOVERED = 59 "android.nfc.action.NDEF_TAG_DISCOVERED"; 60 61 /** 62 * Mandatory Tag extra for the ACTION_TAG and ACTION_NDEF_TAG intents. 63 */ 64 public static final String EXTRA_TAG = "android.nfc.extra.TAG"; 65 66 /** 67 * Broadcast Action: a transaction with a secure element has been detected. 68 * <p> 69 * Always contains the extra field 70 * {@link android.nfc.NfcAdapter#EXTRA_AID} 71 * @hide 72 */ 73 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 74 public static final String ACTION_TRANSACTION_DETECTED = 75 "android.nfc.action.TRANSACTION_DETECTED"; 76 77 /** 78 * Mandatory byte array extra field in 79 * {@link android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED}. 80 * <p> 81 * Contains the AID of the applet involved in the transaction. 82 * @hide 83 */ 84 public static final String EXTRA_AID = "android.nfc.extra.AID"; 85 86 /** 87 * LLCP link status: The LLCP link is activated. 88 * @hide 89 */ 90 public static final int LLCP_LINK_STATE_ACTIVATED = 0; 91 92 /** 93 * LLCP link status: The LLCP link is deactivated. 94 * @hide 95 */ 96 public static final int LLCP_LINK_STATE_DEACTIVATED = 1; 97 98 /** 99 * Broadcast Action: the LLCP link state changed. 100 * <p> 101 * Always contains the extra field 102 * {@link android.nfc.NfcAdapter#EXTRA_LLCP_LINK_STATE_CHANGED}. 103 * @hide 104 */ 105 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 106 public static final String ACTION_LLCP_LINK_STATE_CHANGED = 107 "android.nfc.action.LLCP_LINK_STATE_CHANGED"; 108 109 /** 110 * Used as int extra field in 111 * {@link android.nfc.NfcAdapter#ACTION_LLCP_LINK_STATE_CHANGED}. 112 * <p> 113 * It contains the new state of the LLCP link. 114 * @hide 115 */ 116 public static final String EXTRA_LLCP_LINK_STATE_CHANGED = "android.nfc.extra.LLCP_LINK_STATE"; 117 118 /** 119 * Tag Reader Discovery mode 120 * @hide 121 */ 122 private static final int DISCOVERY_MODE_TAG_READER = 0; 123 124 /** 125 * NFC-IP1 Peer-to-Peer mode Enables the manager to act as a peer in an 126 * NFC-IP1 communication. Implementations should not assume that the 127 * controller will end up behaving as an NFC-IP1 target or initiator and 128 * should handle both cases, depending on the type of the remote peer type. 129 * @hide 130 */ 131 private static final int DISCOVERY_MODE_NFCIP1 = 1; 132 133 /** 134 * Card Emulation mode Enables the manager to act as an NFC tag. Provided 135 * that a Secure Element (an UICC for instance) is connected to the NFC 136 * controller through its SWP interface, it can be exposed to the outside 137 * NFC world and be addressed by external readers the same way they would 138 * with a tag. 139 * <p> 140 * Which Secure Element is exposed is implementation-dependent. 141 * 142 * @hide 143 */ 144 private static final int DISCOVERY_MODE_CARD_EMULATION = 2; 145 146 private static final String TAG = "NFC"; 147 148 private static boolean sIsInitialized = false; 149 private static NfcAdapter sAdapter; 150 151 private final INfcAdapter mService; 152 153 private NfcAdapter(INfcAdapter service) { 154 mService = service; 155 } 156 157 /** 158 * Helper to check if this device has FEATURE_NFC, but without using 159 * a context. 160 * Equivalent to 161 * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC) 162 */ 163 private static boolean hasNfcFeature() { 164 IPackageManager pm = ActivityThread.getPackageManager(); 165 if (pm == null) { 166 Log.e(TAG, "Cannot get package manager, assuming no NFC feature"); 167 return false; 168 } 169 try { 170 return pm.hasSystemFeature(PackageManager.FEATURE_NFC); 171 } catch (RemoteException e) { 172 Log.e(TAG, "Package manager query failed, assuming no NFC feature", e); 173 return false; 174 } 175 } 176 177 /** 178 * Get a handle to the default NFC Adapter on this Android device. 179 * <p> 180 * Most Android devices will only have one NFC Adapter (NFC Controller). 181 * 182 * @return the default NFC adapter, or null if no NFC adapter exists 183 */ 184 public static NfcAdapter getDefaultAdapter() { 185 synchronized (NfcAdapter.class) { 186 if (sIsInitialized) { 187 return sAdapter; 188 } 189 sIsInitialized = true; 190 191 /* is this device meant to have NFC */ 192 if (!hasNfcFeature()) { 193 Log.v(TAG, "this device does not have NFC support"); 194 return null; 195 } 196 197 /* get a handle to NFC service */ 198 IBinder b = ServiceManager.getService("nfc"); 199 if (b == null) { 200 Log.e(TAG, "could not retrieve NFC service"); 201 return null; 202 } 203 204 sAdapter = new NfcAdapter(INfcAdapter.Stub.asInterface(b)); 205 return sAdapter; 206 } 207 } 208 209 /** 210 * Return true if this NFC Adapter is enabled to discover new tags. 211 * <p> 212 * If this method returns false, then applications should request the user 213 * turn on NFC tag discovery in Settings. 214 * 215 * @return true if this NFC Adapter is enabled to discover new tags 216 */ 217 public boolean isTagDiscoveryEnabled() { 218 try { 219 return mService.isEnabled(); 220 } catch (RemoteException e) { 221 Log.e(TAG, "RemoteException in isEnabled()", e); 222 return false; 223 } 224 } 225 226 /** 227 * @hide 228 */ 229 public boolean enableTagDiscovery() { 230 try { 231 return mService.enable(); 232 } catch (RemoteException e) { 233 Log.e(TAG, "RemoteException in enable()", e); 234 return false; 235 } 236 } 237 238 /** 239 * @hide 240 */ 241 public boolean disableTagDiscovery() { 242 try { 243 return mService.disable(); 244 } catch (RemoteException e) { 245 Log.e(TAG, "RemoteException in disable()", e); 246 return false; 247 } 248 } 249 250 /** 251 * Set the NDEF Message that this NFC adapter should appear as to Tag 252 * readers. 253 * <p> 254 * Any Tag reader can read the contents of the local tag when it is in 255 * proximity, without any further user confirmation. 256 * <p> 257 * The implementation of this method must either 258 * <ul> 259 * <li>act as a passive tag containing this NDEF message 260 * <li>provide the NDEF message on over LLCP to peer NFC adapters 261 * </ul> 262 * The NDEF message is preserved across reboot. 263 * <p>Requires {@link android.Manifest.permission#NFC} permission. 264 * 265 * @param message NDEF message to make public 266 */ 267 public void setLocalNdefMessage(NdefMessage message) { 268 try { 269 mService.localSet(message); 270 } catch (RemoteException e) { 271 Log.e(TAG, "NFC service died", e); 272 } 273 } 274 275 /** 276 * Get the NDEF Message that this adapter appears as to Tag readers. 277 * <p>Requires {@link android.Manifest.permission#NFC} permission. 278 * 279 * @return NDEF Message that is publicly readable 280 */ 281 public NdefMessage getLocalNdefMessage() { 282 try { 283 return mService.localGet(); 284 } catch (RemoteException e) { 285 Log.e(TAG, "NFC service died", e); 286 return null; 287 } 288 } 289 290 /** 291 * Create a raw tag connection to the default Target 292 * <p>Requires {@link android.Manifest.permission#NFC} permission. 293 */ 294 public RawTagConnection createRawTagConnection(Tag tag) { 295 try { 296 return new RawTagConnection(mService, tag); 297 } catch (RemoteException e) { 298 Log.e(TAG, "NFC service died", e); 299 return null; 300 } 301 } 302 303 /** 304 * Create a raw tag connection to the specified Target 305 * <p>Requires {@link android.Manifest.permission#NFC} permission. 306 */ 307 public RawTagConnection createRawTagConnection(Tag tag, String target) { 308 try { 309 return new RawTagConnection(mService, tag, target); 310 } catch (RemoteException e) { 311 Log.e(TAG, "NFC service died", e); 312 return null; 313 } 314 } 315 316 /** 317 * Create an NDEF tag connection to the default Target 318 * <p>Requires {@link android.Manifest.permission#NFC} permission. 319 */ 320 public NdefTagConnection createNdefTagConnection(NdefTag tag) { 321 try { 322 return new NdefTagConnection(mService, tag); 323 } catch (RemoteException e) { 324 Log.e(TAG, "NFC service died", e); 325 return null; 326 } 327 } 328 329 /** 330 * Create an NDEF tag connection to the specified Target 331 * <p>Requires {@link android.Manifest.permission#NFC} permission. 332 */ 333 public NdefTagConnection createNdefTagConnection(NdefTag tag, String target) { 334 try { 335 return new NdefTagConnection(mService, tag, target); 336 } catch (RemoteException e) { 337 Log.e(TAG, "NFC service died", e); 338 return null; 339 } 340 } 341} 342