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