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 681 if (getServiceInterface() == null) { 682 // NFC is not available 683 return null; 684 } 685 686 /* use getSystemService() for consistency */ 687 NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE); 688 if (manager == null) { 689 // NFC not available 690 return null; 691 } 692 return manager.getDefaultAdapter(); 693 } 694 695 /** 696 * Legacy NfcAdapter getter, always use {@link #getDefaultAdapter(Context)} instead.<p> 697 * This method was deprecated at API level 10 (Gingerbread MR1) because a context is required 698 * for many NFC API methods. Those methods will fail when called on an NfcAdapter 699 * object created from this method.<p> 700 * @deprecated use {@link #getDefaultAdapter(Context)} 701 * @hide 702 */ 703 @Deprecated 704 @UnsupportedAppUsage getDefaultAdapter()705 public static NfcAdapter getDefaultAdapter() { 706 // introduced in API version 9 (GB 2.3) 707 // deprecated in API version 10 (GB 2.3.3) 708 // removed from public API in version 16 (ICS MR2) 709 // should maintain as a hidden API for binary compatibility for a little longer 710 Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " + 711 "NfcAdapter.getDefaultAdapter(Context) instead", new Exception()); 712 713 return NfcAdapter.getNfcAdapter(null); 714 } 715 NfcAdapter(Context context)716 NfcAdapter(Context context) { 717 mContext = context; 718 mNfcActivityManager = new NfcActivityManager(this); 719 mNfcUnlockHandlers = new HashMap<NfcUnlockHandler, INfcUnlockHandler>(); 720 mTagRemovedListener = null; 721 mLock = new Object(); 722 } 723 724 /** 725 * @hide 726 */ 727 @UnsupportedAppUsage getContext()728 public Context getContext() { 729 return mContext; 730 } 731 732 /** 733 * Returns the binder interface to the service. 734 * @hide 735 */ 736 @UnsupportedAppUsage getService()737 public INfcAdapter getService() { 738 isEnabled(); // NOP call to recover sService if it is stale 739 return sService; 740 } 741 742 /** 743 * Returns the binder interface to the tag service. 744 * @hide 745 */ getTagService()746 public INfcTag getTagService() { 747 isEnabled(); // NOP call to recover sTagService if it is stale 748 return sTagService; 749 } 750 751 /** 752 * Returns the binder interface to the card emulation service. 753 * @hide 754 */ getCardEmulationService()755 public INfcCardEmulation getCardEmulationService() { 756 isEnabled(); 757 return sCardEmulationService; 758 } 759 760 /** 761 * Returns the binder interface to the NFC-F card emulation service. 762 * @hide 763 */ getNfcFCardEmulationService()764 public INfcFCardEmulation getNfcFCardEmulationService() { 765 isEnabled(); 766 return sNfcFCardEmulationService; 767 } 768 769 /** 770 * Returns the binder interface to the NFC-DTA test interface. 771 * @hide 772 */ getNfcDtaInterface()773 public INfcDta getNfcDtaInterface() { 774 if (mContext == null) { 775 throw new UnsupportedOperationException("You need a context on NfcAdapter to use the " 776 + " NFC extras APIs"); 777 } 778 try { 779 return sService.getNfcDtaInterface(mContext.getPackageName()); 780 } catch (RemoteException e) { 781 attemptDeadServiceRecovery(e); 782 return null; 783 } 784 } 785 786 /** 787 * NFC service dead - attempt best effort recovery 788 * @hide 789 */ 790 @UnsupportedAppUsage attemptDeadServiceRecovery(Exception e)791 public void attemptDeadServiceRecovery(Exception e) { 792 Log.e(TAG, "NFC service dead - attempting to recover", e); 793 INfcAdapter service = getServiceInterface(); 794 if (service == null) { 795 Log.e(TAG, "could not retrieve NFC service during service recovery"); 796 // nothing more can be done now, sService is still stale, we'll hit 797 // this recovery path again later 798 return; 799 } 800 // assigning to sService is not thread-safe, but this is best-effort code 801 // and on a well-behaved system should never happen 802 sService = service; 803 try { 804 sTagService = service.getNfcTagInterface(); 805 } catch (RemoteException ee) { 806 Log.e(TAG, "could not retrieve NFC tag service during service recovery"); 807 // nothing more can be done now, sService is still stale, we'll hit 808 // this recovery path again later 809 return; 810 } 811 812 try { 813 sCardEmulationService = service.getNfcCardEmulationInterface(); 814 } catch (RemoteException ee) { 815 Log.e(TAG, "could not retrieve NFC card emulation service during service recovery"); 816 } 817 818 try { 819 sNfcFCardEmulationService = service.getNfcFCardEmulationInterface(); 820 } catch (RemoteException ee) { 821 Log.e(TAG, "could not retrieve NFC-F card emulation service during service recovery"); 822 } 823 824 return; 825 } 826 827 /** 828 * Return true if this NFC Adapter has any features enabled. 829 * 830 * <p>If this method returns false, the NFC hardware is guaranteed not to 831 * generate or respond to any NFC communication over its NFC radio. 832 * <p>Applications can use this to check if NFC is enabled. Applications 833 * can request Settings UI allowing the user to toggle NFC using: 834 * <p><pre>startActivity(new Intent(Settings.ACTION_NFC_SETTINGS))</pre> 835 * 836 * @see android.provider.Settings#ACTION_NFC_SETTINGS 837 * @return true if this NFC Adapter has any features enabled 838 */ isEnabled()839 public boolean isEnabled() { 840 try { 841 return sService.getState() == STATE_ON; 842 } catch (RemoteException e) { 843 attemptDeadServiceRecovery(e); 844 return false; 845 } 846 } 847 848 /** 849 * Return the state of this NFC Adapter. 850 * 851 * <p>Returns one of {@link #STATE_ON}, {@link #STATE_TURNING_ON}, 852 * {@link #STATE_OFF}, {@link #STATE_TURNING_OFF}. 853 * 854 * <p>{@link #isEnabled()} is equivalent to 855 * <code>{@link #getAdapterState()} == {@link #STATE_ON}</code> 856 * 857 * @return the current state of this NFC adapter 858 * 859 * @hide 860 */ 861 @UnsupportedAppUsage getAdapterState()862 public int getAdapterState() { 863 try { 864 return sService.getState(); 865 } catch (RemoteException e) { 866 attemptDeadServiceRecovery(e); 867 return NfcAdapter.STATE_OFF; 868 } 869 } 870 871 /** 872 * Enable NFC hardware. 873 * 874 * <p>This call is asynchronous. Listen for 875 * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the 876 * operation is complete. 877 * 878 * <p>If this returns true, then either NFC is already on, or 879 * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent 880 * to indicate a state transition. If this returns false, then 881 * there is some problem that prevents an attempt to turn 882 * NFC on (for example we are in airplane mode and NFC is not 883 * toggleable in airplane mode on this platform). 884 * 885 * @hide 886 */ 887 @SystemApi 888 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) enable()889 public boolean enable() { 890 try { 891 return sService.enable(); 892 } catch (RemoteException e) { 893 attemptDeadServiceRecovery(e); 894 return false; 895 } 896 } 897 898 /** 899 * Disable NFC hardware. 900 * 901 * <p>No NFC features will work after this call, and the hardware 902 * will not perform or respond to any NFC communication. 903 * 904 * <p>This call is asynchronous. Listen for 905 * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the 906 * operation is complete. 907 * 908 * <p>If this returns true, then either NFC is already off, or 909 * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent 910 * to indicate a state transition. If this returns false, then 911 * there is some problem that prevents an attempt to turn 912 * NFC off. 913 * 914 * @hide 915 */ 916 @SystemApi 917 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) disable()918 public boolean disable() { 919 try { 920 return sService.disable(true); 921 } catch (RemoteException e) { 922 attemptDeadServiceRecovery(e); 923 return false; 924 } 925 } 926 927 /** 928 * Disable NFC hardware. 929 * @hide 930 */ 931 @SystemApi 932 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) disable(boolean persist)933 public boolean disable(boolean persist) { 934 try { 935 return sService.disable(persist); 936 } catch (RemoteException e) { 937 attemptDeadServiceRecovery(e); 938 return false; 939 } 940 } 941 942 /** 943 * Pauses polling for a {@code timeoutInMs} millis. If polling must be resumed before timeout, 944 * use {@link #resumePolling()}. 945 * @hide 946 */ pausePolling(int timeoutInMs)947 public void pausePolling(int timeoutInMs) { 948 try { 949 sService.pausePolling(timeoutInMs); 950 } catch (RemoteException e) { 951 attemptDeadServiceRecovery(e); 952 } 953 } 954 955 /** 956 * Resumes default polling for the current device state if polling is paused. Calling 957 * this while polling is not paused is a no-op. 958 * 959 * @hide 960 */ resumePolling()961 public void resumePolling() { 962 try { 963 sService.resumePolling(); 964 } catch (RemoteException e) { 965 attemptDeadServiceRecovery(e); 966 } 967 } 968 969 /** 970 * Set one or more {@link Uri}s to send using Android Beam (TM). Every 971 * Uri you provide must have either scheme 'file' or scheme 'content'. 972 * 973 * <p>For the data provided through this method, Android Beam tries to 974 * switch to alternate transports such as Bluetooth to achieve a fast 975 * transfer speed. Hence this method is very suitable 976 * for transferring large files such as pictures or songs. 977 * 978 * <p>The receiving side will store the content of each Uri in 979 * a file and present a notification to the user to open the file 980 * with a {@link android.content.Intent} with action 981 * {@link android.content.Intent#ACTION_VIEW}. 982 * If multiple URIs are sent, the {@link android.content.Intent} will refer 983 * to the first of the stored files. 984 * 985 * <p>This method may be called at any time before {@link Activity#onDestroy}, 986 * but the URI(s) are only made available for Android Beam when the 987 * specified activity(s) are in resumed (foreground) state. The recommended 988 * approach is to call this method during your Activity's 989 * {@link Activity#onCreate} - see sample 990 * code below. This method does not immediately perform any I/O or blocking work, 991 * so is safe to call on your main thread. 992 * 993 * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback} 994 * have priority over both {@link #setNdefPushMessage} and 995 * {@link #setNdefPushMessageCallback}. 996 * 997 * <p>If {@link #setBeamPushUris} is called with a null Uri array, 998 * and/or {@link #setBeamPushUrisCallback} is called with a null callback, 999 * then the Uri push will be completely disabled for the specified activity(s). 1000 * 1001 * <p>Code example: 1002 * <pre> 1003 * protected void onCreate(Bundle savedInstanceState) { 1004 * super.onCreate(savedInstanceState); 1005 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1006 * if (nfcAdapter == null) return; // NFC not available on this device 1007 * nfcAdapter.setBeamPushUris(new Uri[] {uri1, uri2}, this); 1008 * }</pre> 1009 * And that is it. Only one call per activity is necessary. The Android 1010 * OS will automatically release its references to the Uri(s) and the 1011 * Activity object when it is destroyed if you follow this pattern. 1012 * 1013 * <p>If your Activity wants to dynamically supply Uri(s), 1014 * then set a callback using {@link #setBeamPushUrisCallback} instead 1015 * of using this method. 1016 * 1017 * <p class="note">Do not pass in an Activity that has already been through 1018 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1019 * during {@link Activity#onCreate}. 1020 * 1021 * <p class="note">If this device does not support alternate transports 1022 * such as Bluetooth or WiFI, calling this method does nothing. 1023 * 1024 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1025 * 1026 * @param uris an array of Uri(s) to push over Android Beam 1027 * @param activity activity for which the Uri(s) will be pushed 1028 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1029 * @deprecated this feature is deprecated. File sharing can work using other technology like 1030 * Bluetooth. 1031 */ 1032 @java.lang.Deprecated setBeamPushUris(Uri[] uris, Activity activity)1033 public void setBeamPushUris(Uri[] uris, Activity activity) { 1034 synchronized (NfcAdapter.class) { 1035 if (!sHasNfcFeature) { 1036 throw new UnsupportedOperationException(); 1037 } 1038 if (!sHasBeamFeature) { 1039 return; 1040 } 1041 } 1042 if (activity == null) { 1043 throw new NullPointerException("activity cannot be null"); 1044 } 1045 if (uris != null) { 1046 for (Uri uri : uris) { 1047 if (uri == null) throw new NullPointerException("Uri not " + 1048 "allowed to be null"); 1049 String scheme = uri.getScheme(); 1050 if (scheme == null || (!scheme.equalsIgnoreCase("file") && 1051 !scheme.equalsIgnoreCase("content"))) { 1052 throw new IllegalArgumentException("URI needs to have " + 1053 "either scheme file or scheme content"); 1054 } 1055 } 1056 } 1057 mNfcActivityManager.setNdefPushContentUri(activity, uris); 1058 } 1059 1060 /** 1061 * Set a callback that will dynamically generate one or more {@link Uri}s 1062 * to send using Android Beam (TM). Every Uri the callback provides 1063 * must have either scheme 'file' or scheme 'content'. 1064 * 1065 * <p>For the data provided through this callback, Android Beam tries to 1066 * switch to alternate transports such as Bluetooth to achieve a fast 1067 * transfer speed. Hence this method is very suitable 1068 * for transferring large files such as pictures or songs. 1069 * 1070 * <p>The receiving side will store the content of each Uri in 1071 * a file and present a notification to the user to open the file 1072 * with a {@link android.content.Intent} with action 1073 * {@link android.content.Intent#ACTION_VIEW}. 1074 * If multiple URIs are sent, the {@link android.content.Intent} will refer 1075 * to the first of the stored files. 1076 * 1077 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1078 * but the URI(s) are only made available for Android Beam when the 1079 * specified activity(s) are in resumed (foreground) state. The recommended 1080 * approach is to call this method during your Activity's 1081 * {@link Activity#onCreate} - see sample 1082 * code below. This method does not immediately perform any I/O or blocking work, 1083 * so is safe to call on your main thread. 1084 * 1085 * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback} 1086 * have priority over both {@link #setNdefPushMessage} and 1087 * {@link #setNdefPushMessageCallback}. 1088 * 1089 * <p>If {@link #setBeamPushUris} is called with a null Uri array, 1090 * and/or {@link #setBeamPushUrisCallback} is called with a null callback, 1091 * then the Uri push will be completely disabled for the specified activity(s). 1092 * 1093 * <p>Code example: 1094 * <pre> 1095 * protected void onCreate(Bundle savedInstanceState) { 1096 * super.onCreate(savedInstanceState); 1097 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1098 * if (nfcAdapter == null) return; // NFC not available on this device 1099 * nfcAdapter.setBeamPushUrisCallback(callback, this); 1100 * }</pre> 1101 * And that is it. Only one call per activity is necessary. The Android 1102 * OS will automatically release its references to the Uri(s) and the 1103 * Activity object when it is destroyed if you follow this pattern. 1104 * 1105 * <p class="note">Do not pass in an Activity that has already been through 1106 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1107 * during {@link Activity#onCreate}. 1108 * 1109 * <p class="note">If this device does not support alternate transports 1110 * such as Bluetooth or WiFI, calling this method does nothing. 1111 * 1112 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1113 * 1114 * @param callback callback, or null to disable 1115 * @param activity activity for which the Uri(s) will be pushed 1116 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1117 * @deprecated this feature is deprecated. File sharing can work using other technology like 1118 * Bluetooth. 1119 */ 1120 @java.lang.Deprecated setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity)1121 public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) { 1122 synchronized (NfcAdapter.class) { 1123 if (!sHasNfcFeature) { 1124 throw new UnsupportedOperationException(); 1125 } 1126 if (!sHasBeamFeature) { 1127 return; 1128 } 1129 } 1130 if (activity == null) { 1131 throw new NullPointerException("activity cannot be null"); 1132 } 1133 mNfcActivityManager.setNdefPushContentUriCallback(activity, callback); 1134 } 1135 1136 /** 1137 * Set a static {@link NdefMessage} to send using Android Beam (TM). 1138 * 1139 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1140 * but the NDEF message is only made available for NDEF push when the 1141 * specified activity(s) are in resumed (foreground) state. The recommended 1142 * approach is to call this method during your Activity's 1143 * {@link Activity#onCreate} - see sample 1144 * code below. This method does not immediately perform any I/O or blocking work, 1145 * so is safe to call on your main thread. 1146 * 1147 * <p>Only one NDEF message can be pushed by the currently resumed activity. 1148 * If both {@link #setNdefPushMessage} and 1149 * {@link #setNdefPushMessageCallback} are set, then 1150 * the callback will take priority. 1151 * 1152 * <p>If neither {@link #setNdefPushMessage} or 1153 * {@link #setNdefPushMessageCallback} have been called for your activity, then 1154 * the Android OS may choose to send a default NDEF message on your behalf, 1155 * such as a URI for your application. 1156 * 1157 * <p>If {@link #setNdefPushMessage} is called with a null NDEF message, 1158 * and/or {@link #setNdefPushMessageCallback} is called with a null callback, 1159 * then NDEF push will be completely disabled for the specified activity(s). 1160 * This also disables any default NDEF message the Android OS would have 1161 * otherwise sent on your behalf for those activity(s). 1162 * 1163 * <p>If you want to prevent the Android OS from sending default NDEF 1164 * messages completely (for all activities), you can include a 1165 * {@code <meta-data>} element inside the {@code <application>} 1166 * element of your AndroidManifest.xml file, like this: 1167 * <pre> 1168 * <application ...> 1169 * <meta-data android:name="android.nfc.disable_beam_default" 1170 * android:value="true" /> 1171 * </application></pre> 1172 * 1173 * <p>The API allows for multiple activities to be specified at a time, 1174 * but it is strongly recommended to just register one at a time, 1175 * and to do so during the activity's {@link Activity#onCreate}. For example: 1176 * <pre> 1177 * protected void onCreate(Bundle savedInstanceState) { 1178 * super.onCreate(savedInstanceState); 1179 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1180 * if (nfcAdapter == null) return; // NFC not available on this device 1181 * nfcAdapter.setNdefPushMessage(ndefMessage, this); 1182 * }</pre> 1183 * And that is it. Only one call per activity is necessary. The Android 1184 * OS will automatically release its references to the NDEF message and the 1185 * Activity object when it is destroyed if you follow this pattern. 1186 * 1187 * <p>If your Activity wants to dynamically generate an NDEF message, 1188 * then set a callback using {@link #setNdefPushMessageCallback} instead 1189 * of a static message. 1190 * 1191 * <p class="note">Do not pass in an Activity that has already been through 1192 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1193 * during {@link Activity#onCreate}. 1194 * 1195 * <p class="note">For sending large content such as pictures and songs, 1196 * consider using {@link #setBeamPushUris}, which switches to alternate transports 1197 * such as Bluetooth to achieve a fast transfer rate. 1198 * 1199 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1200 * 1201 * @param message NDEF message to push over NFC, or null to disable 1202 * @param activity activity for which the NDEF message will be pushed 1203 * @param activities optional additional activities, however we strongly recommend 1204 * to only register one at a time, and to do so in that activity's 1205 * {@link Activity#onCreate} 1206 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1207 * @deprecated this feature is deprecated. File sharing can work using other technology like 1208 * Bluetooth. 1209 */ 1210 @java.lang.Deprecated setNdefPushMessage(NdefMessage message, Activity activity, Activity ... activities)1211 public void setNdefPushMessage(NdefMessage message, Activity activity, 1212 Activity ... activities) { 1213 synchronized (NfcAdapter.class) { 1214 if (!sHasNfcFeature) { 1215 throw new UnsupportedOperationException(); 1216 } 1217 if (!sHasBeamFeature) { 1218 return; 1219 } 1220 } 1221 int targetSdkVersion = getSdkVersion(); 1222 try { 1223 if (activity == null) { 1224 throw new NullPointerException("activity cannot be null"); 1225 } 1226 mNfcActivityManager.setNdefPushMessage(activity, message, 0); 1227 for (Activity a : activities) { 1228 if (a == null) { 1229 throw new NullPointerException("activities cannot contain null"); 1230 } 1231 mNfcActivityManager.setNdefPushMessage(a, message, 0); 1232 } 1233 } catch (IllegalStateException e) { 1234 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { 1235 // Less strict on old applications - just log the error 1236 Log.e(TAG, "Cannot call API with Activity that has already " + 1237 "been destroyed", e); 1238 } else { 1239 // Prevent new applications from making this mistake, re-throw 1240 throw(e); 1241 } 1242 } 1243 } 1244 1245 /** 1246 * @hide 1247 */ 1248 @SystemApi setNdefPushMessage(NdefMessage message, Activity activity, int flags)1249 public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) { 1250 synchronized (NfcAdapter.class) { 1251 if (!sHasNfcFeature) { 1252 throw new UnsupportedOperationException(); 1253 } 1254 } 1255 if (activity == null) { 1256 throw new NullPointerException("activity cannot be null"); 1257 } 1258 mNfcActivityManager.setNdefPushMessage(activity, message, flags); 1259 } 1260 1261 /** 1262 * Set a callback that dynamically generates NDEF messages to send using Android Beam (TM). 1263 * 1264 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1265 * but the NDEF message callback can only occur when the 1266 * specified activity(s) are in resumed (foreground) state. The recommended 1267 * approach is to call this method during your Activity's 1268 * {@link Activity#onCreate} - see sample 1269 * code below. This method does not immediately perform any I/O or blocking work, 1270 * so is safe to call on your main thread. 1271 * 1272 * <p>Only one NDEF message can be pushed by the currently resumed activity. 1273 * If both {@link #setNdefPushMessage} and 1274 * {@link #setNdefPushMessageCallback} are set, then 1275 * the callback will take priority. 1276 * 1277 * <p>If neither {@link #setNdefPushMessage} or 1278 * {@link #setNdefPushMessageCallback} have been called for your activity, then 1279 * the Android OS may choose to send a default NDEF message on your behalf, 1280 * such as a URI for your application. 1281 * 1282 * <p>If {@link #setNdefPushMessage} is called with a null NDEF message, 1283 * and/or {@link #setNdefPushMessageCallback} is called with a null callback, 1284 * then NDEF push will be completely disabled for the specified activity(s). 1285 * This also disables any default NDEF message the Android OS would have 1286 * otherwise sent on your behalf for those activity(s). 1287 * 1288 * <p>If you want to prevent the Android OS from sending default NDEF 1289 * messages completely (for all activities), you can include a 1290 * {@code <meta-data>} element inside the {@code <application>} 1291 * element of your AndroidManifest.xml file, like this: 1292 * <pre> 1293 * <application ...> 1294 * <meta-data android:name="android.nfc.disable_beam_default" 1295 * android:value="true" /> 1296 * </application></pre> 1297 * 1298 * <p>The API allows for multiple activities to be specified at a time, 1299 * but it is strongly recommended to just register one at a time, 1300 * and to do so during the activity's {@link Activity#onCreate}. For example: 1301 * <pre> 1302 * protected void onCreate(Bundle savedInstanceState) { 1303 * super.onCreate(savedInstanceState); 1304 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1305 * if (nfcAdapter == null) return; // NFC not available on this device 1306 * nfcAdapter.setNdefPushMessageCallback(callback, this); 1307 * }</pre> 1308 * And that is it. Only one call per activity is necessary. The Android 1309 * OS will automatically release its references to the callback and the 1310 * Activity object when it is destroyed if you follow this pattern. 1311 * 1312 * <p class="note">Do not pass in an Activity that has already been through 1313 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1314 * during {@link Activity#onCreate}. 1315 * <p class="note">For sending large content such as pictures and songs, 1316 * consider using {@link #setBeamPushUris}, which switches to alternate transports 1317 * such as Bluetooth to achieve a fast transfer rate. 1318 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1319 * 1320 * @param callback callback, or null to disable 1321 * @param activity activity for which the NDEF message will be pushed 1322 * @param activities optional additional activities, however we strongly recommend 1323 * to only register one at a time, and to do so in that activity's 1324 * {@link Activity#onCreate} 1325 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1326 * @deprecated this feature is deprecated. File sharing can work using other technology like 1327 * Bluetooth. 1328 */ 1329 @java.lang.Deprecated setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, Activity ... activities)1330 public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, 1331 Activity ... activities) { 1332 synchronized (NfcAdapter.class) { 1333 if (!sHasNfcFeature) { 1334 throw new UnsupportedOperationException(); 1335 } 1336 if (!sHasBeamFeature) { 1337 return; 1338 } 1339 } 1340 int targetSdkVersion = getSdkVersion(); 1341 try { 1342 if (activity == null) { 1343 throw new NullPointerException("activity cannot be null"); 1344 } 1345 mNfcActivityManager.setNdefPushMessageCallback(activity, callback, 0); 1346 for (Activity a : activities) { 1347 if (a == null) { 1348 throw new NullPointerException("activities cannot contain null"); 1349 } 1350 mNfcActivityManager.setNdefPushMessageCallback(a, callback, 0); 1351 } 1352 } catch (IllegalStateException e) { 1353 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { 1354 // Less strict on old applications - just log the error 1355 Log.e(TAG, "Cannot call API with Activity that has already " + 1356 "been destroyed", e); 1357 } else { 1358 // Prevent new applications from making this mistake, re-throw 1359 throw(e); 1360 } 1361 } 1362 } 1363 1364 /** 1365 * @hide 1366 */ 1367 @UnsupportedAppUsage setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, int flags)1368 public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, 1369 int flags) { 1370 if (activity == null) { 1371 throw new NullPointerException("activity cannot be null"); 1372 } 1373 mNfcActivityManager.setNdefPushMessageCallback(activity, callback, flags); 1374 } 1375 1376 /** 1377 * Set a callback on successful Android Beam (TM). 1378 * 1379 * <p>This method may be called at any time before {@link Activity#onDestroy}, 1380 * but the callback can only occur when the 1381 * specified activity(s) are in resumed (foreground) state. The recommended 1382 * approach is to call this method during your Activity's 1383 * {@link Activity#onCreate} - see sample 1384 * code below. This method does not immediately perform any I/O or blocking work, 1385 * so is safe to call on your main thread. 1386 * 1387 * <p>The API allows for multiple activities to be specified at a time, 1388 * but it is strongly recommended to just register one at a time, 1389 * and to do so during the activity's {@link Activity#onCreate}. For example: 1390 * <pre> 1391 * protected void onCreate(Bundle savedInstanceState) { 1392 * super.onCreate(savedInstanceState); 1393 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 1394 * if (nfcAdapter == null) return; // NFC not available on this device 1395 * nfcAdapter.setOnNdefPushCompleteCallback(callback, this); 1396 * }</pre> 1397 * And that is it. Only one call per activity is necessary. The Android 1398 * OS will automatically release its references to the callback and the 1399 * Activity object when it is destroyed if you follow this pattern. 1400 * 1401 * <p class="note">Do not pass in an Activity that has already been through 1402 * {@link Activity#onDestroy}. This is guaranteed if you call this API 1403 * during {@link Activity#onCreate}. 1404 * 1405 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1406 * 1407 * @param callback callback, or null to disable 1408 * @param activity activity for which the NDEF message will be pushed 1409 * @param activities optional additional activities, however we strongly recommend 1410 * to only register one at a time, and to do so in that activity's 1411 * {@link Activity#onCreate} 1412 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1413 * @deprecated this feature is deprecated. File sharing can work using other technology like 1414 * Bluetooth. 1415 */ 1416 @java.lang.Deprecated setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, Activity activity, Activity ... activities)1417 public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, 1418 Activity activity, Activity ... activities) { 1419 synchronized (NfcAdapter.class) { 1420 if (!sHasNfcFeature) { 1421 throw new UnsupportedOperationException(); 1422 } 1423 if (!sHasBeamFeature) { 1424 return; 1425 } 1426 } 1427 int targetSdkVersion = getSdkVersion(); 1428 try { 1429 if (activity == null) { 1430 throw new NullPointerException("activity cannot be null"); 1431 } 1432 mNfcActivityManager.setOnNdefPushCompleteCallback(activity, callback); 1433 for (Activity a : activities) { 1434 if (a == null) { 1435 throw new NullPointerException("activities cannot contain null"); 1436 } 1437 mNfcActivityManager.setOnNdefPushCompleteCallback(a, callback); 1438 } 1439 } catch (IllegalStateException e) { 1440 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { 1441 // Less strict on old applications - just log the error 1442 Log.e(TAG, "Cannot call API with Activity that has already " + 1443 "been destroyed", e); 1444 } else { 1445 // Prevent new applications from making this mistake, re-throw 1446 throw(e); 1447 } 1448 } 1449 } 1450 1451 /** 1452 * Enable foreground dispatch to the given Activity. 1453 * 1454 * <p>This will give priority to the foreground activity when 1455 * dispatching a discovered {@link Tag} to an application. 1456 * 1457 * <p>If any IntentFilters are provided to this method they are used to match dispatch Intents 1458 * for both the {@link NfcAdapter#ACTION_NDEF_DISCOVERED} and 1459 * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. Since {@link NfcAdapter#ACTION_TECH_DISCOVERED} 1460 * relies on meta data outside of the IntentFilter matching for that dispatch Intent is handled 1461 * by passing in the tech lists separately. Each first level entry in the tech list represents 1462 * an array of technologies that must all be present to match. If any of the first level sets 1463 * match then the dispatch is routed through the given PendingIntent. In other words, the second 1464 * level is ANDed together and the first level entries are ORed together. 1465 * 1466 * <p>If you pass {@code null} for both the {@code filters} and {@code techLists} parameters 1467 * that acts a wild card and will cause the foreground activity to receive all tags via the 1468 * {@link NfcAdapter#ACTION_TAG_DISCOVERED} intent. 1469 * 1470 * <p>This method must be called from the main thread, and only when the activity is in the 1471 * foreground (resumed). Also, activities must call {@link #disableForegroundDispatch} before 1472 * the completion of their {@link Activity#onPause} callback to disable foreground dispatch 1473 * after it has been enabled. 1474 * 1475 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1476 * 1477 * @param activity the Activity to dispatch to 1478 * @param intent the PendingIntent to start for the dispatch 1479 * @param filters the IntentFilters to override dispatching for, or null to always dispatch 1480 * @param techLists the tech lists used to perform matching for dispatching of the 1481 * {@link NfcAdapter#ACTION_TECH_DISCOVERED} intent 1482 * @throws IllegalStateException if the Activity is not currently in the foreground 1483 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1484 */ enableForegroundDispatch(Activity activity, PendingIntent intent, IntentFilter[] filters, String[][] techLists)1485 public void enableForegroundDispatch(Activity activity, PendingIntent intent, 1486 IntentFilter[] filters, String[][] techLists) { 1487 synchronized (NfcAdapter.class) { 1488 if (!sHasNfcFeature) { 1489 throw new UnsupportedOperationException(); 1490 } 1491 } 1492 if (activity == null || intent == null) { 1493 throw new NullPointerException(); 1494 } 1495 if (!activity.isResumed()) { 1496 throw new IllegalStateException("Foreground dispatch can only be enabled " + 1497 "when your activity is resumed"); 1498 } 1499 try { 1500 TechListParcel parcel = null; 1501 if (techLists != null && techLists.length > 0) { 1502 parcel = new TechListParcel(techLists); 1503 } 1504 ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity, 1505 mForegroundDispatchListener); 1506 sService.setForegroundDispatch(intent, filters, parcel); 1507 } catch (RemoteException e) { 1508 attemptDeadServiceRecovery(e); 1509 } 1510 } 1511 1512 /** 1513 * Disable foreground dispatch to the given activity. 1514 * 1515 * <p>After calling {@link #enableForegroundDispatch}, an activity 1516 * must call this method before its {@link Activity#onPause} callback 1517 * completes. 1518 * 1519 * <p>This method must be called from the main thread. 1520 * 1521 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1522 * 1523 * @param activity the Activity to disable dispatch to 1524 * @throws IllegalStateException if the Activity has already been paused 1525 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1526 */ disableForegroundDispatch(Activity activity)1527 public void disableForegroundDispatch(Activity activity) { 1528 synchronized (NfcAdapter.class) { 1529 if (!sHasNfcFeature) { 1530 throw new UnsupportedOperationException(); 1531 } 1532 } 1533 ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity, 1534 mForegroundDispatchListener); 1535 disableForegroundDispatchInternal(activity, false); 1536 } 1537 1538 OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() { 1539 @Override 1540 public void onPaused(Activity activity) { 1541 disableForegroundDispatchInternal(activity, true); 1542 } 1543 }; 1544 disableForegroundDispatchInternal(Activity activity, boolean force)1545 void disableForegroundDispatchInternal(Activity activity, boolean force) { 1546 try { 1547 sService.setForegroundDispatch(null, null, null); 1548 if (!force && !activity.isResumed()) { 1549 throw new IllegalStateException("You must disable foreground dispatching " + 1550 "while your activity is still resumed"); 1551 } 1552 } catch (RemoteException e) { 1553 attemptDeadServiceRecovery(e); 1554 } 1555 } 1556 1557 /** 1558 * Limit the NFC controller to reader mode while this Activity is in the foreground. 1559 * 1560 * <p>In this mode the NFC controller will only act as an NFC tag reader/writer, 1561 * thus disabling any peer-to-peer (Android Beam) and card-emulation modes of 1562 * the NFC adapter on this device. 1563 * 1564 * <p>Use {@link #FLAG_READER_SKIP_NDEF_CHECK} to prevent the platform from 1565 * performing any NDEF checks in reader mode. Note that this will prevent the 1566 * {@link Ndef} tag technology from being enumerated on the tag, and that 1567 * NDEF-based tag dispatch will not be functional. 1568 * 1569 * <p>For interacting with tags that are emulated on another Android device 1570 * using Android's host-based card-emulation, the recommended flags are 1571 * {@link #FLAG_READER_NFC_A} and {@link #FLAG_READER_SKIP_NDEF_CHECK}. 1572 * 1573 * @param activity the Activity that requests the adapter to be in reader mode 1574 * @param callback the callback to be called when a tag is discovered 1575 * @param flags Flags indicating poll technologies and other optional parameters 1576 * @param extras Additional extras for configuring reader mode. 1577 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1578 */ enableReaderMode(Activity activity, ReaderCallback callback, int flags, Bundle extras)1579 public void enableReaderMode(Activity activity, ReaderCallback callback, int flags, 1580 Bundle extras) { 1581 synchronized (NfcAdapter.class) { 1582 if (!sHasNfcFeature) { 1583 throw new UnsupportedOperationException(); 1584 } 1585 } 1586 mNfcActivityManager.enableReaderMode(activity, callback, flags, extras); 1587 } 1588 1589 /** 1590 * Restore the NFC adapter to normal mode of operation: supporting 1591 * peer-to-peer (Android Beam), card emulation, and polling for 1592 * all supported tag technologies. 1593 * 1594 * @param activity the Activity that currently has reader mode enabled 1595 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1596 */ disableReaderMode(Activity activity)1597 public void disableReaderMode(Activity activity) { 1598 synchronized (NfcAdapter.class) { 1599 if (!sHasNfcFeature) { 1600 throw new UnsupportedOperationException(); 1601 } 1602 } 1603 mNfcActivityManager.disableReaderMode(activity); 1604 } 1605 1606 /** 1607 * Manually invoke Android Beam to share data. 1608 * 1609 * <p>The Android Beam animation is normally only shown when two NFC-capable 1610 * devices come into range. 1611 * By calling this method, an Activity can invoke the Beam animation directly 1612 * even if no other NFC device is in range yet. The Beam animation will then 1613 * prompt the user to tap another NFC-capable device to complete the data 1614 * transfer. 1615 * 1616 * <p>The main advantage of using this method is that it avoids the need for the 1617 * user to tap the screen to complete the transfer, as this method already 1618 * establishes the direction of the transfer and the consent of the user to 1619 * share data. Callers are responsible for making sure that the user has 1620 * consented to sharing data on NFC tap. 1621 * 1622 * <p>Note that to use this method, the passed in Activity must have already 1623 * set data to share over Beam by using method calls such as 1624 * {@link #setNdefPushMessageCallback} or 1625 * {@link #setBeamPushUrisCallback}. 1626 * 1627 * @param activity the current foreground Activity that has registered data to share 1628 * @return whether the Beam animation was successfully invoked 1629 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1630 * @deprecated this feature is deprecated. File sharing can work using other technology like 1631 * Bluetooth. 1632 */ 1633 @java.lang.Deprecated invokeBeam(Activity activity)1634 public boolean invokeBeam(Activity activity) { 1635 synchronized (NfcAdapter.class) { 1636 if (!sHasNfcFeature) { 1637 throw new UnsupportedOperationException(); 1638 } 1639 if (!sHasBeamFeature) { 1640 return false; 1641 } 1642 } 1643 if (activity == null) { 1644 throw new NullPointerException("activity may not be null."); 1645 } 1646 enforceResumed(activity); 1647 try { 1648 sService.invokeBeam(); 1649 return true; 1650 } catch (RemoteException e) { 1651 Log.e(TAG, "invokeBeam: NFC process has died."); 1652 attemptDeadServiceRecovery(e); 1653 return false; 1654 } 1655 } 1656 1657 /** 1658 * @hide 1659 */ invokeBeam(BeamShareData shareData)1660 public boolean invokeBeam(BeamShareData shareData) { 1661 try { 1662 Log.e(TAG, "invokeBeamInternal()"); 1663 sService.invokeBeamInternal(shareData); 1664 return true; 1665 } catch (RemoteException e) { 1666 Log.e(TAG, "invokeBeam: NFC process has died."); 1667 attemptDeadServiceRecovery(e); 1668 return false; 1669 } 1670 } 1671 1672 /** 1673 * Enable NDEF message push over NFC while this Activity is in the foreground. 1674 * 1675 * <p>You must explicitly call this method every time the activity is 1676 * resumed, and you must call {@link #disableForegroundNdefPush} before 1677 * your activity completes {@link Activity#onPause}. 1678 * 1679 * <p>Strongly recommend to use the new {@link #setNdefPushMessage} 1680 * instead: it automatically hooks into your activity life-cycle, 1681 * so you do not need to call enable/disable in your onResume/onPause. 1682 * 1683 * <p>For NDEF push to function properly the other NFC device must 1684 * support either NFC Forum's SNEP (Simple Ndef Exchange Protocol), or 1685 * Android's "com.android.npp" (Ndef Push Protocol). This was optional 1686 * on Gingerbread level Android NFC devices, but SNEP is mandatory on 1687 * Ice-Cream-Sandwich and beyond. 1688 * 1689 * <p>This method must be called from the main thread. 1690 * 1691 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1692 * 1693 * @param activity foreground activity 1694 * @param message a NDEF Message to push over NFC 1695 * @throws IllegalStateException if the activity is not currently in the foreground 1696 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1697 * @deprecated use {@link #setNdefPushMessage} instead 1698 */ 1699 @Deprecated enableForegroundNdefPush(Activity activity, NdefMessage message)1700 public void enableForegroundNdefPush(Activity activity, NdefMessage message) { 1701 synchronized (NfcAdapter.class) { 1702 if (!sHasNfcFeature) { 1703 throw new UnsupportedOperationException(); 1704 } 1705 if (!sHasBeamFeature) { 1706 return; 1707 } 1708 } 1709 if (activity == null || message == null) { 1710 throw new NullPointerException(); 1711 } 1712 enforceResumed(activity); 1713 mNfcActivityManager.setNdefPushMessage(activity, message, 0); 1714 } 1715 1716 /** 1717 * Disable NDEF message push over P2P. 1718 * 1719 * <p>After calling {@link #enableForegroundNdefPush}, an activity 1720 * must call this method before its {@link Activity#onPause} callback 1721 * completes. 1722 * 1723 * <p>Strongly recommend to use the new {@link #setNdefPushMessage} 1724 * instead: it automatically hooks into your activity life-cycle, 1725 * so you do not need to call enable/disable in your onResume/onPause. 1726 * 1727 * <p>This method must be called from the main thread. 1728 * 1729 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1730 * 1731 * @param activity the Foreground activity 1732 * @throws IllegalStateException if the Activity has already been paused 1733 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1734 * @deprecated use {@link #setNdefPushMessage} instead 1735 */ 1736 @Deprecated disableForegroundNdefPush(Activity activity)1737 public void disableForegroundNdefPush(Activity activity) { 1738 synchronized (NfcAdapter.class) { 1739 if (!sHasNfcFeature) { 1740 throw new UnsupportedOperationException(); 1741 } 1742 if (!sHasBeamFeature) { 1743 return; 1744 } 1745 } 1746 if (activity == null) { 1747 throw new NullPointerException(); 1748 } 1749 enforceResumed(activity); 1750 mNfcActivityManager.setNdefPushMessage(activity, null, 0); 1751 mNfcActivityManager.setNdefPushMessageCallback(activity, null, 0); 1752 mNfcActivityManager.setOnNdefPushCompleteCallback(activity, null); 1753 } 1754 1755 /** 1756 * Sets Secure NFC feature. 1757 * <p>This API is for the Settings application. 1758 * @return True if successful 1759 * @hide 1760 */ 1761 @SystemApi 1762 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) enableSecureNfc(boolean enable)1763 public boolean enableSecureNfc(boolean enable) { 1764 if (!sHasNfcFeature) { 1765 throw new UnsupportedOperationException(); 1766 } 1767 try { 1768 return sService.setNfcSecure(enable); 1769 } catch (RemoteException e) { 1770 attemptDeadServiceRecovery(e); 1771 return false; 1772 } 1773 } 1774 1775 /** 1776 * Checks if the device supports Secure NFC functionality. 1777 * 1778 * @return True if device supports Secure NFC, false otherwise 1779 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1780 */ isSecureNfcSupported()1781 public boolean isSecureNfcSupported() { 1782 if (!sHasNfcFeature) { 1783 throw new UnsupportedOperationException(); 1784 } 1785 try { 1786 return sService.deviceSupportsNfcSecure(); 1787 } catch (RemoteException e) { 1788 attemptDeadServiceRecovery(e); 1789 return false; 1790 } 1791 } 1792 1793 /** 1794 * Checks Secure NFC feature is enabled. 1795 * 1796 * @return True if Secure NFC is enabled, false otherwise 1797 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1798 * @throws UnsupportedOperationException if device doesn't support 1799 * Secure NFC functionality. {@link #isSecureNfcSupported} 1800 */ isSecureNfcEnabled()1801 public boolean isSecureNfcEnabled() { 1802 if (!sHasNfcFeature) { 1803 throw new UnsupportedOperationException(); 1804 } 1805 try { 1806 return sService.isNfcSecureEnabled(); 1807 } catch (RemoteException e) { 1808 attemptDeadServiceRecovery(e); 1809 return false; 1810 } 1811 } 1812 1813 /** 1814 * Enable NDEF Push feature. 1815 * <p>This API is for the Settings application. 1816 * @hide 1817 */ 1818 @SystemApi 1819 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) enableNdefPush()1820 public boolean enableNdefPush() { 1821 if (!sHasNfcFeature) { 1822 throw new UnsupportedOperationException(); 1823 } 1824 try { 1825 return sService.enableNdefPush(); 1826 } catch (RemoteException e) { 1827 attemptDeadServiceRecovery(e); 1828 return false; 1829 } 1830 } 1831 1832 /** 1833 * Disable NDEF Push feature. 1834 * <p>This API is for the Settings application. 1835 * @hide 1836 */ 1837 @SystemApi 1838 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) disableNdefPush()1839 public boolean disableNdefPush() { 1840 synchronized (NfcAdapter.class) { 1841 if (!sHasNfcFeature) { 1842 throw new UnsupportedOperationException(); 1843 } 1844 } 1845 try { 1846 return sService.disableNdefPush(); 1847 } catch (RemoteException e) { 1848 attemptDeadServiceRecovery(e); 1849 return false; 1850 } 1851 } 1852 1853 /** 1854 * Return true if the NDEF Push (Android Beam) feature is enabled. 1855 * <p>This function will return true only if both NFC is enabled, and the 1856 * NDEF Push feature is enabled. 1857 * <p>Note that if NFC is enabled but NDEF Push is disabled then this 1858 * device can still <i>receive</i> NDEF messages, it just cannot send them. 1859 * <p>Applications cannot directly toggle the NDEF Push feature, but they 1860 * can request Settings UI allowing the user to toggle NDEF Push using 1861 * <code>startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS))</code> 1862 * <p>Example usage in an Activity that requires NDEF Push: 1863 * <p><pre> 1864 * protected void onResume() { 1865 * super.onResume(); 1866 * if (!nfcAdapter.isEnabled()) { 1867 * startActivity(new Intent(Settings.ACTION_NFC_SETTINGS)); 1868 * } else if (!nfcAdapter.isNdefPushEnabled()) { 1869 * startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS)); 1870 * } 1871 * }</pre> 1872 * 1873 * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS 1874 * @return true if NDEF Push feature is enabled 1875 * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. 1876 * @deprecated this feature is deprecated. File sharing can work using other technology like 1877 * Bluetooth. 1878 */ 1879 @java.lang.Deprecated 1880 isNdefPushEnabled()1881 public boolean isNdefPushEnabled() { 1882 synchronized (NfcAdapter.class) { 1883 if (!sHasNfcFeature) { 1884 throw new UnsupportedOperationException(); 1885 } 1886 if (!sHasBeamFeature) { 1887 return false; 1888 } 1889 } 1890 try { 1891 return sService.isNdefPushEnabled(); 1892 } catch (RemoteException e) { 1893 attemptDeadServiceRecovery(e); 1894 return false; 1895 } 1896 } 1897 1898 /** 1899 * Signals that you are no longer interested in communicating with an NFC tag 1900 * for as long as it remains in range. 1901 * 1902 * All future attempted communication to this tag will fail with {@link IOException}. 1903 * The NFC controller will be put in a low-power polling mode, allowing the device 1904 * to save power in cases where it's "attached" to a tag all the time (e.g. a tag in 1905 * car dock). 1906 * 1907 * Additionally the debounceMs parameter allows you to specify for how long the tag needs 1908 * to have gone out of range, before it will be dispatched again. 1909 * 1910 * Note: the NFC controller typically polls at a pretty slow interval (100 - 500 ms). 1911 * This means that if the tag repeatedly goes in and out of range (for example, in 1912 * case of a flaky connection), and the controller happens to poll every time the 1913 * tag is out of range, it *will* re-dispatch the tag after debounceMs, despite the tag 1914 * having been "in range" during the interval. 1915 * 1916 * Note 2: if a tag with another UID is detected after this API is called, its effect 1917 * will be cancelled; if this tag shows up before the amount of time specified in 1918 * debounceMs, it will be dispatched again. 1919 * 1920 * Note 3: some tags have a random UID, in which case this API won't work reliably. 1921 * 1922 * @param tag the {@link android.nfc.Tag Tag} to ignore. 1923 * @param debounceMs minimum amount of time the tag needs to be out of range before being 1924 * dispatched again. 1925 * @param tagRemovedListener listener to be called when the tag is removed from the field. 1926 * Note that this will only be called if the tag has been out of range 1927 * for at least debounceMs, or if another tag came into range before 1928 * debounceMs. May be null in case you don't want a callback. 1929 * @param handler the {@link android.os.Handler Handler} that will be used for delivering 1930 * the callback. if the handler is null, then the thread used for delivering 1931 * the callback is unspecified. 1932 * @return false if the tag couldn't be found (or has already gone out of range), true otherwise 1933 */ ignore(final Tag tag, int debounceMs, final OnTagRemovedListener tagRemovedListener, final Handler handler)1934 public boolean ignore(final Tag tag, int debounceMs, 1935 final OnTagRemovedListener tagRemovedListener, final Handler handler) { 1936 ITagRemovedCallback.Stub iListener = null; 1937 if (tagRemovedListener != null) { 1938 iListener = new ITagRemovedCallback.Stub() { 1939 @Override 1940 public void onTagRemoved() throws RemoteException { 1941 if (handler != null) { 1942 handler.post(new Runnable() { 1943 @Override 1944 public void run() { 1945 tagRemovedListener.onTagRemoved(); 1946 } 1947 }); 1948 } else { 1949 tagRemovedListener.onTagRemoved(); 1950 } 1951 synchronized (mLock) { 1952 mTagRemovedListener = null; 1953 } 1954 } 1955 }; 1956 } 1957 synchronized (mLock) { 1958 mTagRemovedListener = iListener; 1959 } 1960 try { 1961 return sService.ignore(tag.getServiceHandle(), debounceMs, iListener); 1962 } catch (RemoteException e) { 1963 return false; 1964 } 1965 } 1966 1967 /** 1968 * Inject a mock NFC tag.<p> 1969 * Used for testing purposes. 1970 * <p class="note">Requires the 1971 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. 1972 * @hide 1973 */ dispatch(Tag tag)1974 public void dispatch(Tag tag) { 1975 if (tag == null) { 1976 throw new NullPointerException("tag cannot be null"); 1977 } 1978 try { 1979 sService.dispatch(tag); 1980 } catch (RemoteException e) { 1981 attemptDeadServiceRecovery(e); 1982 } 1983 } 1984 1985 /** 1986 * @hide 1987 */ setP2pModes(int initiatorModes, int targetModes)1988 public void setP2pModes(int initiatorModes, int targetModes) { 1989 try { 1990 sService.setP2pModes(initiatorModes, targetModes); 1991 } catch (RemoteException e) { 1992 attemptDeadServiceRecovery(e); 1993 } 1994 } 1995 1996 /** 1997 * Registers a new NFC unlock handler with the NFC service. 1998 * 1999 * <p />NFC unlock handlers are intended to unlock the keyguard in the presence of a trusted 2000 * NFC device. The handler should return true if it successfully authenticates the user and 2001 * unlocks the keyguard. 2002 * 2003 * <p /> The parameter {@code tagTechnologies} determines which Tag technologies will be polled for 2004 * at the lockscreen. Polling for less tag technologies reduces latency, and so it is 2005 * strongly recommended to only provide the Tag technologies that the handler is expected to 2006 * receive. There must be at least one tag technology provided, otherwise the unlock handler 2007 * is ignored. 2008 * 2009 * @hide 2010 */ 2011 @SystemApi 2012 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) addNfcUnlockHandler(final NfcUnlockHandler unlockHandler, String[] tagTechnologies)2013 public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler, 2014 String[] tagTechnologies) { 2015 synchronized (NfcAdapter.class) { 2016 if (!sHasNfcFeature) { 2017 throw new UnsupportedOperationException(); 2018 } 2019 } 2020 // If there are no tag technologies, don't bother adding unlock handler 2021 if (tagTechnologies.length == 0) { 2022 return false; 2023 } 2024 2025 try { 2026 synchronized (mLock) { 2027 if (mNfcUnlockHandlers.containsKey(unlockHandler)) { 2028 // update the tag technologies 2029 sService.removeNfcUnlockHandler(mNfcUnlockHandlers.get(unlockHandler)); 2030 mNfcUnlockHandlers.remove(unlockHandler); 2031 } 2032 2033 INfcUnlockHandler.Stub iHandler = new INfcUnlockHandler.Stub() { 2034 @Override 2035 public boolean onUnlockAttempted(Tag tag) throws RemoteException { 2036 return unlockHandler.onUnlockAttempted(tag); 2037 } 2038 }; 2039 2040 sService.addNfcUnlockHandler(iHandler, 2041 Tag.getTechCodesFromStrings(tagTechnologies)); 2042 mNfcUnlockHandlers.put(unlockHandler, iHandler); 2043 } 2044 } catch (RemoteException e) { 2045 attemptDeadServiceRecovery(e); 2046 return false; 2047 } catch (IllegalArgumentException e) { 2048 Log.e(TAG, "Unable to register LockscreenDispatch", e); 2049 return false; 2050 } 2051 2052 return true; 2053 } 2054 2055 /** 2056 * Removes a previously registered unlock handler. Also removes the tag technologies 2057 * associated with the removed unlock handler. 2058 * 2059 * @hide 2060 */ 2061 @SystemApi 2062 @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) removeNfcUnlockHandler(NfcUnlockHandler unlockHandler)2063 public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) { 2064 synchronized (NfcAdapter.class) { 2065 if (!sHasNfcFeature) { 2066 throw new UnsupportedOperationException(); 2067 } 2068 } 2069 try { 2070 synchronized (mLock) { 2071 if (mNfcUnlockHandlers.containsKey(unlockHandler)) { 2072 sService.removeNfcUnlockHandler(mNfcUnlockHandlers.remove(unlockHandler)); 2073 } 2074 2075 return true; 2076 } 2077 } catch (RemoteException e) { 2078 attemptDeadServiceRecovery(e); 2079 return false; 2080 } 2081 } 2082 2083 /** 2084 * @hide 2085 */ 2086 @UnsupportedAppUsage getNfcAdapterExtrasInterface()2087 public INfcAdapterExtras getNfcAdapterExtrasInterface() { 2088 if (mContext == null) { 2089 throw new UnsupportedOperationException("You need a context on NfcAdapter to use the " 2090 + " NFC extras APIs"); 2091 } 2092 try { 2093 return sService.getNfcAdapterExtrasInterface(mContext.getPackageName()); 2094 } catch (RemoteException e) { 2095 attemptDeadServiceRecovery(e); 2096 return null; 2097 } 2098 } 2099 enforceResumed(Activity activity)2100 void enforceResumed(Activity activity) { 2101 if (!activity.isResumed()) { 2102 throw new IllegalStateException("API cannot be called while activity is paused"); 2103 } 2104 } 2105 getSdkVersion()2106 int getSdkVersion() { 2107 if (mContext == null) { 2108 return android.os.Build.VERSION_CODES.GINGERBREAD; // best guess 2109 } else { 2110 return mContext.getApplicationInfo().targetSdkVersion; 2111 } 2112 } 2113 } 2114