NfcAdapter.java revision 7bcd2c62ebfad640e8082c1dc700c9d8c57aba81
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 17package android.nfc; 18 19import android.annotation.SdkConstant; 20import android.annotation.SdkConstant.SdkConstantType; 21import android.app.Activity; 22import android.app.ActivityThread; 23import android.app.OnActivityPausedListener; 24import android.app.PendingIntent; 25import android.content.Context; 26import android.content.IntentFilter; 27import android.content.pm.IPackageManager; 28import android.content.pm.PackageManager; 29import android.nfc.tech.MifareClassic; 30import android.nfc.tech.Ndef; 31import android.nfc.tech.NfcA; 32import android.nfc.tech.NfcF; 33import android.os.IBinder; 34import android.os.RemoteException; 35import android.os.ServiceManager; 36import android.util.Log; 37 38/** 39 * Represents the local NFC adapter. 40 * <p> 41 * Use the helper {@link #getDefaultAdapter(Context)} to get the default NFC 42 * adapter for this Android device. 43 */ 44public final class NfcAdapter { 45 private static final String TAG = "NFC"; 46 47 /** 48 * Intent to start an activity when a tag with NDEF payload is discovered. 49 * 50 * <p>The system inspects the first {@link NdefRecord} in the first {@link NdefMessage} and 51 * looks for a URI, SmartPoster, or MIME record. If a URI or SmartPoster record is found the 52 * intent will contain the URI in its data field. If a MIME record is found the intent will 53 * contain the MIME type in its type field. This allows activities to register 54 * {@link IntentFilter}s targeting specific content on tags. Activities should register the 55 * most specific intent filters possible to avoid the activity chooser dialog, which can 56 * disrupt the interaction with the tag as the user interacts with the screen. 57 * 58 * <p>If the tag has an NDEF payload this intent is started before 59 * {@link #ACTION_TECH_DISCOVERED}. If any activities respond to this intent neither 60 * {@link #ACTION_TECH_DISCOVERED} or {@link #ACTION_TAG_DISCOVERED} will be started. 61 */ 62 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 63 public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED"; 64 65 /** 66 * Intent to start an activity when a tag is discovered and activities are registered for the 67 * specific technologies on the tag. 68 * 69 * <p>To receive this intent an activity must include an intent filter 70 * for this action and specify the desired tech types in a 71 * manifest <code>meta-data</code> entry. Here is an example manfiest entry: 72 * <pre> 73 * <activity android:name=".nfc.TechFilter" android:label="NFC/TechFilter"> 74 * <!-- Add a technology filter --> 75 * <intent-filter> 76 * <action android:name="android.nfc.action.TECH_DISCOVERED" /> 77 * </intent-filter> 78 * 79 * <meta-data android:name="android.nfc.action.TECH_DISCOVERED" 80 * android:resource="@xml/filter_nfc" 81 * /> 82 * </activity> 83 * </pre> 84 * 85 * <p>The meta-data XML file should contain one or more <code>tech-list</code> entries 86 * each consisting or one or more <code>tech</code> entries. The <code>tech</code> entries refer 87 * to the qualified class name implementing the technology, for example "android.nfc.tech.NfcA". 88 * 89 * <p>A tag matches if any of the 90 * <code>tech-list</code> sets is a subset of {@link Tag#getTechList() Tag.getTechList()}. Each 91 * of the <code>tech-list</code>s is considered independently and the 92 * activity is considered a match is any single <code>tech-list</code> matches the tag that was 93 * discovered. This provides AND and OR semantics for filtering desired techs. Here is an 94 * example that will match any tag using {@link NfcF} or any tag using {@link NfcA}, 95 * {@link MifareClassic}, and {@link Ndef}: 96 * 97 * <pre> 98 * <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 99 * <!-- capture anything using NfcF --> 100 * <tech-list> 101 * <tech>android.nfc.tech.NfcF</tech> 102 * </tech-list> 103 * 104 * <!-- OR --> 105 * 106 * <!-- capture all MIFARE Classics with NDEF payloads --> 107 * <tech-list> 108 * <tech>android.nfc.tech.NfcA</tech> 109 * <tech>android.nfc.tech.MifareClassic</tech> 110 * <tech>android.nfc.tech.Ndef</tech> 111 * </tech-list> 112 * </resources> 113 * </pre> 114 * 115 * <p>This intent is started after {@link #ACTION_NDEF_DISCOVERED} and before 116 * {@link #ACTION_TAG_DISCOVERED}. If any activities respond to {@link #ACTION_NDEF_DISCOVERED} 117 * this intent will not be started. If any activities respond to this intent 118 * {@link #ACTION_TAG_DISCOVERED} will not be started. 119 */ 120 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 121 public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED"; 122 123 /** 124 * Intent to start an activity when a tag is discovered. 125 * 126 * <p>This intent will not be started when a tag is discovered if any activities respond to 127 * {@link #ACTION_NDEF_DISCOVERED} or {@link #ACTION_TECH_DISCOVERED} for the current tag. 128 */ 129 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 130 public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; 131 132 /** 133 * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED 134 * @hide 135 */ 136 public static final String ACTION_TAG_LEFT_FIELD = "android.nfc.action.TAG_LOST"; 137 138 /** 139 * Mandatory extra containing the {@link Tag} that was discovered for the 140 * {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and 141 * {@link #ACTION_TAG_DISCOVERED} intents. 142 */ 143 public static final String EXTRA_TAG = "android.nfc.extra.TAG"; 144 145 /** 146 * Optional extra containing an array of {@link NdefMessage} present on the discovered tag for 147 * the {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and 148 * {@link #ACTION_TAG_DISCOVERED} intents. 149 */ 150 public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES"; 151 152 /** 153 * Optional extra containing a byte array containing the ID of the discovered tag for 154 * the {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and 155 * {@link #ACTION_TAG_DISCOVERED} intents. 156 */ 157 public static final String EXTRA_ID = "android.nfc.extra.ID"; 158 159 /** 160 * Broadcast Action: a transaction with a secure element has been detected. 161 * <p> 162 * Always contains the extra field 163 * {@link android.nfc.NfcAdapter#EXTRA_AID} 164 * @hide 165 */ 166 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 167 public static final String ACTION_TRANSACTION_DETECTED = 168 "android.nfc.action.TRANSACTION_DETECTED"; 169 170 /** 171 * Broadcast Action: an RF field ON has been detected. 172 * @hide 173 */ 174 public static final String ACTION_RF_FIELD_ON_DETECTED = 175 "android.nfc.action.RF_FIELD_ON_DETECTED"; 176 177 /** 178 * Broadcast Action: an RF Field OFF has been detected. 179 * @hide 180 */ 181 public static final String ACTION_RF_FIELD_OFF_DETECTED = 182 "android.nfc.action.RF_FIELD_OFF_DETECTED"; 183 184 /** 185 * Broadcast Action: an adapter's state changed between enabled and disabled. 186 * 187 * The new value is stored in the extra EXTRA_NEW_BOOLEAN_STATE and just contains 188 * whether it's enabled or disabled, not including any information about whether it's 189 * actively enabling or disabling. 190 * 191 * @hide 192 */ 193 public static final String ACTION_ADAPTER_STATE_CHANGE = 194 "android.nfc.action.ADAPTER_STATE_CHANGE"; 195 196 /** 197 * The Intent extra for ACTION_ADAPTER_STATE_CHANGE, saying what the new state is. 198 * 199 * @hide 200 */ 201 public static final String EXTRA_NEW_BOOLEAN_STATE = "android.nfc.isEnabled"; 202 203 /** 204 * Mandatory byte array extra field in 205 * {@link android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED}. 206 * <p> 207 * Contains the AID of the applet involved in the transaction. 208 * @hide 209 */ 210 public static final String EXTRA_AID = "android.nfc.extra.AID"; 211 212 /** 213 * LLCP link status: The LLCP link is activated. 214 * @hide 215 */ 216 public static final int LLCP_LINK_STATE_ACTIVATED = 0; 217 218 /** 219 * LLCP link status: The LLCP link is deactivated. 220 * @hide 221 */ 222 public static final int LLCP_LINK_STATE_DEACTIVATED = 1; 223 224 /** 225 * Broadcast Action: the LLCP link state changed. 226 * <p> 227 * Always contains the extra field 228 * {@link android.nfc.NfcAdapter#EXTRA_LLCP_LINK_STATE_CHANGED}. 229 * @hide 230 */ 231 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 232 public static final String ACTION_LLCP_LINK_STATE_CHANGED = 233 "android.nfc.action.LLCP_LINK_STATE_CHANGED"; 234 235 /** 236 * Used as int extra field in 237 * {@link android.nfc.NfcAdapter#ACTION_LLCP_LINK_STATE_CHANGED}. 238 * <p> 239 * It contains the new state of the LLCP link. 240 * @hide 241 */ 242 public static final String EXTRA_LLCP_LINK_STATE_CHANGED = "android.nfc.extra.LLCP_LINK_STATE"; 243 244 /** 245 * Tag Reader Discovery mode 246 * @hide 247 */ 248 private static final int DISCOVERY_MODE_TAG_READER = 0; 249 250 /** 251 * NFC-IP1 Peer-to-Peer mode Enables the manager to act as a peer in an 252 * NFC-IP1 communication. Implementations should not assume that the 253 * controller will end up behaving as an NFC-IP1 target or initiator and 254 * should handle both cases, depending on the type of the remote peer type. 255 * @hide 256 */ 257 private static final int DISCOVERY_MODE_NFCIP1 = 1; 258 259 /** 260 * Card Emulation mode Enables the manager to act as an NFC tag. Provided 261 * that a Secure Element (an UICC for instance) is connected to the NFC 262 * controller through its SWP interface, it can be exposed to the outside 263 * NFC world and be addressed by external readers the same way they would 264 * with a tag. 265 * <p> 266 * Which Secure Element is exposed is implementation-dependent. 267 * 268 * @hide 269 */ 270 private static final int DISCOVERY_MODE_CARD_EMULATION = 2; 271 272 273 // Guarded by NfcAdapter.class 274 private static boolean sIsInitialized = false; 275 276 // Final after first constructor, except for 277 // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort 278 // recovery 279 private static INfcAdapter sService; 280 private static INfcTag sTagService; 281 282 /** 283 * Helper to check if this device has FEATURE_NFC, but without using 284 * a context. 285 * Equivalent to 286 * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC) 287 */ 288 private static boolean hasNfcFeature() { 289 IPackageManager pm = ActivityThread.getPackageManager(); 290 if (pm == null) { 291 Log.e(TAG, "Cannot get package manager, assuming no NFC feature"); 292 return false; 293 } 294 try { 295 return pm.hasSystemFeature(PackageManager.FEATURE_NFC); 296 } catch (RemoteException e) { 297 Log.e(TAG, "Package manager query failed, assuming no NFC feature", e); 298 return false; 299 } 300 } 301 302 private static synchronized INfcAdapter setupService() { 303 if (!sIsInitialized) { 304 sIsInitialized = true; 305 306 /* is this device meant to have NFC */ 307 if (!hasNfcFeature()) { 308 Log.v(TAG, "this device does not have NFC support"); 309 return null; 310 } 311 312 sService = getServiceInterface(); 313 if (sService == null) { 314 Log.e(TAG, "could not retrieve NFC service"); 315 return null; 316 } 317 try { 318 sTagService = sService.getNfcTagInterface(); 319 } catch (RemoteException e) { 320 Log.e(TAG, "could not retrieve NFC Tag service"); 321 return null; 322 } 323 } 324 return sService; 325 } 326 327 /** get handle to NFC service interface */ 328 private static INfcAdapter getServiceInterface() { 329 /* get a handle to NFC service */ 330 IBinder b = ServiceManager.getService("nfc"); 331 if (b == null) { 332 return null; 333 } 334 return INfcAdapter.Stub.asInterface(b); 335 } 336 337 /** 338 * Helper to get the default NFC Adapter. 339 * <p> 340 * Most Android devices will only have one NFC Adapter (NFC Controller). 341 * <p> 342 * This helper is the equivalent of: 343 * <pre>{@code 344 * NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE); 345 * NfcAdapter adapter = manager.getDefaultAdapter(); 346 * }</pre> 347 * @param context the calling application's context 348 * 349 * @return the default NFC adapter, or null if no NFC adapter exists 350 */ 351 public static NfcAdapter getDefaultAdapter(Context context) { 352 /* use getSystemService() instead of just instantiating to take 353 * advantage of the context's cached NfcManager & NfcAdapter */ 354 NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE); 355 return manager.getDefaultAdapter(); 356 } 357 358 /** 359 * Get a handle to the default NFC Adapter on this Android device. 360 * <p> 361 * Most Android devices will only have one NFC Adapter (NFC Controller). 362 * 363 * @return the default NFC adapter, or null if no NFC adapter exists 364 * @deprecated use {@link #getDefaultAdapter(Context)} 365 */ 366 @Deprecated 367 public static NfcAdapter getDefaultAdapter() { 368 Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " + 369 "NfcAdapter.getDefaultAdapter(Context) instead", new Exception()); 370 return new NfcAdapter(null); 371 } 372 373 /*package*/ NfcAdapter(Context context) { 374 if (setupService() == null) { 375 throw new UnsupportedOperationException(); 376 } 377 } 378 379 /** 380 * Returns the binder interface to the service. 381 * @hide 382 */ 383 public INfcAdapter getService() { 384 isEnabled(); // NOP call to recover sService if it is stale 385 return sService; 386 } 387 388 /** 389 * Returns the binder interface to the tag service. 390 * @hide 391 */ 392 public INfcTag getTagService() { 393 isEnabled(); // NOP call to recover sTagService if it is stale 394 return sTagService; 395 } 396 397 /** 398 * NFC service dead - attempt best effort recovery 399 * @hide 400 */ 401 public void attemptDeadServiceRecovery(Exception e) { 402 Log.e(TAG, "NFC service dead - attempting to recover", e); 403 INfcAdapter service = getServiceInterface(); 404 if (service == null) { 405 Log.e(TAG, "could not retrieve NFC service during service recovery"); 406 // nothing more can be done now, sService is still stale, we'll hit 407 // this recovery path again later 408 return; 409 } 410 // assigning to sService is not thread-safe, but this is best-effort code 411 // and on a well-behaved system should never happen 412 sService = service; 413 try { 414 sTagService = service.getNfcTagInterface(); 415 } catch (RemoteException ee) { 416 Log.e(TAG, "could not retrieve NFC tag service during service recovery"); 417 // nothing more can be done now, sService is still stale, we'll hit 418 // this recovery path again later 419 } 420 421 return; 422 } 423 424 /** 425 * Return true if this NFC Adapter has any features enabled. 426 * 427 * <p>Application may use this as a helper to suggest that the user 428 * should turn on NFC in Settings. 429 * <p>If this method returns false, the NFC hardware is guaranteed not to 430 * generate or respond to any NFC transactions. 431 * 432 * @return true if this NFC Adapter has any features enabled 433 */ 434 public boolean isEnabled() { 435 try { 436 return sService.isEnabled(); 437 } catch (RemoteException e) { 438 attemptDeadServiceRecovery(e); 439 return false; 440 } 441 } 442 443 /** 444 * Enable NFC hardware. 445 * <p> 446 * NOTE: may block for ~second or more. Poor API. Avoid 447 * calling from the UI thread. 448 * 449 * @hide 450 */ 451 public boolean enable() { 452 try { 453 return sService.enable(); 454 } catch (RemoteException e) { 455 attemptDeadServiceRecovery(e); 456 return false; 457 } 458 } 459 460 /** 461 * Disable NFC hardware. 462 * No NFC features will work after this call, and the hardware 463 * will not perform or respond to any NFC communication. 464 * <p> 465 * NOTE: may block for ~second or more. Poor API. Avoid 466 * calling from the UI thread. 467 * 468 * @hide 469 */ 470 public boolean disable() { 471 try { 472 return sService.disable(); 473 } catch (RemoteException e) { 474 attemptDeadServiceRecovery(e); 475 return false; 476 } 477 } 478 479 /** 480 * Enable foreground dispatch to the given Activity. 481 * 482 * <p>This will give give priority to the foreground activity when 483 * dispatching a discovered {@link Tag} to an application. 484 * 485 * <p>If any IntentFilters are provided to this method they are used to match dispatch Intents 486 * for both the {@link NfcAdapter#ACTION_NDEF_DISCOVERED} and 487 * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. Since {@link NfcAdapter#ACTION_TECH_DISCOVERED} 488 * relies on meta data outside of the IntentFilter matching for that dispatch Intent is handled 489 * by passing in the tech lists separately. Each first level entry in the tech list represents 490 * an array of technologies that must all be present to match. If any of the first level sets 491 * match then the dispatch is routed through the given PendingIntent. In other words, the second 492 * level is ANDed together and the first level entries are ORed together. 493 * 494 * <p>If you pass {@code null} for both the {@code filters} and {@code techLists} parameters 495 * that acts a wild card and will cause the foreground activity to receive all tags via the 496 * {@link NfcAdapter#ACTION_TAG_DISCOVERED} intent. 497 * 498 * <p>This method must be called from the main thread, and only when the activity is in the 499 * foreground (resumed). Also, activities must call {@link #disableForegroundDispatch} before 500 * the completion of their {@link Activity#onPause} callback to disable foreground dispatch 501 * after it has been enabled. 502 * 503 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 504 * 505 * @param activity the Activity to dispatch to 506 * @param intent the PendingIntent to start for the dispatch 507 * @param filters the IntentFilters to override dispatching for, or null to always dispatch 508 * @param techLists the tech lists used to perform matching for dispatching of the 509 * {@link NfcAdapter#ACTION_TECH_DISCOVERED} intent 510 * @throws IllegalStateException if the Activity is not currently in the foreground 511 */ 512 public void enableForegroundDispatch(Activity activity, PendingIntent intent, 513 IntentFilter[] filters, String[][] techLists) { 514 if (activity == null || intent == null) { 515 throw new NullPointerException(); 516 } 517 if (!activity.isResumed()) { 518 throw new IllegalStateException("Foregorund dispatching can only be enabled " + 519 "when your activity is resumed"); 520 } 521 try { 522 TechListParcel parcel = null; 523 if (techLists != null && techLists.length > 0) { 524 parcel = new TechListParcel(techLists); 525 } 526 ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity, 527 mForegroundDispatchListener); 528 sService.enableForegroundDispatch(activity.getComponentName(), intent, filters, 529 parcel); 530 } catch (RemoteException e) { 531 attemptDeadServiceRecovery(e); 532 } 533 } 534 535 /** 536 * Disable foreground dispatch to the given activity. 537 * 538 * <p>After calling {@link #enableForegroundDispatch}, an activity 539 * must call this method before its {@link Activity#onPause} callback 540 * completes. 541 * 542 * <p>This method must be called from the main thread. 543 * 544 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 545 * 546 * @param activity the Activity to disable dispatch to 547 * @throws IllegalStateException if the Activity has already been paused 548 */ 549 public void disableForegroundDispatch(Activity activity) { 550 ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity, 551 mForegroundDispatchListener); 552 disableForegroundDispatchInternal(activity, false); 553 } 554 555 OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() { 556 @Override 557 public void onPaused(Activity activity) { 558 disableForegroundDispatchInternal(activity, true); 559 } 560 }; 561 562 void disableForegroundDispatchInternal(Activity activity, boolean force) { 563 try { 564 sService.disableForegroundDispatch(activity.getComponentName()); 565 if (!force && !activity.isResumed()) { 566 throw new IllegalStateException("You must disable forgeground dispatching " + 567 "while your activity is still resumed"); 568 } 569 } catch (RemoteException e) { 570 attemptDeadServiceRecovery(e); 571 } 572 } 573 574 /** 575 * Enable NDEF message push over P2P while this Activity is in the foreground. 576 * 577 * <p>For this to function properly the other NFC device being scanned must 578 * support the "com.android.npp" NDEF push protocol. Support for this 579 * protocol is currently optional for Android NFC devices. 580 * 581 * <p>This method must be called from the main thread. 582 * 583 * <p class="note"><em>NOTE:</em> While foreground NDEF push is active standard tag dispatch is disabled. 584 * Only the foreground activity may receive tag discovered dispatches via 585 * {@link #enableForegroundDispatch}. 586 * 587 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 588 * 589 * @param activity the foreground Activity 590 * @param msg a NDEF Message to push over P2P 591 * @throws IllegalStateException if the Activity is not currently in the foreground 592 * @throws OperationNotSupportedException if this Android device does not support NDEF push 593 */ 594 public void enableForegroundNdefPush(Activity activity, NdefMessage msg) { 595 if (activity == null || msg == null) { 596 throw new NullPointerException(); 597 } 598 if (!activity.isResumed()) { 599 throw new IllegalStateException("Foregorund NDEF push can only be enabled " + 600 "when your activity is resumed"); 601 } 602 try { 603 ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity, 604 mForegroundNdefPushListener); 605 sService.enableForegroundNdefPush(activity.getComponentName(), msg); 606 } catch (RemoteException e) { 607 attemptDeadServiceRecovery(e); 608 } 609 } 610 611 /** 612 * Disable NDEF message push over P2P. 613 * 614 * <p>After calling {@link #enableForegroundNdefPush}, an activity 615 * must call this method before its {@link Activity#onPause} callback 616 * completes. 617 * 618 * <p>This method must be called from the main thread. 619 * 620 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 621 * 622 * @param activity the Foreground activity 623 * @throws IllegalStateException if the Activity has already been paused 624 * @throws OperationNotSupportedException if this Android device does not support NDEF push 625 */ 626 public void disableForegroundNdefPush(Activity activity) { 627 ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity, 628 mForegroundNdefPushListener); 629 disableForegroundNdefPushInternal(activity, false); 630 } 631 632 OnActivityPausedListener mForegroundNdefPushListener = new OnActivityPausedListener() { 633 @Override 634 public void onPaused(Activity activity) { 635 disableForegroundNdefPushInternal(activity, true); 636 } 637 }; 638 639 void disableForegroundNdefPushInternal(Activity activity, boolean force) { 640 try { 641 sService.disableForegroundNdefPush(activity.getComponentName()); 642 if (!force && !activity.isResumed()) { 643 throw new IllegalStateException("You must disable forgeground NDEF push " + 644 "while your activity is still resumed"); 645 } 646 } catch (RemoteException e) { 647 attemptDeadServiceRecovery(e); 648 } 649 } 650 651 /** 652 * Set the NDEF Message that this NFC adapter should appear as to Tag 653 * readers. 654 * <p> 655 * Any Tag reader can read the contents of the local tag when it is in 656 * proximity, without any further user confirmation. 657 * <p> 658 * The implementation of this method must either 659 * <ul> 660 * <li>act as a passive tag containing this NDEF message 661 * <li>provide the NDEF message on over LLCP to peer NFC adapters 662 * </ul> 663 * The NDEF message is preserved across reboot. 664 * <p>Requires {@link android.Manifest.permission#NFC} permission. 665 * 666 * @param message NDEF message to make public 667 * @hide 668 */ 669 public void setLocalNdefMessage(NdefMessage message) { 670 try { 671 sService.localSet(message); 672 } catch (RemoteException e) { 673 attemptDeadServiceRecovery(e); 674 } 675 } 676 677 /** 678 * Get the NDEF Message that this adapter appears as to Tag readers. 679 * <p>Requires {@link android.Manifest.permission#NFC} permission. 680 * 681 * @return NDEF Message that is publicly readable 682 * @hide 683 */ 684 public NdefMessage getLocalNdefMessage() { 685 try { 686 return sService.localGet(); 687 } catch (RemoteException e) { 688 attemptDeadServiceRecovery(e); 689 return null; 690 } 691 } 692 693 /** 694 * Create an Nfc Secure Element Connection 695 * @hide 696 */ 697 public NfcSecureElement createNfcSecureElementConnection() { 698 try { 699 return new NfcSecureElement(sService.getNfcSecureElementInterface()); 700 } catch (RemoteException e) { 701 Log.e(TAG, "createNfcSecureElementConnection failed", e); 702 return null; 703 } 704 } 705 706 /** 707 * To change the Secure Element Card Emulation state (ON/OFF) 708 * @hide 709 */ 710 public void changeNfcSecureElementCardEmulationState(boolean state) 711 { 712 int seId = 11259375; 713 if(state){ 714 /* Enable card emulation */ 715 try { 716 sService.selectSecureElement(seId); 717 } catch (RemoteException e) { 718 Log.e(TAG, "Enable card emulation failed", e); 719 } 720 }else{ 721 /* Disable card emulation */ 722 try { 723 sService.deselectSecureElement(); 724 } catch (RemoteException e) { 725 Log.e(TAG, " card emulation failed", e); 726 } 727 } 728 } 729} 730