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 17 package android.nfc; 18 19 import android.annotation.NonNull; 20 import android.annotation.RequiresPermission; 21 import android.annotation.SdkConstant; 22 import android.annotation.SdkConstant.SdkConstantType; 23 import android.annotation.SystemApi; 24 import android.app.Activity; 25 import android.app.ActivityThread; 26 import android.app.OnActivityPausedListener; 27 import android.app.PendingIntent; 28 import android.compat.annotation.UnsupportedAppUsage; 29 import android.content.Context; 30 import android.content.IntentFilter; 31 import android.content.pm.IPackageManager; 32 import android.content.pm.PackageManager; 33 import android.net.Uri; 34 import android.nfc.tech.MifareClassic; 35 import android.nfc.tech.Ndef; 36 import android.nfc.tech.NfcA; 37 import android.nfc.tech.NfcF; 38 import android.os.Bundle; 39 import android.os.Handler; 40 import android.os.IBinder; 41 import android.os.RemoteException; 42 import android.os.ServiceManager; 43 import android.util.Log; 44 45 import java.io.IOException; 46 import java.util.ArrayList; 47 import java.util.HashMap; 48 import java.util.List; 49 50 /** 51 * Represents the local NFC adapter. 52 * <p> 53 * Use the helper {@link #getDefaultAdapter(Context)} to get the default NFC 54 * adapter for this Android device. 55 * 56 * <div class="special reference"> 57 * <h3>Developer Guides</h3> 58 * <p>For more information about using NFC, read the 59 * <a href="{@docRoot}guide/topics/nfc/index.html">Near Field Communication</a> developer guide.</p> 60 * <p>To perform basic file sharing between devices, read 61 * <a href="{@docRoot}training/beam-files/index.html">Sharing Files with NFC</a>. 62 * </div> 63 */ 64 public final class NfcAdapter { 65 static final String TAG = "NFC"; 66 67 /** 68 * Intent to start an activity when a tag with NDEF payload is discovered. 69 * 70 * <p>The system inspects the first {@link NdefRecord} in the first {@link NdefMessage} and 71 * looks for a URI, SmartPoster, or MIME record. If a URI or SmartPoster record is found the 72 * intent will contain the URI in its data field. If a MIME record is found the intent will 73 * contain the MIME type in its type field. This allows activities to register 74 * {@link IntentFilter}s targeting specific content on tags. Activities should register the 75 * most specific intent filters possible to avoid the activity chooser dialog, which can 76 * disrupt the interaction with the tag as the user interacts with the screen. 77 * 78 * <p>If the tag has an NDEF payload this intent is started before 79 * {@link #ACTION_TECH_DISCOVERED}. If any activities respond to this intent neither 80 * {@link #ACTION_TECH_DISCOVERED} or {@link #ACTION_TAG_DISCOVERED} will be started. 81 * 82 * <p>The MIME type or data URI of this intent are normalized before dispatch - 83 * so that MIME, URI scheme and URI host are always lower-case. 84 */ 85 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 86 public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED"; 87 88 /** 89 * Intent to start an activity when a tag is discovered and activities are registered for the 90 * specific technologies on the tag. 91 * 92 * <p>To receive this intent an activity must include an intent filter 93 * for this action and specify the desired tech types in a 94 * manifest <code>meta-data</code> entry. Here is an example manfiest entry: 95 * <pre> 96 * <activity android:name=".nfc.TechFilter" android:label="NFC/TechFilter"> 97 * <!-- Add a technology filter --> 98 * <intent-filter> 99 * <action android:name="android.nfc.action.TECH_DISCOVERED" /> 100 * </intent-filter> 101 * 102 * <meta-data android:name="android.nfc.action.TECH_DISCOVERED" 103 * android:resource="@xml/filter_nfc" 104 * /> 105 * </activity></pre> 106 * 107 * <p>The meta-data XML file should contain one or more <code>tech-list</code> entries 108 * each consisting or one or more <code>tech</code> entries. The <code>tech</code> entries refer 109 * to the qualified class name implementing the technology, for example "android.nfc.tech.NfcA". 110 * 111 * <p>A tag matches if any of the 112 * <code>tech-list</code> sets is a subset of {@link Tag#getTechList() Tag.getTechList()}. Each 113 * of the <code>tech-list</code>s is considered independently and the 114 * activity is considered a match is any single <code>tech-list</code> matches the tag that was 115 * discovered. This provides AND and OR semantics for filtering desired techs. Here is an 116 * example that will match any tag using {@link NfcF} or any tag using {@link NfcA}, 117 * {@link MifareClassic}, and {@link Ndef}: 118 * 119 * <pre> 120 * <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 121 * <!-- capture anything using NfcF --> 122 * <tech-list> 123 * <tech>android.nfc.tech.NfcF</tech> 124 * </tech-list> 125 * 126 * <!-- OR --> 127 * 128 * <!-- capture all MIFARE Classics with NDEF payloads --> 129 * <tech-list> 130 * <tech>android.nfc.tech.NfcA</tech> 131 * <tech>android.nfc.tech.MifareClassic</tech> 132 * <tech>android.nfc.tech.Ndef</tech> 133 * </tech-list> 134 * </resources></pre> 135 * 136 * <p>This intent is started after {@link #ACTION_NDEF_DISCOVERED} and before 137 * {@link #ACTION_TAG_DISCOVERED}. If any activities respond to {@link #ACTION_NDEF_DISCOVERED} 138 * this intent will not be started. If any activities respond to this intent 139 * {@link #ACTION_TAG_DISCOVERED} will not be started. 140 */ 141 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 142 public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED"; 143 144 /** 145 * Intent to start an activity when a tag is discovered. 146 * 147 * <p>This intent will not be started when a tag is discovered if any activities respond to 148 * {@link #ACTION_NDEF_DISCOVERED} or {@link #ACTION_TECH_DISCOVERED} for the current tag. 149 */ 150 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 151 public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; 152 153 /** 154 * Broadcast Action: Intent to notify an application that a transaction event has occurred 155 * on the Secure Element. 156 * 157 * <p>This intent will only be sent if the application has requested permission for 158 * {@link android.Manifest.permission#NFC_TRANSACTION_EVENT} and if the application has the 159 * necessary access to Secure Element which witnessed the particular event. 160 */ 161 @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT) 162 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 163 public static final String ACTION_TRANSACTION_DETECTED = 164 "android.nfc.action.TRANSACTION_DETECTED"; 165 166 /** 167 * Broadcast Action: Intent to notify if the preferred payment service changed. 168 * 169 * <p>This intent will only be sent to the application has requested permission for 170 * {@link android.Manifest.permission#NFC_PREFERRED_PAYMENT_INFO} and if the application 171 * has the necessary access to Secure Element which witnessed the particular event. 172 */ 173 @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) 174 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 175 public static final String ACTION_PREFERRED_PAYMENT_CHANGED = 176 "android.nfc.action.PREFERRED_PAYMENT_CHANGED"; 177 178 /** 179 * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED 180 * @hide 181 */ 182 public static final String ACTION_TAG_LEFT_FIELD = "android.nfc.action.TAG_LOST"; 183 184 /** 185 * Mandatory extra containing the {@link Tag} that was discovered for the 186 * {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and 187 * {@link #ACTION_TAG_DISCOVERED} intents. 188 */ 189 public static final String EXTRA_TAG = "android.nfc.extra.TAG"; 190 191 /** 192 * Extra containing an array of {@link NdefMessage} present on the discovered tag.<p> 193 * This extra is mandatory for {@link #ACTION_NDEF_DISCOVERED} intents, 194 * and optional for {@link #ACTION_TECH_DISCOVERED}, and 195 * {@link #ACTION_TAG_DISCOVERED} intents.<p> 196 * When this extra is present there will always be at least one 197 * {@link NdefMessage} element. Most NDEF tags have only one NDEF message, 198 * but we use an array for future compatibility. 199 */ 200 public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES"; 201 202 /** 203 * Optional extra containing a byte array containing the ID of the discovered tag for 204 * the {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and 205 * {@link #ACTION_TAG_DISCOVERED} intents. 206 */ 207 public static final String EXTRA_ID = "android.nfc.extra.ID"; 208 209 /** 210 * Broadcast Action: The state of the local NFC adapter has been 211 * changed. 212 * <p>For example, NFC has been turned on or off. 213 * <p>Always contains the extra field {@link #EXTRA_ADAPTER_STATE} 214 */ 215 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 216 public static final String ACTION_ADAPTER_STATE_CHANGED = 217 "android.nfc.action.ADAPTER_STATE_CHANGED"; 218 219 /** 220 * Used as an int extra field in {@link #ACTION_ADAPTER_STATE_CHANGED} 221 * intents to request the current power state. Possible values are: 222 * {@link #STATE_OFF}, 223 * {@link #STATE_TURNING_ON}, 224 * {@link #STATE_ON}, 225 * {@link #STATE_TURNING_OFF}, 226 */ 227 public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE"; 228 229 /** 230 * Mandatory byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED} 231 */ 232 public static final String EXTRA_AID = "android.nfc.extra.AID"; 233 234 /** 235 * Optional byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED} 236 */ 237 public static final String EXTRA_DATA = "android.nfc.extra.DATA"; 238 239 /** 240 * Mandatory String extra field in {@link #ACTION_TRANSACTION_DETECTED} 241 * Indicates the Secure Element on which the transaction occurred. 242 * eSE1...eSEn for Embedded Secure Elements, SIM1...SIMn for UICC, etc. 243 */ 244 public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME"; 245 246 /** 247 * Mandatory String extra field in {@link #ACTION_PREFERRED_PAYMENT_CHANGED} 248 * Indicates the condition when trigger this event. Possible values are: 249 * {@link #PREFERRED_PAYMENT_LOADED}, 250 * {@link #PREFERRED_PAYMENT_CHANGED}, 251 * {@link #PREFERRED_PAYMENT_UPDATED}, 252 */ 253 public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON = 254 "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON"; 255 /** 256 * Nfc is enabled and the preferred payment aids are registered. 257 */ 258 public static final int PREFERRED_PAYMENT_LOADED = 1; 259 /** 260 * User selected another payment application as the preferred payment. 261 */ 262 public static final int PREFERRED_PAYMENT_CHANGED = 2; 263 /** 264 * Current preferred payment has issued an update (registered/unregistered new aids or has been 265 * updated itself). 266 */ 267 public static final int PREFERRED_PAYMENT_UPDATED = 3; 268 269 public static final int STATE_OFF = 1; 270 public static final int STATE_TURNING_ON = 2; 271 public static final int STATE_ON = 3; 272 public static final int STATE_TURNING_OFF = 4; 273 274 /** 275 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 276 * <p> 277 * Setting this flag enables polling for Nfc-A technology. 278 */ 279 public static final int FLAG_READER_NFC_A = 0x1; 280 281 /** 282 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 283 * <p> 284 * Setting this flag enables polling for Nfc-B technology. 285 */ 286 public static final int FLAG_READER_NFC_B = 0x2; 287 288 /** 289 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 290 * <p> 291 * Setting this flag enables polling for Nfc-F technology. 292 */ 293 public static final int FLAG_READER_NFC_F = 0x4; 294 295 /** 296 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 297 * <p> 298 * Setting this flag enables polling for Nfc-V (ISO15693) technology. 299 */ 300 public static final int FLAG_READER_NFC_V = 0x8; 301 302 /** 303 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 304 * <p> 305 * Setting this flag enables polling for NfcBarcode technology. 306 */ 307 public static final int FLAG_READER_NFC_BARCODE = 0x10; 308 309 /** 310 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 311 * <p> 312 * Setting this flag allows the caller to prevent the 313 * platform from performing an NDEF check on the tags it 314 * finds. 315 */ 316 public static final int FLAG_READER_SKIP_NDEF_CHECK = 0x80; 317 318 /** 319 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 320 * <p> 321 * Setting this flag allows the caller to prevent the 322 * platform from playing sounds when it discovers a tag. 323 */ 324 public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 0x100; 325 326 /** 327 * Int Extra for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. 328 * <p> 329 * Setting this integer extra allows the calling application to specify 330 * the delay that the platform will use for performing presence checks 331 * on any discovered tag. 332 */ 333 public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence"; 334 335 /** @hide */ 336 @SystemApi 337 public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1; 338 339 /** @hide */ 340 public static final String ACTION_HANDOVER_TRANSFER_STARTED = 341 "android.nfc.action.HANDOVER_TRANSFER_STARTED"; 342 343 /** @hide */ 344 public static final String ACTION_HANDOVER_TRANSFER_DONE = 345 "android.nfc.action.HANDOVER_TRANSFER_DONE"; 346 347 /** @hide */ 348 public static final String EXTRA_HANDOVER_TRANSFER_STATUS = 349 "android.nfc.extra.HANDOVER_TRANSFER_STATUS"; 350 351 /** @hide */ 352 public static final int HANDOVER_TRANSFER_STATUS_SUCCESS = 0; 353 /** @hide */ 354 public static final int HANDOVER_TRANSFER_STATUS_FAILURE = 1; 355 356 /** @hide */ 357 public static final String EXTRA_HANDOVER_TRANSFER_URI = 358 "android.nfc.extra.HANDOVER_TRANSFER_URI"; 359 360 // Guarded by NfcAdapter.class 361 static boolean sIsInitialized = false; 362 static boolean sHasNfcFeature; 363 static boolean sHasBeamFeature; 364 365 // Final after first constructor, except for 366 // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort 367 // recovery 368 @UnsupportedAppUsage 369 static INfcAdapter sService; 370 static INfcTag sTagService; 371 static INfcCardEmulation sCardEmulationService; 372 static INfcFCardEmulation sNfcFCardEmulationService; 373 374 /** 375 * The NfcAdapter object for each application context. 376 * There is a 1-1 relationship between application context and 377 * NfcAdapter object. 378 */ 379 static HashMap<Context, NfcAdapter> sNfcAdapters = new HashMap(); //guard by NfcAdapter.class 380 381 /** 382 * NfcAdapter used with a null context. This ctor was deprecated but we have 383 * to support it for backwards compatibility. New methods that require context 384 * might throw when called on the null-context NfcAdapter. 385 */ 386 static NfcAdapter sNullContextNfcAdapter; // protected by NfcAdapter.class 387 388 final NfcActivityManager mNfcActivityManager; 389 final Context mContext; 390 final HashMap<NfcUnlockHandler, INfcUnlockHandler> mNfcUnlockHandlers; 391 final Object mLock; 392 393 ITagRemovedCallback mTagRemovedListener; // protected by mLock 394 395 /** 396 * A callback to be invoked when the system finds a tag while the foreground activity is 397 * operating in reader mode. 398 * <p>Register your {@code ReaderCallback} implementation with {@link 399 * NfcAdapter#enableReaderMode} and disable it with {@link 400 * NfcAdapter#disableReaderMode}. 401 * @see NfcAdapter#enableReaderMode 402 */ 403 public interface ReaderCallback { onTagDiscovered(Tag tag)404 public void onTagDiscovered(Tag tag); 405 } 406 407 /** 408 * A callback to be invoked when the system successfully delivers your {@link NdefMessage} 409 * to another device. 410 * @see #setOnNdefPushCompleteCallback 411 * @deprecated this feature is deprecated. File sharing can work using other technology like 412 * Bluetooth. 413 */ 414 @java.lang.Deprecated 415 public interface OnNdefPushCompleteCallback { 416 /** 417 * Called on successful NDEF push. 418 * 419 * <p>This callback is usually made on a binder thread (not the UI thread). 420 * 421 * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set 422 * @see #setNdefPushMessageCallback 423 */ onNdefPushComplete(NfcEvent event)424 public void onNdefPushComplete(NfcEvent event); 425 } 426 427 /** 428 * A callback to be invoked when another NFC device capable of NDEF push (Android Beam) 429 * is within range. 430 * <p>Implement this interface and pass it to {@link 431 * NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()} in order to create an 432 * {@link NdefMessage} at the moment that another device is within range for NFC. Using this 433 * callback allows you to create a message with data that might vary based on the 434 * content currently visible to the user. Alternatively, you can call {@link 435 * #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the 436 * same data. 437 * @deprecated this feature is deprecated. File sharing can work using other technology like 438 * Bluetooth. 439 */ 440 @java.lang.Deprecated 441 public interface CreateNdefMessageCallback { 442 /** 443 * Called to provide a {@link NdefMessage} to push. 444 * 445 * <p>This callback is usually made on a binder thread (not the UI thread). 446 * 447 * <p>Called when this device is in range of another device 448 * that might support NDEF push. It allows the application to 449 * create the NDEF message only when it is required. 450 * 451 * <p>NDEF push cannot occur until this method returns, so do not 452 * block for too long. 453 * 454 * <p>The Android operating system will usually show a system UI 455 * on top of your activity during this time, so do not try to request 456 * input from the user to complete the callback, or provide custom NDEF 457 * push UI. The user probably will not see it. 458 * 459 * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set 460 * @return NDEF message to push, or null to not provide a message 461 */ createNdefMessage(NfcEvent event)462 public NdefMessage createNdefMessage(NfcEvent event); 463 } 464 465 466 /** 467 * @deprecated this feature is deprecated. File sharing can work using other technology like 468 * Bluetooth. 469 */ 470 @java.lang.Deprecated 471 public interface CreateBeamUrisCallback { createBeamUris(NfcEvent event)472 public Uri[] createBeamUris(NfcEvent event); 473 } 474 475 /** 476 * A callback that is invoked when a tag is removed from the field. 477 * @see NfcAdapter#ignore 478 */ 479 public interface OnTagRemovedListener { onTagRemoved()480 void onTagRemoved(); 481 } 482 483 /** 484 * A callback to be invoked when an application has registered as a 485 * handler to unlock the device given an NFC tag at the lockscreen. 486 * @hide 487 */ 488 @SystemApi 489 public interface NfcUnlockHandler { 490 /** 491 * Called at the lock screen to attempt to unlock the device with the given tag. 492 * @param tag the detected tag, to be used to unlock the device 493 * @return true if the device was successfully unlocked 494 */ onUnlockAttempted(Tag tag)495 public boolean onUnlockAttempted(Tag tag); 496 } 497 498 /** 499 * Helper to check if this device has FEATURE_NFC_BEAM, but without using 500 * a context. 501 * Equivalent to 502 * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_BEAM) 503 */ hasBeamFeature()504 private static boolean hasBeamFeature() { 505 IPackageManager pm = ActivityThread.getPackageManager(); 506 if (pm == null) { 507 Log.e(TAG, "Cannot get package manager, assuming no Android Beam feature"); 508 return false; 509 } 510 try { 511 return pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM, 0); 512 } catch (RemoteException e) { 513 Log.e(TAG, "Package manager query failed, assuming no Android Beam feature", e); 514 return false; 515 } 516 } 517 518 /** 519 * Helper to check if this device has FEATURE_NFC, but without using 520 * a context. 521 * Equivalent to 522 * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC) 523 */ hasNfcFeature()524 private static boolean hasNfcFeature() { 525 IPackageManager pm = ActivityThread.getPackageManager(); 526 if (pm == null) { 527 Log.e(TAG, "Cannot get package manager, assuming no NFC feature"); 528 return false; 529 } 530 try { 531 return pm.hasSystemFeature(PackageManager.FEATURE_NFC, 0); 532 } catch (RemoteException e) { 533 Log.e(TAG, "Package manager query failed, assuming no NFC feature", e); 534 return false; 535 } 536 } 537 538 /** 539 * Helper to check if this device is NFC HCE capable, by checking for 540 * FEATURE_NFC_HOST_CARD_EMULATION and/or FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 541 * but without using a context. 542 */ hasNfcHceFeature()543 private static boolean hasNfcHceFeature() { 544 IPackageManager pm = ActivityThread.getPackageManager(); 545 if (pm == null) { 546 Log.e(TAG, "Cannot get package manager, assuming no NFC feature"); 547 return false; 548 } 549 try { 550 return pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION, 0) 551 || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 0); 552 } catch (RemoteException e) { 553 Log.e(TAG, "Package manager query failed, assuming no NFC feature", e); 554 return false; 555 } 556 } 557 558 /** 559 * Return list of Secure Elements which support off host card emulation. 560 * 561 * @return List<String> containing secure elements on the device which supports 562 * off host card emulation. eSE for Embedded secure element, 563 * SIM for UICC and so on. 564 * @hide 565 */ getSupportedOffHostSecureElements()566 public @NonNull List<String> getSupportedOffHostSecureElements() { 567 List<String> offHostSE = new ArrayList<String>(); 568 IPackageManager pm = ActivityThread.getPackageManager(); 569 if (pm == null) { 570 Log.e(TAG, "Cannot get package manager, assuming no off-host CE feature"); 571 return offHostSE; 572 } 573 try { 574 if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC, 0)) { 575 offHostSE.add("SIM"); 576 } 577 if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE, 0)) { 578 offHostSE.add("eSE"); 579 } 580 } catch (RemoteException e) { 581 Log.e(TAG, "Package manager query failed, assuming no off-host CE feature", e); 582 offHostSE.clear(); 583 return offHostSE; 584 } 585 return offHostSE; 586 } 587 588 /** 589 * Returns the NfcAdapter for application context, 590 * or throws if NFC is not available. 591 * @hide 592 */ 593 @UnsupportedAppUsage getNfcAdapter(Context context)594 public static synchronized NfcAdapter getNfcAdapter(Context context) { 595 if (!sIsInitialized) { 596 sHasNfcFeature = hasNfcFeature(); 597 sHasBeamFeature = hasBeamFeature(); 598 boolean hasHceFeature = hasNfcHceFeature(); 599 /* is this device meant to have NFC */ 600 if (!sHasNfcFeature && !hasHceFeature) { 601 Log.v(TAG, "this device does not have NFC support"); 602 throw new UnsupportedOperationException(); 603 } 604 sService = getServiceInterface(); 605 if (sService == null) { 606 Log.e(TAG, "could not retrieve NFC service"); 607 throw new UnsupportedOperationException(); 608 } 609 if (sHasNfcFeature) { 610 try { 611 sTagService = sService.getNfcTagInterface(); 612 } catch (RemoteException e) { 613 Log.e(TAG, "could not retrieve NFC Tag service"); 614 throw new UnsupportedOperationException(); 615 } 616 } 617 if (hasHceFeature) { 618 try { 619 sNfcFCardEmulationService = sService.getNfcFCardEmulationInterface(); 620 } catch (RemoteException e) { 621 Log.e(TAG, "could not retrieve NFC-F card emulation service"); 622 throw new UnsupportedOperationException(); 623 } 624 try { 625 sCardEmulationService = sService.getNfcCardEmulationInterface(); 626 } catch (RemoteException e) { 627 Log.e(TAG, "could not retrieve card emulation service"); 628 throw new UnsupportedOperationException(); 629 } 630 } 631 632 sIsInitialized = true; 633 } 634 if (context == null) { 635 if (sNullContextNfcAdapter == null) { 636 sNullContextNfcAdapter = new NfcAdapter(null); 637 } 638 return sNullContextNfcAdapter; 639 } 640 NfcAdapter adapter = sNfcAdapters.get(context); 641 if (adapter == null) { 642 adapter = new NfcAdapter(context); 643 sNfcAdapters.put(context, adapter); 644 } 645 return adapter; 646 } 647 648 /** get handle to NFC service interface */ getServiceInterface()649 private static INfcAdapter getServiceInterface() { 650 /* get a handle to NFC service */ 651 IBinder b = ServiceManager.getService("nfc"); 652 if (b == null) { 653 return null; 654 } 655 return INfcAdapter.Stub.asInterface(b); 656 } 657 658 /** 659 * Helper to get the default NFC Adapter. 660 * <p> 661 * Most Android devices will only have one NFC Adapter (NFC Controller). 662 * <p> 663 * This helper is the equivalent of: 664 * <pre> 665 * NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE); 666 * NfcAdapter adapter = manager.getDefaultAdapter();</pre> 667 * @param context the calling application's context 668 * 669 * @return the default NFC adapter, or null if no NFC adapter exists 670 */ getDefaultAdapter(Context context)671 public static NfcAdapter getDefaultAdapter(Context context) { 672 if (context == null) { 673 throw new IllegalArgumentException("context cannot be null"); 674 } 675 context = context.getApplicationContext(); 676 if (context == null) { 677 throw new IllegalArgumentException( 678 "context not associated with any application (using a mock context?)"); 679 } 680 /* use getSystemService() for consistency */ 681 NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE); 682 if (manager == null) { 683 // NFC not available 684 return null; 685 } 686 return manager.getDefaultAdapter(); 687 } 688 689 /** 690 * Legacy NfcAdapter getter, always use {@link #getDefaultAdapter(Context)} instead.<p> 691 * This method was deprecated at API level 10 (Gingerbread MR1) because a context is required 692 * for many NFC API methods. Those methods will fail when called on an NfcAdapter 693 * object created from this method.<p> 694 * @deprecated use {@link #getDefaultAdapter(Context)} 695 * @hide 696 */ 697 @Deprecated 698 @UnsupportedAppUsage getDefaultAdapter()699 public static NfcAdapter getDefaultAdapter() { 700 // introduced in API version 9 (GB 2.3) 701 // deprecated in API version 10 (GB 2.3.3) 702 // removed from public API in version 16 (ICS MR2) 703 // should maintain as a hidden API for binary compatibility for a little longer 704 Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " + 705 "NfcAdapter.getDefaultAdapter(Context) instead", new Exception()); 706 707 return NfcAdapter.getNfcAdapter(null); 708 } 709 NfcAdapter(Context context)710 NfcAdapter(Context context) { 711 mContext = context; 712 mNfcActivityManager = new NfcActivityManager(this); 713 mNfcUnlockHandlers = new HashMap<NfcUnlockHandler, INfcUnlockHandler>(); 714 mTagRemovedListener = null; 715 mLock = new Object(); 716 } 717 718 /** 719 * @hide 720 */ 721 @UnsupportedAppUsage getContext()722 public Context getContext() { 723 return mContext; 724 } 725 726 /** 727 * Returns the binder interface to the service. 728 * @hide 729 */ 730 @UnsupportedAppUsage getService()731 public INfcAdapter getService() { 732 isEnabled(); // NOP call to recover sService if it is stale 733 return sService; 734 } 735 736 /** 737 * Returns the binder interface to the tag service. 738 * @hide 739 */ getTagService()740 public INfcTag getTagService() { 741 isEnabled(); // NOP call to recover sTagService if it is stale 742 return sTagService; 743 } 744 745 /** 746 * Returns the binder interface to the card emulation service. 747 * @hide 748 */ getCardEmulationService()749 public INfcCardEmulation getCardEmulationService() { 750 isEnabled(); 751 return sCardEmulationService; 752 } 753 754 /** 755 * Returns the binder interface to the NFC-F card emulation service. 756 * @hide 757 */ getNfcFCardEmulationService()758 public INfcFCardEmulation getNfcFCardEmulationService() { 759 isEnabled(); 760 return sNfcFCardEmulationService; 761 } 762 763 /** 764 * Returns the binder interface to the NFC-DTA test interface. 765 * @hide 766 */ getNfcDtaInterface()767 public INfcDta getNfcDtaInterface() { 768 if (mContext == null) { 769 throw new UnsupportedOperationException("You need a context on NfcAdapter to use the " 770 + " NFC extras APIs"); 771 } 772 try { 773 return sService.getNfcDtaInterface(mContext.getPackageName()); 774 } catch (RemoteException e) { 775 attemptDeadServiceRecovery(e); 776 return null; 777 } 778 } 779 780 /** 781 * NFC service dead - attempt best effort recovery 782 * @hide 783 */ 784 @UnsupportedAppUsage attemptDeadServiceRecovery(Exception e)785 public void attemptDeadServiceRecovery(Exception e) { 786 Log.e(TAG, "NFC service dead - attempting to recover", e); 787 INfcAdapter service = getServiceInterface(); 788 if (service == null) { 789 Log.e(TAG, "could not retrieve NFC service during service recovery"); 790 // nothing more can be done now, sService is still stale, we'll hit 791 // this recovery path again later 792 return; 793 } 794 // assigning to sService is not thread-safe, but this is best-effort code 795 // and on a well-behaved system should never happen 796 sService = service; 797 try { 798 sTagService = service.getNfcTagInterface(); 799 } catch (RemoteException ee) { 800 Log.e(TAG, "could not retrieve NFC tag service during service recovery"); 801 // nothing more can be done now, sService is still stale, we'll hit 802 // this recovery path again later 803 return; 804 } 805 806 try { 807 sCardEmulationService = service.getNfcCardEmulationInterface(); 808 } catch (RemoteException ee) { 809 Log.e(TAG, "could not retrieve NFC card emulation service during service recovery"); 810 } 811 812 try { 813 sNfcFCardEmulationService = service.getNfcFCardEmulationInterface(); 814 } catch (RemoteException ee) { 815 Log.e(TAG, "could not retrieve NFC-F card emulation service during service recovery"); 816 } 817 818 return; 819 } 820 821 /** 822 * Return true if this NFC Adapter has any features enabled. 823 * 824 * <p>If this method returns false, the NFC hardware is guaranteed not to 825 * generate or respond to any NFC communication over its NFC radio. 826 * <p>Applications can use this to check if NFC is enabled. Applications 827 * can request Settings UI allowing the user to toggle NFC using: 828 * <p><pre>startActivity(new Intent(Settings.ACTION_NFC_SETTINGS))</pre> 829 * 830 * @see android.provider.Settings#ACTION_NFC_SETTINGS 831 * @return true if this NFC Adapter has any features enabled 832 */ isEnabled()833 public boolean isEnabled() { 834 try { 835 return sService.getState() == STATE_ON; 836 } catch (RemoteException e) { 837 attemptDeadServiceRecovery(e); 838 return false; 839 } 840 } 841 842 /** 843 * Return the state of this NFC Adapter. 844 * 845 * <p>Returns one of {@link #STATE_ON}, {@link #STATE_TURNING_ON}, 846 * {@link #STATE_OFF}, {@link #STATE_TURNING_OFF}. 847 * 848 * <p>{@link #isEnabled()} is equivalent to 849 * <code>{@link #getAdapterState()} == {@link #STATE_ON}</code> 850 * 851 * @return the current state of this NFC adapter 852 * 853 * @hide 854 */ 855 @UnsupportedAppUsage getAdapterState()856 public int getAdapterState() { 857 try { 858 return sService.getState(); 859 } catch (RemoteException e) { 860 attemptDeadServiceRecovery(e); 861 return NfcAdapter.STATE_OFF; 862 } 863 } 864 865 /** 866 * Enable NFC hardware. 867 * 868 * <p>This call is asynchronous. Listen for 869 * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the 870 * operation is complete. 871 * 872 * <p>If this returns true, then either NFC is already on, or 873 * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent 874 * to indicate a state transition. If this returns false, then 875 * there is some problem that prevents an attempt to turn 876 * NFC on (for example we are in airplane mode and NFC is not 877 * toggleable in airplane mode on this platform). 878 * 879 * @hide 880 */ 881 @SystemApi 882 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) enable()883 public boolean enable() { 884 try { 885 return sService.enable(); 886 } catch (RemoteException e) { 887 attemptDeadServiceRecovery(e); 888 return false; 889 } 890 } 891 892 /** 893 * Disable NFC hardware. 894 * 895 * <p>No NFC features will work after this call, and the hardware 896 * will not perform or respond to any NFC communication. 897 * 898 * <p>This call is asynchronous. Listen for 899 * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the 900 * operation is complete. 901 * 902 * <p>If this returns true, then either NFC is already off, or 903 * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent 904 * to indicate a state transition. If this returns false, then 905 * there is some problem that prevents an attempt to turn 906 * NFC off. 907 * 908 * @hide 909 */ 910 @SystemApi 911 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) disable()912 public boolean disable() { 913 try { 914 return sService.disable(true); 915 } catch (RemoteException e) { 916 attemptDeadServiceRecovery(e); 917 return false; 918 } 919 } 920 921 /** 922 * Disable NFC hardware. 923 * @hide 924 */ 925 @SystemApi 926 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) disable(boolean persist)927 public boolean disable(boolean persist) { 928 try { 929 return sService.disable(persist); 930 } catch (RemoteException e) { 931 attemptDeadServiceRecovery(e); 932 return false; 933 } 934 } 935 936 /** 937 * Pauses polling for a {@code timeoutInMs} millis. If polling must be resumed before timeout, 938 * use {@link #resumePolling()}. 939 * @hide 940 */ pausePolling(int timeoutInMs)941 public void pausePolling(int timeoutInMs) { 942 try { 943 sService.pausePolling(timeoutInMs); 944 } catch (RemoteException e) { 945 attemptDeadServiceRecovery(e); 946 } 947 } 948 949 /** 950 * Resumes default polling for the current device state if polling is paused. Calling 951 * this while polling is not paused is a no-op. 952 * 953 * @hide 954 */ resumePolling()955 public void resumePolling() { 956 try { 957 sService.resumePolling(); 958 } catch (RemoteException e) { 959 attemptDeadServiceRecovery(e); 960 } 961 } 962 963 /** 964 * Set one or more {@link Uri}s to send using Android Beam (TM). Every 965 * Uri you provide must have either scheme 'file' or scheme 'content'. 966 * 967 * <p>For the data provided through this method, Android Beam tries to 968 * switch to alternate transports such as Bluetooth to achieve a fast 969 * transfer speed. Hence this method is very suitable 970 * for transferring large files such as pictures or songs. 971 * 972 * <p>The receiving side will store the content of each Uri in 973 * a file and present a notification to the user to open the file 974 * with a {@link android.content.Intent} with action 975 * {@link android.content.Intent#ACTION_VIEW}. 976 * If multiple URIs are sent, the {@link android.content.Intent} will refer 977 * to the first of the stored files. 978 * 979 * <p>This method may be called at any time before {@link Activity#onDestroy}, 980 * but the URI(s) are only made available for Android Beam when the 981 * specified activity(s) are in resumed (foreground) state. The recommended 982 * approach is to call this method during your Activity's 983 * {@link Activity#onCreate} - see sample 984 * code below. This method does not immediately perform any I/O or blocking work, 985 * so is safe to call on your main thread. 986 * 987 * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback} 988 * have priority over both {@link #setNdefPushMessage} and 989 * {@link #setNdefPushMessageCallback}. 990 * 991 * <p>If {@link #setBeamPushUris} is called with a null Uri array, 992 * and/or {@link #setBeamPushUrisCallback} is called with a null callback, 993 * then the Uri push will be completely disabled for the specified activity(s). 994 * 995 * <p>Code example: 996 * <pre> 997 * protected void onCreate(Bundle savedInstanceState) { 998 * super.onCreate(savedInstanceState); 999 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1000 * if (nfcAdapter == null) return; // NFC not available on this device 1001 * nfcAdapter.setBeamPushUris(new Uri[] {uri1, uri2}, this); 1002 * }</pre> 1003 * And that is it. Only one call per activity is necessary. The Android 1004 * OS will automatically release its references to the Uri(s) and the 1005 * Activity object when it is destroyed if you follow this pattern. 1006 * 1007 * <p>If your Activity wants to dynamically supply Uri(s), 1008 * then set a callback using {@link #setBeamPushUrisCallback} instead 1009 * of using this method. 1010 * 1011 * <p class="note">Do not pass in an Activity that has already been through 1012 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1013 * during {@link Activity#onCreate}. 1014 * 1015 * <p class="note">If this device does not support alternate transports 1016 * such as Bluetooth or WiFI, calling this method does nothing. 1017 * 1018 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1019 * 1020 * @param uris an array of Uri(s) to push over Android Beam 1021 * @param activity activity for which the Uri(s) will be pushed 1022 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1023 * @deprecated this feature is deprecated. File sharing can work using other technology like 1024 * Bluetooth. 1025 */ 1026 @java.lang.Deprecated setBeamPushUris(Uri[] uris, Activity activity)1027 public void setBeamPushUris(Uri[] uris, Activity activity) { 1028 synchronized (NfcAdapter.class) { 1029 if (!sHasNfcFeature) { 1030 throw new UnsupportedOperationException(); 1031 } 1032 if (!sHasBeamFeature) { 1033 return; 1034 } 1035 } 1036 if (activity == null) { 1037 throw new NullPointerException("activity cannot be null"); 1038 } 1039 if (uris != null) { 1040 for (Uri uri : uris) { 1041 if (uri == null) throw new NullPointerException("Uri not " + 1042 "allowed to be null"); 1043 String scheme = uri.getScheme(); 1044 if (scheme == null || (!scheme.equalsIgnoreCase("file") && 1045 !scheme.equalsIgnoreCase("content"))) { 1046 throw new IllegalArgumentException("URI needs to have " + 1047 "either scheme file or scheme content"); 1048 } 1049 } 1050 } 1051 mNfcActivityManager.setNdefPushContentUri(activity, uris); 1052 } 1053 1054 /** 1055 * Set a callback that will dynamically generate one or more {@link Uri}s 1056 * to send using Android Beam (TM). Every Uri the callback provides 1057 * must have either scheme 'file' or scheme 'content'. 1058 * 1059 * <p>For the data provided through this callback, Android Beam tries to 1060 * switch to alternate transports such as Bluetooth to achieve a fast 1061 * transfer speed. Hence this method is very suitable 1062 * for transferring large files such as pictures or songs. 1063 * 1064 * <p>The receiving side will store the content of each Uri in 1065 * a file and present a notification to the user to open the file 1066 * with a {@link android.content.Intent} with action 1067 * {@link android.content.Intent#ACTION_VIEW}. 1068 * If multiple URIs are sent, the {@link android.content.Intent} will refer 1069 * to the first of the stored files. 1070 * 1071 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1072 * but the URI(s) are only made available for Android Beam when the 1073 * specified activity(s) are in resumed (foreground) state. The recommended 1074 * approach is to call this method during your Activity's 1075 * {@link Activity#onCreate} - see sample 1076 * code below. This method does not immediately perform any I/O or blocking work, 1077 * so is safe to call on your main thread. 1078 * 1079 * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback} 1080 * have priority over both {@link #setNdefPushMessage} and 1081 * {@link #setNdefPushMessageCallback}. 1082 * 1083 * <p>If {@link #setBeamPushUris} is called with a null Uri array, 1084 * and/or {@link #setBeamPushUrisCallback} is called with a null callback, 1085 * then the Uri push will be completely disabled for the specified activity(s). 1086 * 1087 * <p>Code example: 1088 * <pre> 1089 * protected void onCreate(Bundle savedInstanceState) { 1090 * super.onCreate(savedInstanceState); 1091 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1092 * if (nfcAdapter == null) return; // NFC not available on this device 1093 * nfcAdapter.setBeamPushUrisCallback(callback, this); 1094 * }</pre> 1095 * And that is it. Only one call per activity is necessary. The Android 1096 * OS will automatically release its references to the Uri(s) and the 1097 * Activity object when it is destroyed if you follow this pattern. 1098 * 1099 * <p class="note">Do not pass in an Activity that has already been through 1100 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1101 * during {@link Activity#onCreate}. 1102 * 1103 * <p class="note">If this device does not support alternate transports 1104 * such as Bluetooth or WiFI, calling this method does nothing. 1105 * 1106 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1107 * 1108 * @param callback callback, or null to disable 1109 * @param activity activity for which the Uri(s) will be pushed 1110 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1111 * @deprecated this feature is deprecated. File sharing can work using other technology like 1112 * Bluetooth. 1113 */ 1114 @java.lang.Deprecated setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity)1115 public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) { 1116 synchronized (NfcAdapter.class) { 1117 if (!sHasNfcFeature) { 1118 throw new UnsupportedOperationException(); 1119 } 1120 if (!sHasBeamFeature) { 1121 return; 1122 } 1123 } 1124 if (activity == null) { 1125 throw new NullPointerException("activity cannot be null"); 1126 } 1127 mNfcActivityManager.setNdefPushContentUriCallback(activity, callback); 1128 } 1129 1130 /** 1131 * Set a static {@link NdefMessage} to send using Android Beam (TM). 1132 * 1133 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1134 * but the NDEF message is only made available for NDEF push when the 1135 * specified activity(s) are in resumed (foreground) state. The recommended 1136 * approach is to call this method during your Activity's 1137 * {@link Activity#onCreate} - see sample 1138 * code below. This method does not immediately perform any I/O or blocking work, 1139 * so is safe to call on your main thread. 1140 * 1141 * <p>Only one NDEF message can be pushed by the currently resumed activity. 1142 * If both {@link #setNdefPushMessage} and 1143 * {@link #setNdefPushMessageCallback} are set, then 1144 * the callback will take priority. 1145 * 1146 * <p>If neither {@link #setNdefPushMessage} or 1147 * {@link #setNdefPushMessageCallback} have been called for your activity, then 1148 * the Android OS may choose to send a default NDEF message on your behalf, 1149 * such as a URI for your application. 1150 * 1151 * <p>If {@link #setNdefPushMessage} is called with a null NDEF message, 1152 * and/or {@link #setNdefPushMessageCallback} is called with a null callback, 1153 * then NDEF push will be completely disabled for the specified activity(s). 1154 * This also disables any default NDEF message the Android OS would have 1155 * otherwise sent on your behalf for those activity(s). 1156 * 1157 * <p>If you want to prevent the Android OS from sending default NDEF 1158 * messages completely (for all activities), you can include a 1159 * {@code <meta-data>} element inside the {@code <application>} 1160 * element of your AndroidManifest.xml file, like this: 1161 * <pre> 1162 * <application ...> 1163 * <meta-data android:name="android.nfc.disable_beam_default" 1164 * android:value="true" /> 1165 * </application></pre> 1166 * 1167 * <p>The API allows for multiple activities to be specified at a time, 1168 * but it is strongly recommended to just register one at a time, 1169 * and to do so during the activity's {@link Activity#onCreate}. For example: 1170 * <pre> 1171 * protected void onCreate(Bundle savedInstanceState) { 1172 * super.onCreate(savedInstanceState); 1173 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1174 * if (nfcAdapter == null) return; // NFC not available on this device 1175 * nfcAdapter.setNdefPushMessage(ndefMessage, this); 1176 * }</pre> 1177 * And that is it. Only one call per activity is necessary. The Android 1178 * OS will automatically release its references to the NDEF message and the 1179 * Activity object when it is destroyed if you follow this pattern. 1180 * 1181 * <p>If your Activity wants to dynamically generate an NDEF message, 1182 * then set a callback using {@link #setNdefPushMessageCallback} instead 1183 * of a static message. 1184 * 1185 * <p class="note">Do not pass in an Activity that has already been through 1186 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1187 * during {@link Activity#onCreate}. 1188 * 1189 * <p class="note">For sending large content such as pictures and songs, 1190 * consider using {@link #setBeamPushUris}, which switches to alternate transports 1191 * such as Bluetooth to achieve a fast transfer rate. 1192 * 1193 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1194 * 1195 * @param message NDEF message to push over NFC, or null to disable 1196 * @param activity activity for which the NDEF message will be pushed 1197 * @param activities optional additional activities, however we strongly recommend 1198 * to only register one at a time, and to do so in that activity's 1199 * {@link Activity#onCreate} 1200 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1201 * @deprecated this feature is deprecated. File sharing can work using other technology like 1202 * Bluetooth. 1203 */ 1204 @java.lang.Deprecated setNdefPushMessage(NdefMessage message, Activity activity, Activity ... activities)1205 public void setNdefPushMessage(NdefMessage message, Activity activity, 1206 Activity ... activities) { 1207 synchronized (NfcAdapter.class) { 1208 if (!sHasNfcFeature) { 1209 throw new UnsupportedOperationException(); 1210 } 1211 if (!sHasBeamFeature) { 1212 return; 1213 } 1214 } 1215 int targetSdkVersion = getSdkVersion(); 1216 try { 1217 if (activity == null) { 1218 throw new NullPointerException("activity cannot be null"); 1219 } 1220 mNfcActivityManager.setNdefPushMessage(activity, message, 0); 1221 for (Activity a : activities) { 1222 if (a == null) { 1223 throw new NullPointerException("activities cannot contain null"); 1224 } 1225 mNfcActivityManager.setNdefPushMessage(a, message, 0); 1226 } 1227 } catch (IllegalStateException e) { 1228 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { 1229 // Less strict on old applications - just log the error 1230 Log.e(TAG, "Cannot call API with Activity that has already " + 1231 "been destroyed", e); 1232 } else { 1233 // Prevent new applications from making this mistake, re-throw 1234 throw(e); 1235 } 1236 } 1237 } 1238 1239 /** 1240 * @hide 1241 */ 1242 @SystemApi setNdefPushMessage(NdefMessage message, Activity activity, int flags)1243 public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) { 1244 synchronized (NfcAdapter.class) { 1245 if (!sHasNfcFeature) { 1246 throw new UnsupportedOperationException(); 1247 } 1248 } 1249 if (activity == null) { 1250 throw new NullPointerException("activity cannot be null"); 1251 } 1252 mNfcActivityManager.setNdefPushMessage(activity, message, flags); 1253 } 1254 1255 /** 1256 * Set a callback that dynamically generates NDEF messages to send using Android Beam (TM). 1257 * 1258 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1259 * but the NDEF message callback can only occur when the 1260 * specified activity(s) are in resumed (foreground) state. The recommended 1261 * approach is to call this method during your Activity's 1262 * {@link Activity#onCreate} - see sample 1263 * code below. This method does not immediately perform any I/O or blocking work, 1264 * so is safe to call on your main thread. 1265 * 1266 * <p>Only one NDEF message can be pushed by the currently resumed activity. 1267 * If both {@link #setNdefPushMessage} and 1268 * {@link #setNdefPushMessageCallback} are set, then 1269 * the callback will take priority. 1270 * 1271 * <p>If neither {@link #setNdefPushMessage} or 1272 * {@link #setNdefPushMessageCallback} have been called for your activity, then 1273 * the Android OS may choose to send a default NDEF message on your behalf, 1274 * such as a URI for your application. 1275 * 1276 * <p>If {@link #setNdefPushMessage} is called with a null NDEF message, 1277 * and/or {@link #setNdefPushMessageCallback} is called with a null callback, 1278 * then NDEF push will be completely disabled for the specified activity(s). 1279 * This also disables any default NDEF message the Android OS would have 1280 * otherwise sent on your behalf for those activity(s). 1281 * 1282 * <p>If you want to prevent the Android OS from sending default NDEF 1283 * messages completely (for all activities), you can include a 1284 * {@code <meta-data>} element inside the {@code <application>} 1285 * element of your AndroidManifest.xml file, like this: 1286 * <pre> 1287 * <application ...> 1288 * <meta-data android:name="android.nfc.disable_beam_default" 1289 * android:value="true" /> 1290 * </application></pre> 1291 * 1292 * <p>The API allows for multiple activities to be specified at a time, 1293 * but it is strongly recommended to just register one at a time, 1294 * and to do so during the activity's {@link Activity#onCreate}. For example: 1295 * <pre> 1296 * protected void onCreate(Bundle savedInstanceState) { 1297 * super.onCreate(savedInstanceState); 1298 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1299 * if (nfcAdapter == null) return; // NFC not available on this device 1300 * nfcAdapter.setNdefPushMessageCallback(callback, this); 1301 * }</pre> 1302 * And that is it. Only one call per activity is necessary. The Android 1303 * OS will automatically release its references to the callback and the 1304 * Activity object when it is destroyed if you follow this pattern. 1305 * 1306 * <p class="note">Do not pass in an Activity that has already been through 1307 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1308 * during {@link Activity#onCreate}. 1309 * <p class="note">For sending large content such as pictures and songs, 1310 * consider using {@link #setBeamPushUris}, which switches to alternate transports 1311 * such as Bluetooth to achieve a fast transfer rate. 1312 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1313 * 1314 * @param callback callback, or null to disable 1315 * @param activity activity for which the NDEF message will be pushed 1316 * @param activities optional additional activities, however we strongly recommend 1317 * to only register one at a time, and to do so in that activity's 1318 * {@link Activity#onCreate} 1319 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1320 * @deprecated this feature is deprecated. File sharing can work using other technology like 1321 * Bluetooth. 1322 */ 1323 @java.lang.Deprecated setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, Activity ... activities)1324 public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, 1325 Activity ... activities) { 1326 synchronized (NfcAdapter.class) { 1327 if (!sHasNfcFeature) { 1328 throw new UnsupportedOperationException(); 1329 } 1330 if (!sHasBeamFeature) { 1331 return; 1332 } 1333 } 1334 int targetSdkVersion = getSdkVersion(); 1335 try { 1336 if (activity == null) { 1337 throw new NullPointerException("activity cannot be null"); 1338 } 1339 mNfcActivityManager.setNdefPushMessageCallback(activity, callback, 0); 1340 for (Activity a : activities) { 1341 if (a == null) { 1342 throw new NullPointerException("activities cannot contain null"); 1343 } 1344 mNfcActivityManager.setNdefPushMessageCallback(a, callback, 0); 1345 } 1346 } catch (IllegalStateException e) { 1347 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { 1348 // Less strict on old applications - just log the error 1349 Log.e(TAG, "Cannot call API with Activity that has already " + 1350 "been destroyed", e); 1351 } else { 1352 // Prevent new applications from making this mistake, re-throw 1353 throw(e); 1354 } 1355 } 1356 } 1357 1358 /** 1359 * @hide 1360 */ 1361 @UnsupportedAppUsage setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, int flags)1362 public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, 1363 int flags) { 1364 if (activity == null) { 1365 throw new NullPointerException("activity cannot be null"); 1366 } 1367 mNfcActivityManager.setNdefPushMessageCallback(activity, callback, flags); 1368 } 1369 1370 /** 1371 * Set a callback on successful Android Beam (TM). 1372 * 1373 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1374 * but the callback can only occur when the 1375 * specified activity(s) are in resumed (foreground) state. The recommended 1376 * approach is to call this method during your Activity's 1377 * {@link Activity#onCreate} - see sample 1378 * code below. This method does not immediately perform any I/O or blocking work, 1379 * so is safe to call on your main thread. 1380 * 1381 * <p>The API allows for multiple activities to be specified at a time, 1382 * but it is strongly recommended to just register one at a time, 1383 * and to do so during the activity's {@link Activity#onCreate}. For example: 1384 * <pre> 1385 * protected void onCreate(Bundle savedInstanceState) { 1386 * super.onCreate(savedInstanceState); 1387 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1388 * if (nfcAdapter == null) return; // NFC not available on this device 1389 * nfcAdapter.setOnNdefPushCompleteCallback(callback, this); 1390 * }</pre> 1391 * And that is it. Only one call per activity is necessary. The Android 1392 * OS will automatically release its references to the callback and the 1393 * Activity object when it is destroyed if you follow this pattern. 1394 * 1395 * <p class="note">Do not pass in an Activity that has already been through 1396 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1397 * during {@link Activity#onCreate}. 1398 * 1399 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1400 * 1401 * @param callback callback, or null to disable 1402 * @param activity activity for which the NDEF message will be pushed 1403 * @param activities optional additional activities, however we strongly recommend 1404 * to only register one at a time, and to do so in that activity's 1405 * {@link Activity#onCreate} 1406 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1407 * @deprecated this feature is deprecated. File sharing can work using other technology like 1408 * Bluetooth. 1409 */ 1410 @java.lang.Deprecated setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, Activity activity, Activity ... activities)1411 public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, 1412 Activity activity, Activity ... activities) { 1413 synchronized (NfcAdapter.class) { 1414 if (!sHasNfcFeature) { 1415 throw new UnsupportedOperationException(); 1416 } 1417 if (!sHasBeamFeature) { 1418 return; 1419 } 1420 } 1421 int targetSdkVersion = getSdkVersion(); 1422 try { 1423 if (activity == null) { 1424 throw new NullPointerException("activity cannot be null"); 1425 } 1426 mNfcActivityManager.setOnNdefPushCompleteCallback(activity, callback); 1427 for (Activity a : activities) { 1428 if (a == null) { 1429 throw new NullPointerException("activities cannot contain null"); 1430 } 1431 mNfcActivityManager.setOnNdefPushCompleteCallback(a, callback); 1432 } 1433 } catch (IllegalStateException e) { 1434 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { 1435 // Less strict on old applications - just log the error 1436 Log.e(TAG, "Cannot call API with Activity that has already " + 1437 "been destroyed", e); 1438 } else { 1439 // Prevent new applications from making this mistake, re-throw 1440 throw(e); 1441 } 1442 } 1443 } 1444 1445 /** 1446 * Enable foreground dispatch to the given Activity. 1447 * 1448 * <p>This will give priority to the foreground activity when 1449 * dispatching a discovered {@link Tag} to an application. 1450 * 1451 * <p>If any IntentFilters are provided to this method they are used to match dispatch Intents 1452 * for both the {@link NfcAdapter#ACTION_NDEF_DISCOVERED} and 1453 * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. Since {@link NfcAdapter#ACTION_TECH_DISCOVERED} 1454 * relies on meta data outside of the IntentFilter matching for that dispatch Intent is handled 1455 * by passing in the tech lists separately. Each first level entry in the tech list represents 1456 * an array of technologies that must all be present to match. If any of the first level sets 1457 * match then the dispatch is routed through the given PendingIntent. In other words, the second 1458 * level is ANDed together and the first level entries are ORed together. 1459 * 1460 * <p>If you pass {@code null} for both the {@code filters} and {@code techLists} parameters 1461 * that acts a wild card and will cause the foreground activity to receive all tags via the 1462 * {@link NfcAdapter#ACTION_TAG_DISCOVERED} intent. 1463 * 1464 * <p>This method must be called from the main thread, and only when the activity is in the 1465 * foreground (resumed). Also, activities must call {@link #disableForegroundDispatch} before 1466 * the completion of their {@link Activity#onPause} callback to disable foreground dispatch 1467 * after it has been enabled. 1468 * 1469 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1470 * 1471 * @param activity the Activity to dispatch to 1472 * @param intent the PendingIntent to start for the dispatch 1473 * @param filters the IntentFilters to override dispatching for, or null to always dispatch 1474 * @param techLists the tech lists used to perform matching for dispatching of the 1475 * {@link NfcAdapter#ACTION_TECH_DISCOVERED} intent 1476 * @throws IllegalStateException if the Activity is not currently in the foreground 1477 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1478 */ enableForegroundDispatch(Activity activity, PendingIntent intent, IntentFilter[] filters, String[][] techLists)1479 public void enableForegroundDispatch(Activity activity, PendingIntent intent, 1480 IntentFilter[] filters, String[][] techLists) { 1481 synchronized (NfcAdapter.class) { 1482 if (!sHasNfcFeature) { 1483 throw new UnsupportedOperationException(); 1484 } 1485 } 1486 if (activity == null || intent == null) { 1487 throw new NullPointerException(); 1488 } 1489 if (!activity.isResumed()) { 1490 throw new IllegalStateException("Foreground dispatch can only be enabled " + 1491 "when your activity is resumed"); 1492 } 1493 try { 1494 TechListParcel parcel = null; 1495 if (techLists != null && techLists.length > 0) { 1496 parcel = new TechListParcel(techLists); 1497 } 1498 ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity, 1499 mForegroundDispatchListener); 1500 sService.setForegroundDispatch(intent, filters, parcel); 1501 } catch (RemoteException e) { 1502 attemptDeadServiceRecovery(e); 1503 } 1504 } 1505 1506 /** 1507 * Disable foreground dispatch to the given activity. 1508 * 1509 * <p>After calling {@link #enableForegroundDispatch}, an activity 1510 * must call this method before its {@link Activity#onPause} callback 1511 * completes. 1512 * 1513 * <p>This method must be called from the main thread. 1514 * 1515 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1516 * 1517 * @param activity the Activity to disable dispatch to 1518 * @throws IllegalStateException if the Activity has already been paused 1519 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1520 */ disableForegroundDispatch(Activity activity)1521 public void disableForegroundDispatch(Activity activity) { 1522 synchronized (NfcAdapter.class) { 1523 if (!sHasNfcFeature) { 1524 throw new UnsupportedOperationException(); 1525 } 1526 } 1527 ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity, 1528 mForegroundDispatchListener); 1529 disableForegroundDispatchInternal(activity, false); 1530 } 1531 1532 OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() { 1533 @Override 1534 public void onPaused(Activity activity) { 1535 disableForegroundDispatchInternal(activity, true); 1536 } 1537 }; 1538 disableForegroundDispatchInternal(Activity activity, boolean force)1539 void disableForegroundDispatchInternal(Activity activity, boolean force) { 1540 try { 1541 sService.setForegroundDispatch(null, null, null); 1542 if (!force && !activity.isResumed()) { 1543 throw new IllegalStateException("You must disable foreground dispatching " + 1544 "while your activity is still resumed"); 1545 } 1546 } catch (RemoteException e) { 1547 attemptDeadServiceRecovery(e); 1548 } 1549 } 1550 1551 /** 1552 * Limit the NFC controller to reader mode while this Activity is in the foreground. 1553 * 1554 * <p>In this mode the NFC controller will only act as an NFC tag reader/writer, 1555 * thus disabling any peer-to-peer (Android Beam) and card-emulation modes of 1556 * the NFC adapter on this device. 1557 * 1558 * <p>Use {@link #FLAG_READER_SKIP_NDEF_CHECK} to prevent the platform from 1559 * performing any NDEF checks in reader mode. Note that this will prevent the 1560 * {@link Ndef} tag technology from being enumerated on the tag, and that 1561 * NDEF-based tag dispatch will not be functional. 1562 * 1563 * <p>For interacting with tags that are emulated on another Android device 1564 * using Android's host-based card-emulation, the recommended flags are 1565 * {@link #FLAG_READER_NFC_A} and {@link #FLAG_READER_SKIP_NDEF_CHECK}. 1566 * 1567 * @param activity the Activity that requests the adapter to be in reader mode 1568 * @param callback the callback to be called when a tag is discovered 1569 * @param flags Flags indicating poll technologies and other optional parameters 1570 * @param extras Additional extras for configuring reader mode. 1571 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1572 */ enableReaderMode(Activity activity, ReaderCallback callback, int flags, Bundle extras)1573 public void enableReaderMode(Activity activity, ReaderCallback callback, int flags, 1574 Bundle extras) { 1575 synchronized (NfcAdapter.class) { 1576 if (!sHasNfcFeature) { 1577 throw new UnsupportedOperationException(); 1578 } 1579 } 1580 mNfcActivityManager.enableReaderMode(activity, callback, flags, extras); 1581 } 1582 1583 /** 1584 * Restore the NFC adapter to normal mode of operation: supporting 1585 * peer-to-peer (Android Beam), card emulation, and polling for 1586 * all supported tag technologies. 1587 * 1588 * @param activity the Activity that currently has reader mode enabled 1589 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1590 */ disableReaderMode(Activity activity)1591 public void disableReaderMode(Activity activity) { 1592 synchronized (NfcAdapter.class) { 1593 if (!sHasNfcFeature) { 1594 throw new UnsupportedOperationException(); 1595 } 1596 } 1597 mNfcActivityManager.disableReaderMode(activity); 1598 } 1599 1600 /** 1601 * Manually invoke Android Beam to share data. 1602 * 1603 * <p>The Android Beam animation is normally only shown when two NFC-capable 1604 * devices come into range. 1605 * By calling this method, an Activity can invoke the Beam animation directly 1606 * even if no other NFC device is in range yet. The Beam animation will then 1607 * prompt the user to tap another NFC-capable device to complete the data 1608 * transfer. 1609 * 1610 * <p>The main advantage of using this method is that it avoids the need for the 1611 * user to tap the screen to complete the transfer, as this method already 1612 * establishes the direction of the transfer and the consent of the user to 1613 * share data. Callers are responsible for making sure that the user has 1614 * consented to sharing data on NFC tap. 1615 * 1616 * <p>Note that to use this method, the passed in Activity must have already 1617 * set data to share over Beam by using method calls such as 1618 * {@link #setNdefPushMessageCallback} or 1619 * {@link #setBeamPushUrisCallback}. 1620 * 1621 * @param activity the current foreground Activity that has registered data to share 1622 * @return whether the Beam animation was successfully invoked 1623 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1624 * @deprecated this feature is deprecated. File sharing can work using other technology like 1625 * Bluetooth. 1626 */ 1627 @java.lang.Deprecated invokeBeam(Activity activity)1628 public boolean invokeBeam(Activity activity) { 1629 synchronized (NfcAdapter.class) { 1630 if (!sHasNfcFeature) { 1631 throw new UnsupportedOperationException(); 1632 } 1633 if (!sHasBeamFeature) { 1634 return false; 1635 } 1636 } 1637 if (activity == null) { 1638 throw new NullPointerException("activity may not be null."); 1639 } 1640 enforceResumed(activity); 1641 try { 1642 sService.invokeBeam(); 1643 return true; 1644 } catch (RemoteException e) { 1645 Log.e(TAG, "invokeBeam: NFC process has died."); 1646 attemptDeadServiceRecovery(e); 1647 return false; 1648 } 1649 } 1650 1651 /** 1652 * @hide 1653 */ invokeBeam(BeamShareData shareData)1654 public boolean invokeBeam(BeamShareData shareData) { 1655 try { 1656 Log.e(TAG, "invokeBeamInternal()"); 1657 sService.invokeBeamInternal(shareData); 1658 return true; 1659 } catch (RemoteException e) { 1660 Log.e(TAG, "invokeBeam: NFC process has died."); 1661 attemptDeadServiceRecovery(e); 1662 return false; 1663 } 1664 } 1665 1666 /** 1667 * Enable NDEF message push over NFC while this Activity is in the foreground. 1668 * 1669 * <p>You must explicitly call this method every time the activity is 1670 * resumed, and you must call {@link #disableForegroundNdefPush} before 1671 * your activity completes {@link Activity#onPause}. 1672 * 1673 * <p>Strongly recommend to use the new {@link #setNdefPushMessage} 1674 * instead: it automatically hooks into your activity life-cycle, 1675 * so you do not need to call enable/disable in your onResume/onPause. 1676 * 1677 * <p>For NDEF push to function properly the other NFC device must 1678 * support either NFC Forum's SNEP (Simple Ndef Exchange Protocol), or 1679 * Android's "com.android.npp" (Ndef Push Protocol). This was optional 1680 * on Gingerbread level Android NFC devices, but SNEP is mandatory on 1681 * Ice-Cream-Sandwich and beyond. 1682 * 1683 * <p>This method must be called from the main thread. 1684 * 1685 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1686 * 1687 * @param activity foreground activity 1688 * @param message a NDEF Message to push over NFC 1689 * @throws IllegalStateException if the activity is not currently in the foreground 1690 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1691 * @deprecated use {@link #setNdefPushMessage} instead 1692 */ 1693 @Deprecated enableForegroundNdefPush(Activity activity, NdefMessage message)1694 public void enableForegroundNdefPush(Activity activity, NdefMessage message) { 1695 synchronized (NfcAdapter.class) { 1696 if (!sHasNfcFeature) { 1697 throw new UnsupportedOperationException(); 1698 } 1699 if (!sHasBeamFeature) { 1700 return; 1701 } 1702 } 1703 if (activity == null || message == null) { 1704 throw new NullPointerException(); 1705 } 1706 enforceResumed(activity); 1707 mNfcActivityManager.setNdefPushMessage(activity, message, 0); 1708 } 1709 1710 /** 1711 * Disable NDEF message push over P2P. 1712 * 1713 * <p>After calling {@link #enableForegroundNdefPush}, an activity 1714 * must call this method before its {@link Activity#onPause} callback 1715 * completes. 1716 * 1717 * <p>Strongly recommend to use the new {@link #setNdefPushMessage} 1718 * instead: it automatically hooks into your activity life-cycle, 1719 * so you do not need to call enable/disable in your onResume/onPause. 1720 * 1721 * <p>This method must be called from the main thread. 1722 * 1723 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1724 * 1725 * @param activity the Foreground activity 1726 * @throws IllegalStateException if the Activity has already been paused 1727 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1728 * @deprecated use {@link #setNdefPushMessage} instead 1729 */ 1730 @Deprecated disableForegroundNdefPush(Activity activity)1731 public void disableForegroundNdefPush(Activity activity) { 1732 synchronized (NfcAdapter.class) { 1733 if (!sHasNfcFeature) { 1734 throw new UnsupportedOperationException(); 1735 } 1736 if (!sHasBeamFeature) { 1737 return; 1738 } 1739 } 1740 if (activity == null) { 1741 throw new NullPointerException(); 1742 } 1743 enforceResumed(activity); 1744 mNfcActivityManager.setNdefPushMessage(activity, null, 0); 1745 mNfcActivityManager.setNdefPushMessageCallback(activity, null, 0); 1746 mNfcActivityManager.setOnNdefPushCompleteCallback(activity, null); 1747 } 1748 1749 /** 1750 * Sets Secure NFC feature. 1751 * <p>This API is for the Settings application. 1752 * @return True if successful 1753 * @hide 1754 */ 1755 @SystemApi 1756 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) enableSecureNfc(boolean enable)1757 public boolean enableSecureNfc(boolean enable) { 1758 if (!sHasNfcFeature) { 1759 throw new UnsupportedOperationException(); 1760 } 1761 try { 1762 return sService.setNfcSecure(enable); 1763 } catch (RemoteException e) { 1764 attemptDeadServiceRecovery(e); 1765 return false; 1766 } 1767 } 1768 1769 /** 1770 * Checks if the device supports Secure NFC functionality. 1771 * 1772 * @return True if device supports Secure NFC, false otherwise 1773 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1774 */ isSecureNfcSupported()1775 public boolean isSecureNfcSupported() { 1776 if (!sHasNfcFeature) { 1777 throw new UnsupportedOperationException(); 1778 } 1779 try { 1780 return sService.deviceSupportsNfcSecure(); 1781 } catch (RemoteException e) { 1782 attemptDeadServiceRecovery(e); 1783 return false; 1784 } 1785 } 1786 1787 /** 1788 * Checks Secure NFC feature is enabled. 1789 * 1790 * @return True if Secure NFC is enabled, false otherwise 1791 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1792 * @throws UnsupportedOperationException if device doesn't support 1793 * Secure NFC functionality. {@link #isSecureNfcSupported} 1794 */ isSecureNfcEnabled()1795 public boolean isSecureNfcEnabled() { 1796 if (!sHasNfcFeature) { 1797 throw new UnsupportedOperationException(); 1798 } 1799 try { 1800 return sService.isNfcSecureEnabled(); 1801 } catch (RemoteException e) { 1802 attemptDeadServiceRecovery(e); 1803 return false; 1804 } 1805 } 1806 1807 /** 1808 * Enable NDEF Push feature. 1809 * <p>This API is for the Settings application. 1810 * @hide 1811 */ 1812 @SystemApi 1813 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) enableNdefPush()1814 public boolean enableNdefPush() { 1815 if (!sHasNfcFeature) { 1816 throw new UnsupportedOperationException(); 1817 } 1818 try { 1819 return sService.enableNdefPush(); 1820 } catch (RemoteException e) { 1821 attemptDeadServiceRecovery(e); 1822 return false; 1823 } 1824 } 1825 1826 /** 1827 * Disable NDEF Push feature. 1828 * <p>This API is for the Settings application. 1829 * @hide 1830 */ 1831 @SystemApi 1832 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) disableNdefPush()1833 public boolean disableNdefPush() { 1834 synchronized (NfcAdapter.class) { 1835 if (!sHasNfcFeature) { 1836 throw new UnsupportedOperationException(); 1837 } 1838 } 1839 try { 1840 return sService.disableNdefPush(); 1841 } catch (RemoteException e) { 1842 attemptDeadServiceRecovery(e); 1843 return false; 1844 } 1845 } 1846 1847 /** 1848 * Return true if the NDEF Push (Android Beam) feature is enabled. 1849 * <p>This function will return true only if both NFC is enabled, and the 1850 * NDEF Push feature is enabled. 1851 * <p>Note that if NFC is enabled but NDEF Push is disabled then this 1852 * device can still <i>receive</i> NDEF messages, it just cannot send them. 1853 * <p>Applications cannot directly toggle the NDEF Push feature, but they 1854 * can request Settings UI allowing the user to toggle NDEF Push using 1855 * <code>startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS))</code> 1856 * <p>Example usage in an Activity that requires NDEF Push: 1857 * <p><pre> 1858 * protected void onResume() { 1859 * super.onResume(); 1860 * if (!nfcAdapter.isEnabled()) { 1861 * startActivity(new Intent(Settings.ACTION_NFC_SETTINGS)); 1862 * } else if (!nfcAdapter.isNdefPushEnabled()) { 1863 * startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS)); 1864 * } 1865 * }</pre> 1866 * 1867 * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS 1868 * @return true if NDEF Push feature is enabled 1869 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1870 * @deprecated this feature is deprecated. File sharing can work using other technology like 1871 * Bluetooth. 1872 */ 1873 @java.lang.Deprecated 1874 isNdefPushEnabled()1875 public boolean isNdefPushEnabled() { 1876 synchronized (NfcAdapter.class) { 1877 if (!sHasNfcFeature) { 1878 throw new UnsupportedOperationException(); 1879 } 1880 if (!sHasBeamFeature) { 1881 return false; 1882 } 1883 } 1884 try { 1885 return sService.isNdefPushEnabled(); 1886 } catch (RemoteException e) { 1887 attemptDeadServiceRecovery(e); 1888 return false; 1889 } 1890 } 1891 1892 /** 1893 * Signals that you are no longer interested in communicating with an NFC tag 1894 * for as long as it remains in range. 1895 * 1896 * All future attempted communication to this tag will fail with {@link IOException}. 1897 * The NFC controller will be put in a low-power polling mode, allowing the device 1898 * to save power in cases where it's "attached" to a tag all the time (e.g. a tag in 1899 * car dock). 1900 * 1901 * Additionally the debounceMs parameter allows you to specify for how long the tag needs 1902 * to have gone out of range, before it will be dispatched again. 1903 * 1904 * Note: the NFC controller typically polls at a pretty slow interval (100 - 500 ms). 1905 * This means that if the tag repeatedly goes in and out of range (for example, in 1906 * case of a flaky connection), and the controller happens to poll every time the 1907 * tag is out of range, it *will* re-dispatch the tag after debounceMs, despite the tag 1908 * having been "in range" during the interval. 1909 * 1910 * Note 2: if a tag with another UID is detected after this API is called, its effect 1911 * will be cancelled; if this tag shows up before the amount of time specified in 1912 * debounceMs, it will be dispatched again. 1913 * 1914 * Note 3: some tags have a random UID, in which case this API won't work reliably. 1915 * 1916 * @param tag the {@link android.nfc.Tag Tag} to ignore. 1917 * @param debounceMs minimum amount of time the tag needs to be out of range before being 1918 * dispatched again. 1919 * @param tagRemovedListener listener to be called when the tag is removed from the field. 1920 * Note that this will only be called if the tag has been out of range 1921 * for at least debounceMs, or if another tag came into range before 1922 * debounceMs. May be null in case you don't want a callback. 1923 * @param handler the {@link android.os.Handler Handler} that will be used for delivering 1924 * the callback. if the handler is null, then the thread used for delivering 1925 * the callback is unspecified. 1926 * @return false if the tag couldn't be found (or has already gone out of range), true otherwise 1927 */ ignore(final Tag tag, int debounceMs, final OnTagRemovedListener tagRemovedListener, final Handler handler)1928 public boolean ignore(final Tag tag, int debounceMs, 1929 final OnTagRemovedListener tagRemovedListener, final Handler handler) { 1930 ITagRemovedCallback.Stub iListener = null; 1931 if (tagRemovedListener != null) { 1932 iListener = new ITagRemovedCallback.Stub() { 1933 @Override 1934 public void onTagRemoved() throws RemoteException { 1935 if (handler != null) { 1936 handler.post(new Runnable() { 1937 @Override 1938 public void run() { 1939 tagRemovedListener.onTagRemoved(); 1940 } 1941 }); 1942 } else { 1943 tagRemovedListener.onTagRemoved(); 1944 } 1945 synchronized (mLock) { 1946 mTagRemovedListener = null; 1947 } 1948 } 1949 }; 1950 } 1951 synchronized (mLock) { 1952 mTagRemovedListener = iListener; 1953 } 1954 try { 1955 return sService.ignore(tag.getServiceHandle(), debounceMs, iListener); 1956 } catch (RemoteException e) { 1957 return false; 1958 } 1959 } 1960 1961 /** 1962 * Inject a mock NFC tag.<p> 1963 * Used for testing purposes. 1964 * <p class="note">Requires the 1965 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. 1966 * @hide 1967 */ dispatch(Tag tag)1968 public void dispatch(Tag tag) { 1969 if (tag == null) { 1970 throw new NullPointerException("tag cannot be null"); 1971 } 1972 try { 1973 sService.dispatch(tag); 1974 } catch (RemoteException e) { 1975 attemptDeadServiceRecovery(e); 1976 } 1977 } 1978 1979 /** 1980 * @hide 1981 */ setP2pModes(int initiatorModes, int targetModes)1982 public void setP2pModes(int initiatorModes, int targetModes) { 1983 try { 1984 sService.setP2pModes(initiatorModes, targetModes); 1985 } catch (RemoteException e) { 1986 attemptDeadServiceRecovery(e); 1987 } 1988 } 1989 1990 /** 1991 * Registers a new NFC unlock handler with the NFC service. 1992 * 1993 * <p />NFC unlock handlers are intended to unlock the keyguard in the presence of a trusted 1994 * NFC device. The handler should return true if it successfully authenticates the user and 1995 * unlocks the keyguard. 1996 * 1997 * <p /> The parameter {@code tagTechnologies} determines which Tag technologies will be polled for 1998 * at the lockscreen. Polling for less tag technologies reduces latency, and so it is 1999 * strongly recommended to only provide the Tag technologies that the handler is expected to 2000 * receive. There must be at least one tag technology provided, otherwise the unlock handler 2001 * is ignored. 2002 * 2003 * @hide 2004 */ 2005 @SystemApi 2006 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) addNfcUnlockHandler(final NfcUnlockHandler unlockHandler, String[] tagTechnologies)2007 public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler, 2008 String[] tagTechnologies) { 2009 synchronized (NfcAdapter.class) { 2010 if (!sHasNfcFeature) { 2011 throw new UnsupportedOperationException(); 2012 } 2013 } 2014 // If there are no tag technologies, don't bother adding unlock handler 2015 if (tagTechnologies.length == 0) { 2016 return false; 2017 } 2018 2019 try { 2020 synchronized (mLock) { 2021 if (mNfcUnlockHandlers.containsKey(unlockHandler)) { 2022 // update the tag technologies 2023 sService.removeNfcUnlockHandler(mNfcUnlockHandlers.get(unlockHandler)); 2024 mNfcUnlockHandlers.remove(unlockHandler); 2025 } 2026 2027 INfcUnlockHandler.Stub iHandler = new INfcUnlockHandler.Stub() { 2028 @Override 2029 public boolean onUnlockAttempted(Tag tag) throws RemoteException { 2030 return unlockHandler.onUnlockAttempted(tag); 2031 } 2032 }; 2033 2034 sService.addNfcUnlockHandler(iHandler, 2035 Tag.getTechCodesFromStrings(tagTechnologies)); 2036 mNfcUnlockHandlers.put(unlockHandler, iHandler); 2037 } 2038 } catch (RemoteException e) { 2039 attemptDeadServiceRecovery(e); 2040 return false; 2041 } catch (IllegalArgumentException e) { 2042 Log.e(TAG, "Unable to register LockscreenDispatch", e); 2043 return false; 2044 } 2045 2046 return true; 2047 } 2048 2049 /** 2050 * Removes a previously registered unlock handler. Also removes the tag technologies 2051 * associated with the removed unlock handler. 2052 * 2053 * @hide 2054 */ 2055 @SystemApi 2056 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) removeNfcUnlockHandler(NfcUnlockHandler unlockHandler)2057 public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) { 2058 synchronized (NfcAdapter.class) { 2059 if (!sHasNfcFeature) { 2060 throw new UnsupportedOperationException(); 2061 } 2062 } 2063 try { 2064 synchronized (mLock) { 2065 if (mNfcUnlockHandlers.containsKey(unlockHandler)) { 2066 sService.removeNfcUnlockHandler(mNfcUnlockHandlers.remove(unlockHandler)); 2067 } 2068 2069 return true; 2070 } 2071 } catch (RemoteException e) { 2072 attemptDeadServiceRecovery(e); 2073 return false; 2074 } 2075 } 2076 2077 /** 2078 * @hide 2079 */ 2080 @UnsupportedAppUsage getNfcAdapterExtrasInterface()2081 public INfcAdapterExtras getNfcAdapterExtrasInterface() { 2082 if (mContext == null) { 2083 throw new UnsupportedOperationException("You need a context on NfcAdapter to use the " 2084 + " NFC extras APIs"); 2085 } 2086 try { 2087 return sService.getNfcAdapterExtrasInterface(mContext.getPackageName()); 2088 } catch (RemoteException e) { 2089 attemptDeadServiceRecovery(e); 2090 return null; 2091 } 2092 } 2093 enforceResumed(Activity activity)2094 void enforceResumed(Activity activity) { 2095 if (!activity.isResumed()) { 2096 throw new IllegalStateException("API cannot be called while activity is paused"); 2097 } 2098 } 2099 getSdkVersion()2100 int getSdkVersion() { 2101 if (mContext == null) { 2102 return android.os.Build.VERSION_CODES.GINGERBREAD; // best guess 2103 } else { 2104 return mContext.getApplicationInfo().targetSdkVersion; 2105 } 2106 } 2107 } 2108