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 java.util.HashMap; 20 21 import android.annotation.SdkConstant; 22 import android.annotation.SdkConstant.SdkConstantType; 23 import android.app.Activity; 24 import android.app.ActivityThread; 25 import android.app.OnActivityPausedListener; 26 import android.app.PendingIntent; 27 import android.content.Context; 28 import android.content.IntentFilter; 29 import android.content.pm.IPackageManager; 30 import android.content.pm.PackageManager; 31 import android.net.Uri; 32 import android.nfc.tech.MifareClassic; 33 import android.nfc.tech.Ndef; 34 import android.nfc.tech.NfcA; 35 import android.nfc.tech.NfcF; 36 import android.os.IBinder; 37 import android.os.RemoteException; 38 import android.os.ServiceManager; 39 import android.util.Log; 40 41 /** 42 * Represents the local NFC adapter. 43 * <p> 44 * Use the helper {@link #getDefaultAdapter(Context)} to get the default NFC 45 * adapter for this Android device. 46 * 47 * <div class="special reference"> 48 * <h3>Developer Guides</h3> 49 * <p>For more information about using NFC, read the 50 * <a href="{@docRoot}guide/topics/nfc/index.html">Near Field Communication</a> developer guide.</p> 51 * </div> 52 */ 53 public final class NfcAdapter { 54 static final String TAG = "NFC"; 55 56 /** 57 * Intent to start an activity when a tag with NDEF payload is discovered. 58 * 59 * <p>The system inspects the first {@link NdefRecord} in the first {@link NdefMessage} and 60 * looks for a URI, SmartPoster, or MIME record. If a URI or SmartPoster record is found the 61 * intent will contain the URI in its data field. If a MIME record is found the intent will 62 * contain the MIME type in its type field. This allows activities to register 63 * {@link IntentFilter}s targeting specific content on tags. Activities should register the 64 * most specific intent filters possible to avoid the activity chooser dialog, which can 65 * disrupt the interaction with the tag as the user interacts with the screen. 66 * 67 * <p>If the tag has an NDEF payload this intent is started before 68 * {@link #ACTION_TECH_DISCOVERED}. If any activities respond to this intent neither 69 * {@link #ACTION_TECH_DISCOVERED} or {@link #ACTION_TAG_DISCOVERED} will be started. 70 * 71 * <p>The MIME type or data URI of this intent are normalized before dispatch - 72 * so that MIME, URI scheme and URI host are always lower-case. 73 */ 74 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 75 public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED"; 76 77 /** 78 * Intent to start an activity when a tag is discovered and activities are registered for the 79 * specific technologies on the tag. 80 * 81 * <p>To receive this intent an activity must include an intent filter 82 * for this action and specify the desired tech types in a 83 * manifest <code>meta-data</code> entry. Here is an example manfiest entry: 84 * <pre> 85 * <activity android:name=".nfc.TechFilter" android:label="NFC/TechFilter"> 86 * <!-- Add a technology filter --> 87 * <intent-filter> 88 * <action android:name="android.nfc.action.TECH_DISCOVERED" /> 89 * </intent-filter> 90 * 91 * <meta-data android:name="android.nfc.action.TECH_DISCOVERED" 92 * android:resource="@xml/filter_nfc" 93 * /> 94 * </activity></pre> 95 * 96 * <p>The meta-data XML file should contain one or more <code>tech-list</code> entries 97 * each consisting or one or more <code>tech</code> entries. The <code>tech</code> entries refer 98 * to the qualified class name implementing the technology, for example "android.nfc.tech.NfcA". 99 * 100 * <p>A tag matches if any of the 101 * <code>tech-list</code> sets is a subset of {@link Tag#getTechList() Tag.getTechList()}. Each 102 * of the <code>tech-list</code>s is considered independently and the 103 * activity is considered a match is any single <code>tech-list</code> matches the tag that was 104 * discovered. This provides AND and OR semantics for filtering desired techs. Here is an 105 * example that will match any tag using {@link NfcF} or any tag using {@link NfcA}, 106 * {@link MifareClassic}, and {@link Ndef}: 107 * 108 * <pre> 109 * <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 110 * <!-- capture anything using NfcF --> 111 * <tech-list> 112 * <tech>android.nfc.tech.NfcF</tech> 113 * </tech-list> 114 * 115 * <!-- OR --> 116 * 117 * <!-- capture all MIFARE Classics with NDEF payloads --> 118 * <tech-list> 119 * <tech>android.nfc.tech.NfcA</tech> 120 * <tech>android.nfc.tech.MifareClassic</tech> 121 * <tech>android.nfc.tech.Ndef</tech> 122 * </tech-list> 123 * </resources></pre> 124 * 125 * <p>This intent is started after {@link #ACTION_NDEF_DISCOVERED} and before 126 * {@link #ACTION_TAG_DISCOVERED}. If any activities respond to {@link #ACTION_NDEF_DISCOVERED} 127 * this intent will not be started. If any activities respond to this intent 128 * {@link #ACTION_TAG_DISCOVERED} will not be started. 129 */ 130 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 131 public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED"; 132 133 /** 134 * Intent to start an activity when a tag is discovered. 135 * 136 * <p>This intent will not be started when a tag is discovered if any activities respond to 137 * {@link #ACTION_NDEF_DISCOVERED} or {@link #ACTION_TECH_DISCOVERED} for the current tag. 138 */ 139 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 140 public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; 141 142 /** 143 * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED 144 * @hide 145 */ 146 public static final String ACTION_TAG_LEFT_FIELD = "android.nfc.action.TAG_LOST"; 147 148 /** 149 * Mandatory extra containing the {@link Tag} that was discovered for the 150 * {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and 151 * {@link #ACTION_TAG_DISCOVERED} intents. 152 */ 153 public static final String EXTRA_TAG = "android.nfc.extra.TAG"; 154 155 /** 156 * Extra containing an array of {@link NdefMessage} present on the discovered tag.<p> 157 * This extra is mandatory for {@link #ACTION_NDEF_DISCOVERED} intents, 158 * and optional for {@link #ACTION_TECH_DISCOVERED}, and 159 * {@link #ACTION_TAG_DISCOVERED} intents.<p> 160 * When this extra is present there will always be at least one 161 * {@link NdefMessage} element. Most NDEF tags have only one NDEF message, 162 * but we use an array for future compatibility. 163 */ 164 public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES"; 165 166 /** 167 * Optional extra containing a byte array containing the ID of the discovered tag for 168 * the {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and 169 * {@link #ACTION_TAG_DISCOVERED} intents. 170 */ 171 public static final String EXTRA_ID = "android.nfc.extra.ID"; 172 173 /** 174 * Broadcast Action: The state of the local NFC adapter has been 175 * changed. 176 * <p>For example, NFC has been turned on or off. 177 * <p>Always contains the extra field {@link #EXTRA_ADAPTER_STATE} 178 */ 179 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 180 public static final String ACTION_ADAPTER_STATE_CHANGED = 181 "android.nfc.action.ADAPTER_STATE_CHANGED"; 182 183 /** 184 * Used as an int extra field in {@link #ACTION_ADAPTER_STATE_CHANGED} 185 * intents to request the current power state. Possible values are: 186 * {@link #STATE_OFF}, 187 * {@link #STATE_TURNING_ON}, 188 * {@link #STATE_ON}, 189 * {@link #STATE_TURNING_OFF}, 190 */ 191 public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE"; 192 193 public static final int STATE_OFF = 1; 194 public static final int STATE_TURNING_ON = 2; 195 public static final int STATE_ON = 3; 196 public static final int STATE_TURNING_OFF = 4; 197 198 /** @hide */ 199 public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1; 200 201 /** @hide */ 202 public static final String ACTION_HANDOVER_TRANSFER_STARTED = 203 "android.nfc.action.HANDOVER_TRANSFER_STARTED"; 204 205 /** @hide */ 206 public static final String ACTION_HANDOVER_TRANSFER_DONE = 207 "android.nfc.action.HANDOVER_TRANSFER_DONE"; 208 209 /** @hide */ 210 public static final String EXTRA_HANDOVER_TRANSFER_STATUS = 211 "android.nfc.extra.HANDOVER_TRANSFER_STATUS"; 212 213 /** @hide */ 214 public static final int HANDOVER_TRANSFER_STATUS_SUCCESS = 0; 215 /** @hide */ 216 public static final int HANDOVER_TRANSFER_STATUS_FAILURE = 1; 217 218 /** @hide */ 219 public static final String EXTRA_HANDOVER_TRANSFER_URI = 220 "android.nfc.extra.HANDOVER_TRANSFER_URI"; 221 222 // Guarded by NfcAdapter.class 223 static boolean sIsInitialized = false; 224 225 // Final after first constructor, except for 226 // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort 227 // recovery 228 static INfcAdapter sService; 229 static INfcTag sTagService; 230 231 /** 232 * The NfcAdapter object for each application context. 233 * There is a 1-1 relationship between application context and 234 * NfcAdapter object. 235 */ 236 static HashMap<Context, NfcAdapter> sNfcAdapters = new HashMap(); //guard by NfcAdapter.class 237 238 /** 239 * NfcAdapter used with a null context. This ctor was deprecated but we have 240 * to support it for backwards compatibility. New methods that require context 241 * might throw when called on the null-context NfcAdapter. 242 */ 243 static NfcAdapter sNullContextNfcAdapter; // protected by NfcAdapter.class 244 245 final NfcActivityManager mNfcActivityManager; 246 final Context mContext; 247 248 /** 249 * A callback to be invoked when the system successfully delivers your {@link NdefMessage} 250 * to another device. 251 * @see #setOnNdefPushCompleteCallback 252 */ 253 public interface OnNdefPushCompleteCallback { 254 /** 255 * Called on successful NDEF push. 256 * 257 * <p>This callback is usually made on a binder thread (not the UI thread). 258 * 259 * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set 260 * @see #setNdefPushMessageCallback 261 */ 262 public void onNdefPushComplete(NfcEvent event); 263 } 264 265 /** 266 * A callback to be invoked when another NFC device capable of NDEF push (Android Beam) 267 * is within range. 268 * <p>Implement this interface and pass it to {@link 269 * NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()} in order to create an 270 * {@link NdefMessage} at the moment that another device is within range for NFC. Using this 271 * callback allows you to create a message with data that might vary based on the 272 * content currently visible to the user. Alternatively, you can call {@link 273 * #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the 274 * same data. 275 */ 276 public interface CreateNdefMessageCallback { 277 /** 278 * Called to provide a {@link NdefMessage} to push. 279 * 280 * <p>This callback is usually made on a binder thread (not the UI thread). 281 * 282 * <p>Called when this device is in range of another device 283 * that might support NDEF push. It allows the application to 284 * create the NDEF message only when it is required. 285 * 286 * <p>NDEF push cannot occur until this method returns, so do not 287 * block for too long. 288 * 289 * <p>The Android operating system will usually show a system UI 290 * on top of your activity during this time, so do not try to request 291 * input from the user to complete the callback, or provide custom NDEF 292 * push UI. The user probably will not see it. 293 * 294 * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set 295 * @return NDEF message to push, or null to not provide a message 296 */ 297 public NdefMessage createNdefMessage(NfcEvent event); 298 } 299 300 301 // TODO javadoc 302 public interface CreateBeamUrisCallback { 303 public Uri[] createBeamUris(NfcEvent event); 304 } 305 306 /** 307 * Helper to check if this device has FEATURE_NFC, but without using 308 * a context. 309 * Equivalent to 310 * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC) 311 */ 312 private static boolean hasNfcFeature() { 313 IPackageManager pm = ActivityThread.getPackageManager(); 314 if (pm == null) { 315 Log.e(TAG, "Cannot get package manager, assuming no NFC feature"); 316 return false; 317 } 318 try { 319 return pm.hasSystemFeature(PackageManager.FEATURE_NFC); 320 } catch (RemoteException e) { 321 Log.e(TAG, "Package manager query failed, assuming no NFC feature", e); 322 return false; 323 } 324 } 325 326 /** 327 * Returns the NfcAdapter for application context, 328 * or throws if NFC is not available. 329 * @hide 330 */ 331 public static synchronized NfcAdapter getNfcAdapter(Context context) { 332 if (!sIsInitialized) { 333 /* is this device meant to have NFC */ 334 if (!hasNfcFeature()) { 335 Log.v(TAG, "this device does not have NFC support"); 336 throw new UnsupportedOperationException(); 337 } 338 339 sService = getServiceInterface(); 340 if (sService == null) { 341 Log.e(TAG, "could not retrieve NFC service"); 342 throw new UnsupportedOperationException(); 343 } 344 try { 345 sTagService = sService.getNfcTagInterface(); 346 } catch (RemoteException e) { 347 Log.e(TAG, "could not retrieve NFC Tag service"); 348 throw new UnsupportedOperationException(); 349 } 350 351 sIsInitialized = true; 352 } 353 if (context == null) { 354 if (sNullContextNfcAdapter == null) { 355 sNullContextNfcAdapter = new NfcAdapter(null); 356 } 357 return sNullContextNfcAdapter; 358 } 359 NfcAdapter adapter = sNfcAdapters.get(context); 360 if (adapter == null) { 361 adapter = new NfcAdapter(context); 362 sNfcAdapters.put(context, adapter); 363 } 364 return adapter; 365 } 366 367 /** get handle to NFC service interface */ 368 private static INfcAdapter getServiceInterface() { 369 /* get a handle to NFC service */ 370 IBinder b = ServiceManager.getService("nfc"); 371 if (b == null) { 372 return null; 373 } 374 return INfcAdapter.Stub.asInterface(b); 375 } 376 377 /** 378 * Helper to get the default NFC Adapter. 379 * <p> 380 * Most Android devices will only have one NFC Adapter (NFC Controller). 381 * <p> 382 * This helper is the equivalent of: 383 * <pre> 384 * NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE); 385 * NfcAdapter adapter = manager.getDefaultAdapter();</pre> 386 * @param context the calling application's context 387 * 388 * @return the default NFC adapter, or null if no NFC adapter exists 389 */ 390 public static NfcAdapter getDefaultAdapter(Context context) { 391 if (context == null) { 392 throw new IllegalArgumentException("context cannot be null"); 393 } 394 context = context.getApplicationContext(); 395 if (context == null) { 396 throw new IllegalArgumentException( 397 "context not associated with any application (using a mock context?)"); 398 } 399 /* use getSystemService() for consistency */ 400 NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE); 401 if (manager == null) { 402 // NFC not available 403 return null; 404 } 405 return manager.getDefaultAdapter(); 406 } 407 408 /** 409 * Legacy NfcAdapter getter, always use {@link #getDefaultAdapter(Context)} instead.<p> 410 * This method was deprecated at API level 10 (Gingerbread MR1) because a context is required 411 * for many NFC API methods. Those methods will fail when called on an NfcAdapter 412 * object created from this method.<p> 413 * @deprecated use {@link #getDefaultAdapter(Context)} 414 * @hide 415 */ 416 @Deprecated 417 public static NfcAdapter getDefaultAdapter() { 418 // introduced in API version 9 (GB 2.3) 419 // deprecated in API version 10 (GB 2.3.3) 420 // removed from public API in version 16 (ICS MR2) 421 // should maintain as a hidden API for binary compatibility for a little longer 422 Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " + 423 "NfcAdapter.getDefaultAdapter(Context) instead", new Exception()); 424 425 return NfcAdapter.getNfcAdapter(null); 426 } 427 428 NfcAdapter(Context context) { 429 mContext = context; 430 mNfcActivityManager = new NfcActivityManager(this); 431 } 432 433 /** 434 * @hide 435 */ 436 public Context getContext() { 437 return mContext; 438 } 439 440 /** 441 * Returns the binder interface to the service. 442 * @hide 443 */ 444 public INfcAdapter getService() { 445 isEnabled(); // NOP call to recover sService if it is stale 446 return sService; 447 } 448 449 /** 450 * Returns the binder interface to the tag service. 451 * @hide 452 */ 453 public INfcTag getTagService() { 454 isEnabled(); // NOP call to recover sTagService if it is stale 455 return sTagService; 456 } 457 458 /** 459 * NFC service dead - attempt best effort recovery 460 * @hide 461 */ 462 public void attemptDeadServiceRecovery(Exception e) { 463 Log.e(TAG, "NFC service dead - attempting to recover", e); 464 INfcAdapter service = getServiceInterface(); 465 if (service == null) { 466 Log.e(TAG, "could not retrieve NFC service during service recovery"); 467 // nothing more can be done now, sService is still stale, we'll hit 468 // this recovery path again later 469 return; 470 } 471 // assigning to sService is not thread-safe, but this is best-effort code 472 // and on a well-behaved system should never happen 473 sService = service; 474 try { 475 sTagService = service.getNfcTagInterface(); 476 } catch (RemoteException ee) { 477 Log.e(TAG, "could not retrieve NFC tag service during service recovery"); 478 // nothing more can be done now, sService is still stale, we'll hit 479 // this recovery path again later 480 } 481 482 return; 483 } 484 485 /** 486 * Return true if this NFC Adapter has any features enabled. 487 * 488 * <p>If this method returns false, the NFC hardware is guaranteed not to 489 * generate or respond to any NFC communication over its NFC radio. 490 * <p>Applications can use this to check if NFC is enabled. Applications 491 * can request Settings UI allowing the user to toggle NFC using: 492 * <p><pre>startActivity(new Intent(Settings.ACTION_NFC_SETTINGS))</pre> 493 * 494 * @see android.provider.Settings#ACTION_NFC_SETTINGS 495 * @return true if this NFC Adapter has any features enabled 496 */ 497 public boolean isEnabled() { 498 try { 499 return sService.getState() == STATE_ON; 500 } catch (RemoteException e) { 501 attemptDeadServiceRecovery(e); 502 return false; 503 } 504 } 505 506 /** 507 * Return the state of this NFC Adapter. 508 * 509 * <p>Returns one of {@link #STATE_ON}, {@link #STATE_TURNING_ON}, 510 * {@link #STATE_OFF}, {@link #STATE_TURNING_OFF}. 511 * 512 * <p>{@link #isEnabled()} is equivalent to 513 * <code>{@link #getAdapterState()} == {@link #STATE_ON}</code> 514 * 515 * @return the current state of this NFC adapter 516 * 517 * @hide 518 */ 519 public int getAdapterState() { 520 try { 521 return sService.getState(); 522 } catch (RemoteException e) { 523 attemptDeadServiceRecovery(e); 524 return NfcAdapter.STATE_OFF; 525 } 526 } 527 528 /** 529 * Enable NFC hardware. 530 * 531 * <p>This call is asynchronous. Listen for 532 * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the 533 * operation is complete. 534 * 535 * <p>If this returns true, then either NFC is already on, or 536 * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent 537 * to indicate a state transition. If this returns false, then 538 * there is some problem that prevents an attempt to turn 539 * NFC on (for example we are in airplane mode and NFC is not 540 * toggleable in airplane mode on this platform). 541 * 542 * @hide 543 */ 544 public boolean enable() { 545 try { 546 return sService.enable(); 547 } catch (RemoteException e) { 548 attemptDeadServiceRecovery(e); 549 return false; 550 } 551 } 552 553 /** 554 * Disable NFC hardware. 555 * 556 * <p>No NFC features will work after this call, and the hardware 557 * will not perform or respond to any NFC communication. 558 * 559 * <p>This call is asynchronous. Listen for 560 * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the 561 * operation is complete. 562 * 563 * <p>If this returns true, then either NFC is already off, or 564 * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent 565 * to indicate a state transition. If this returns false, then 566 * there is some problem that prevents an attempt to turn 567 * NFC off. 568 * 569 * @hide 570 */ 571 572 public boolean disable() { 573 try { 574 return sService.disable(true); 575 } catch (RemoteException e) { 576 attemptDeadServiceRecovery(e); 577 return false; 578 } 579 } 580 581 /** 582 * Set one or more {@link Uri}s to send using Android Beam (TM). Every 583 * Uri you provide must have either scheme 'file' or scheme 'content'. 584 * 585 * <p>For the data provided through this method, Android Beam tries to 586 * switch to alternate transports such as Bluetooth to achieve a fast 587 * transfer speed. Hence this method is very suitable 588 * for transferring large files such as pictures or songs. 589 * 590 * <p>The receiving side will store the content of each Uri in 591 * a file and present a notification to the user to open the file 592 * with a {@link android.content.Intent} with action 593 * {@link android.content.Intent#ACTION_VIEW}. 594 * If multiple URIs are sent, the {@link android.content.Intent} will refer 595 * to the first of the stored files. 596 * 597 * <p>This method may be called at any time before {@link Activity#onDestroy}, 598 * but the URI(s) are only made available for Android Beam when the 599 * specified activity(s) are in resumed (foreground) state. The recommended 600 * approach is to call this method during your Activity's 601 * {@link Activity#onCreate} - see sample 602 * code below. This method does not immediately perform any I/O or blocking work, 603 * so is safe to call on your main thread. 604 * 605 * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback} 606 * have priority over both {@link #setNdefPushMessage} and 607 * {@link #setNdefPushMessageCallback}. 608 * 609 * <p>If {@link #setBeamPushUris} is called with a null Uri array, 610 * and/or {@link #setBeamPushUrisCallback} is called with a null callback, 611 * then the Uri push will be completely disabled for the specified activity(s). 612 * 613 * <p>Code example: 614 * <pre> 615 * protected void onCreate(Bundle savedInstanceState) { 616 * super.onCreate(savedInstanceState); 617 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 618 * if (nfcAdapter == null) return; // NFC not available on this device 619 * nfcAdapter.setBeamPushUris(new Uri[] {uri1, uri2}, this); 620 * }</pre> 621 * And that is it. Only one call per activity is necessary. The Android 622 * OS will automatically release its references to the Uri(s) and the 623 * Activity object when it is destroyed if you follow this pattern. 624 * 625 * <p>If your Activity wants to dynamically supply Uri(s), 626 * then set a callback using {@link #setBeamPushUrisCallback} instead 627 * of using this method. 628 * 629 * <p class="note">Do not pass in an Activity that has already been through 630 * {@link Activity#onDestroy}. This is guaranteed if you call this API 631 * during {@link Activity#onCreate}. 632 * 633 * <p class="note">If this device does not support alternate transports 634 * such as Bluetooth or WiFI, calling this method does nothing. 635 * 636 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 637 * 638 * @param uris an array of Uri(s) to push over Android Beam 639 * @param activity activity for which the Uri(s) will be pushed 640 */ 641 public void setBeamPushUris(Uri[] uris, Activity activity) { 642 if (activity == null) { 643 throw new NullPointerException("activity cannot be null"); 644 } 645 if (uris != null) { 646 for (Uri uri : uris) { 647 if (uri == null) throw new NullPointerException("Uri not " + 648 "allowed to be null"); 649 String scheme = uri.getScheme(); 650 if (scheme == null || (!scheme.equalsIgnoreCase("file") && 651 !scheme.equalsIgnoreCase("content"))) { 652 throw new IllegalArgumentException("URI needs to have " + 653 "either scheme file or scheme content"); 654 } 655 } 656 } 657 mNfcActivityManager.setNdefPushContentUri(activity, uris); 658 } 659 660 /** 661 * Set a callback that will dynamically generate one or more {@link Uri}s 662 * to send using Android Beam (TM). Every Uri the callback provides 663 * must have either scheme 'file' or scheme 'content'. 664 * 665 * <p>For the data provided through this callback, Android Beam tries to 666 * switch to alternate transports such as Bluetooth to achieve a fast 667 * transfer speed. Hence this method is very suitable 668 * for transferring large files such as pictures or songs. 669 * 670 * <p>The receiving side will store the content of each Uri in 671 * a file and present a notification to the user to open the file 672 * with a {@link android.content.Intent} with action 673 * {@link android.content.Intent#ACTION_VIEW}. 674 * If multiple URIs are sent, the {@link android.content.Intent} will refer 675 * to the first of the stored files. 676 * 677 * <p>This method may be called at any time before {@link Activity#onDestroy}, 678 * but the URI(s) are only made available for Android Beam when the 679 * specified activity(s) are in resumed (foreground) state. The recommended 680 * approach is to call this method during your Activity's 681 * {@link Activity#onCreate} - see sample 682 * code below. This method does not immediately perform any I/O or blocking work, 683 * so is safe to call on your main thread. 684 * 685 * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback} 686 * have priority over both {@link #setNdefPushMessage} and 687 * {@link #setNdefPushMessageCallback}. 688 * 689 * <p>If {@link #setBeamPushUris} is called with a null Uri array, 690 * and/or {@link #setBeamPushUrisCallback} is called with a null callback, 691 * then the Uri push will be completely disabled for the specified activity(s). 692 * 693 * <p>Code example: 694 * <pre> 695 * protected void onCreate(Bundle savedInstanceState) { 696 * super.onCreate(savedInstanceState); 697 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 698 * if (nfcAdapter == null) return; // NFC not available on this device 699 * nfcAdapter.setBeamPushUrisCallback(callback, this); 700 * }</pre> 701 * And that is it. Only one call per activity is necessary. The Android 702 * OS will automatically release its references to the Uri(s) and the 703 * Activity object when it is destroyed if you follow this pattern. 704 * 705 * <p class="note">Do not pass in an Activity that has already been through 706 * {@link Activity#onDestroy}. This is guaranteed if you call this API 707 * during {@link Activity#onCreate}. 708 * 709 * <p class="note">If this device does not support alternate transports 710 * such as Bluetooth or WiFI, calling this method does nothing. 711 * 712 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 713 * 714 * @param callback callback, or null to disable 715 * @param activity activity for which the Uri(s) will be pushed 716 */ 717 public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) { 718 if (activity == null) { 719 throw new NullPointerException("activity cannot be null"); 720 } 721 mNfcActivityManager.setNdefPushContentUriCallback(activity, callback); 722 } 723 724 /** 725 * Set a static {@link NdefMessage} to send using Android Beam (TM). 726 * 727 * <p>This method may be called at any time before {@link Activity#onDestroy}, 728 * but the NDEF message is only made available for NDEF push when the 729 * specified activity(s) are in resumed (foreground) state. The recommended 730 * approach is to call this method during your Activity's 731 * {@link Activity#onCreate} - see sample 732 * code below. This method does not immediately perform any I/O or blocking work, 733 * so is safe to call on your main thread. 734 * 735 * <p>Only one NDEF message can be pushed by the currently resumed activity. 736 * If both {@link #setNdefPushMessage} and 737 * {@link #setNdefPushMessageCallback} are set, then 738 * the callback will take priority. 739 * 740 * <p>If neither {@link #setNdefPushMessage} or 741 * {@link #setNdefPushMessageCallback} have been called for your activity, then 742 * the Android OS may choose to send a default NDEF message on your behalf, 743 * such as a URI for your application. 744 * 745 * <p>If {@link #setNdefPushMessage} is called with a null NDEF message, 746 * and/or {@link #setNdefPushMessageCallback} is called with a null callback, 747 * then NDEF push will be completely disabled for the specified activity(s). 748 * This also disables any default NDEF message the Android OS would have 749 * otherwise sent on your behalf for those activity(s). 750 * 751 * <p>If you want to prevent the Android OS from sending default NDEF 752 * messages completely (for all activities), you can include a 753 * {@code <meta-data>} element inside the {@code <application>} 754 * element of your AndroidManifest.xml file, like this: 755 * <pre> 756 * <application ...> 757 * <meta-data android:name="android.nfc.disable_beam_default" 758 * android:value="true" /> 759 * </application></pre> 760 * 761 * <p>The API allows for multiple activities to be specified at a time, 762 * but it is strongly recommended to just register one at a time, 763 * and to do so during the activity's {@link Activity#onCreate}. For example: 764 * <pre> 765 * protected void onCreate(Bundle savedInstanceState) { 766 * super.onCreate(savedInstanceState); 767 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 768 * if (nfcAdapter == null) return; // NFC not available on this device 769 * nfcAdapter.setNdefPushMessage(ndefMessage, this); 770 * }</pre> 771 * And that is it. Only one call per activity is necessary. The Android 772 * OS will automatically release its references to the NDEF message and the 773 * Activity object when it is destroyed if you follow this pattern. 774 * 775 * <p>If your Activity wants to dynamically generate an NDEF message, 776 * then set a callback using {@link #setNdefPushMessageCallback} instead 777 * of a static message. 778 * 779 * <p class="note">Do not pass in an Activity that has already been through 780 * {@link Activity#onDestroy}. This is guaranteed if you call this API 781 * during {@link Activity#onCreate}. 782 * 783 * <p class="note">For sending large content such as pictures and songs, 784 * consider using {@link #setBeamPushUris}, which switches to alternate transports 785 * such as Bluetooth to achieve a fast transfer rate. 786 * 787 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 788 * 789 * @param message NDEF message to push over NFC, or null to disable 790 * @param activity activity for which the NDEF message will be pushed 791 * @param activities optional additional activities, however we strongly recommend 792 * to only register one at a time, and to do so in that activity's 793 * {@link Activity#onCreate} 794 */ 795 public void setNdefPushMessage(NdefMessage message, Activity activity, 796 Activity ... activities) { 797 int targetSdkVersion = getSdkVersion(); 798 try { 799 if (activity == null) { 800 throw new NullPointerException("activity cannot be null"); 801 } 802 mNfcActivityManager.setNdefPushMessage(activity, message, 0); 803 for (Activity a : activities) { 804 if (a == null) { 805 throw new NullPointerException("activities cannot contain null"); 806 } 807 mNfcActivityManager.setNdefPushMessage(a, message, 0); 808 } 809 } catch (IllegalStateException e) { 810 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { 811 // Less strict on old applications - just log the error 812 Log.e(TAG, "Cannot call API with Activity that has already " + 813 "been destroyed", e); 814 } else { 815 // Prevent new applications from making this mistake, re-throw 816 throw(e); 817 } 818 } 819 } 820 821 /** 822 * @hide 823 */ 824 public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) { 825 if (activity == null) { 826 throw new NullPointerException("activity cannot be null"); 827 } 828 mNfcActivityManager.setNdefPushMessage(activity, message, flags); 829 } 830 831 /** 832 * Set a callback that dynamically generates NDEF messages to send using Android Beam (TM). 833 * 834 * <p>This method may be called at any time before {@link Activity#onDestroy}, 835 * but the NDEF message callback can only occur when the 836 * specified activity(s) are in resumed (foreground) state. The recommended 837 * approach is to call this method during your Activity's 838 * {@link Activity#onCreate} - see sample 839 * code below. This method does not immediately perform any I/O or blocking work, 840 * so is safe to call on your main thread. 841 * 842 * <p>Only one NDEF message can be pushed by the currently resumed activity. 843 * If both {@link #setNdefPushMessage} and 844 * {@link #setNdefPushMessageCallback} are set, then 845 * the callback will take priority. 846 * 847 * <p>If neither {@link #setNdefPushMessage} or 848 * {@link #setNdefPushMessageCallback} have been called for your activity, then 849 * the Android OS may choose to send a default NDEF message on your behalf, 850 * such as a URI for your application. 851 * 852 * <p>If {@link #setNdefPushMessage} is called with a null NDEF message, 853 * and/or {@link #setNdefPushMessageCallback} is called with a null callback, 854 * then NDEF push will be completely disabled for the specified activity(s). 855 * This also disables any default NDEF message the Android OS would have 856 * otherwise sent on your behalf for those activity(s). 857 * 858 * <p>If you want to prevent the Android OS from sending default NDEF 859 * messages completely (for all activities), you can include a 860 * {@code <meta-data>} element inside the {@code <application>} 861 * element of your AndroidManifest.xml file, like this: 862 * <pre> 863 * <application ...> 864 * <meta-data android:name="android.nfc.disable_beam_default" 865 * android:value="true" /> 866 * </application></pre> 867 * 868 * <p>The API allows for multiple activities to be specified at a time, 869 * but it is strongly recommended to just register one at a time, 870 * and to do so during the activity's {@link Activity#onCreate}. For example: 871 * <pre> 872 * protected void onCreate(Bundle savedInstanceState) { 873 * super.onCreate(savedInstanceState); 874 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 875 * if (nfcAdapter == null) return; // NFC not available on this device 876 * nfcAdapter.setNdefPushMessageCallback(callback, this); 877 * }</pre> 878 * And that is it. Only one call per activity is necessary. The Android 879 * OS will automatically release its references to the callback and the 880 * Activity object when it is destroyed if you follow this pattern. 881 * 882 * <p class="note">Do not pass in an Activity that has already been through 883 * {@link Activity#onDestroy}. This is guaranteed if you call this API 884 * during {@link Activity#onCreate}. 885 * <p class="note">For sending large content such as pictures and songs, 886 * consider using {@link #setBeamPushUris}, which switches to alternate transports 887 * such as Bluetooth to achieve a fast transfer rate. 888 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 889 * 890 * @param callback callback, or null to disable 891 * @param activity activity for which the NDEF message will be pushed 892 * @param activities optional additional activities, however we strongly recommend 893 * to only register one at a time, and to do so in that activity's 894 * {@link Activity#onCreate} 895 */ 896 public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, 897 Activity ... activities) { 898 int targetSdkVersion = getSdkVersion(); 899 try { 900 if (activity == null) { 901 throw new NullPointerException("activity cannot be null"); 902 } 903 mNfcActivityManager.setNdefPushMessageCallback(activity, callback, 0); 904 for (Activity a : activities) { 905 if (a == null) { 906 throw new NullPointerException("activities cannot contain null"); 907 } 908 mNfcActivityManager.setNdefPushMessageCallback(a, callback, 0); 909 } 910 } catch (IllegalStateException e) { 911 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { 912 // Less strict on old applications - just log the error 913 Log.e(TAG, "Cannot call API with Activity that has already " + 914 "been destroyed", e); 915 } else { 916 // Prevent new applications from making this mistake, re-throw 917 throw(e); 918 } 919 } 920 } 921 922 /** 923 * @hide 924 */ 925 public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, 926 int flags) { 927 if (activity == null) { 928 throw new NullPointerException("activity cannot be null"); 929 } 930 mNfcActivityManager.setNdefPushMessageCallback(activity, callback, flags); 931 } 932 933 /** 934 * Set a callback on successful Android Beam (TM). 935 * 936 * <p>This method may be called at any time before {@link Activity#onDestroy}, 937 * but the callback can only occur when the 938 * specified activity(s) are in resumed (foreground) state. The recommended 939 * approach is to call this method during your Activity's 940 * {@link Activity#onCreate} - see sample 941 * code below. This method does not immediately perform any I/O or blocking work, 942 * so is safe to call on your main thread. 943 * 944 * <p>The API allows for multiple activities to be specified at a time, 945 * but it is strongly recommended to just register one at a time, 946 * and to do so during the activity's {@link Activity#onCreate}. For example: 947 * <pre> 948 * protected void onCreate(Bundle savedInstanceState) { 949 * super.onCreate(savedInstanceState); 950 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 951 * if (nfcAdapter == null) return; // NFC not available on this device 952 * nfcAdapter.setOnNdefPushCompleteCallback(callback, this); 953 * }</pre> 954 * And that is it. Only one call per activity is necessary. The Android 955 * OS will automatically release its references to the callback and the 956 * Activity object when it is destroyed if you follow this pattern. 957 * 958 * <p class="note">Do not pass in an Activity that has already been through 959 * {@link Activity#onDestroy}. This is guaranteed if you call this API 960 * during {@link Activity#onCreate}. 961 * 962 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 963 * 964 * @param callback callback, or null to disable 965 * @param activity activity for which the NDEF message will be pushed 966 * @param activities optional additional activities, however we strongly recommend 967 * to only register one at a time, and to do so in that activity's 968 * {@link Activity#onCreate} 969 */ 970 public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, 971 Activity activity, Activity ... activities) { 972 int targetSdkVersion = getSdkVersion(); 973 try { 974 if (activity == null) { 975 throw new NullPointerException("activity cannot be null"); 976 } 977 mNfcActivityManager.setOnNdefPushCompleteCallback(activity, callback); 978 for (Activity a : activities) { 979 if (a == null) { 980 throw new NullPointerException("activities cannot contain null"); 981 } 982 mNfcActivityManager.setOnNdefPushCompleteCallback(a, callback); 983 } 984 } catch (IllegalStateException e) { 985 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) { 986 // Less strict on old applications - just log the error 987 Log.e(TAG, "Cannot call API with Activity that has already " + 988 "been destroyed", e); 989 } else { 990 // Prevent new applications from making this mistake, re-throw 991 throw(e); 992 } 993 } 994 } 995 996 /** 997 * Enable foreground dispatch to the given Activity. 998 * 999 * <p>This will give give priority to the foreground activity when 1000 * dispatching a discovered {@link Tag} to an application. 1001 * 1002 * <p>If any IntentFilters are provided to this method they are used to match dispatch Intents 1003 * for both the {@link NfcAdapter#ACTION_NDEF_DISCOVERED} and 1004 * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. Since {@link NfcAdapter#ACTION_TECH_DISCOVERED} 1005 * relies on meta data outside of the IntentFilter matching for that dispatch Intent is handled 1006 * by passing in the tech lists separately. Each first level entry in the tech list represents 1007 * an array of technologies that must all be present to match. If any of the first level sets 1008 * match then the dispatch is routed through the given PendingIntent. In other words, the second 1009 * level is ANDed together and the first level entries are ORed together. 1010 * 1011 * <p>If you pass {@code null} for both the {@code filters} and {@code techLists} parameters 1012 * that acts a wild card and will cause the foreground activity to receive all tags via the 1013 * {@link NfcAdapter#ACTION_TAG_DISCOVERED} intent. 1014 * 1015 * <p>This method must be called from the main thread, and only when the activity is in the 1016 * foreground (resumed). Also, activities must call {@link #disableForegroundDispatch} before 1017 * the completion of their {@link Activity#onPause} callback to disable foreground dispatch 1018 * after it has been enabled. 1019 * 1020 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1021 * 1022 * @param activity the Activity to dispatch to 1023 * @param intent the PendingIntent to start for the dispatch 1024 * @param filters the IntentFilters to override dispatching for, or null to always dispatch 1025 * @param techLists the tech lists used to perform matching for dispatching of the 1026 * {@link NfcAdapter#ACTION_TECH_DISCOVERED} intent 1027 * @throws IllegalStateException if the Activity is not currently in the foreground 1028 */ 1029 public void enableForegroundDispatch(Activity activity, PendingIntent intent, 1030 IntentFilter[] filters, String[][] techLists) { 1031 if (activity == null || intent == null) { 1032 throw new NullPointerException(); 1033 } 1034 if (!activity.isResumed()) { 1035 throw new IllegalStateException("Foreground dispatch can only be enabled " + 1036 "when your activity is resumed"); 1037 } 1038 try { 1039 TechListParcel parcel = null; 1040 if (techLists != null && techLists.length > 0) { 1041 parcel = new TechListParcel(techLists); 1042 } 1043 ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity, 1044 mForegroundDispatchListener); 1045 sService.setForegroundDispatch(intent, filters, parcel); 1046 } catch (RemoteException e) { 1047 attemptDeadServiceRecovery(e); 1048 } 1049 } 1050 1051 /** 1052 * Disable foreground dispatch to the given activity. 1053 * 1054 * <p>After calling {@link #enableForegroundDispatch}, an activity 1055 * must call this method before its {@link Activity#onPause} callback 1056 * completes. 1057 * 1058 * <p>This method must be called from the main thread. 1059 * 1060 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1061 * 1062 * @param activity the Activity to disable dispatch to 1063 * @throws IllegalStateException if the Activity has already been paused 1064 */ 1065 public void disableForegroundDispatch(Activity activity) { 1066 ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity, 1067 mForegroundDispatchListener); 1068 disableForegroundDispatchInternal(activity, false); 1069 } 1070 1071 OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() { 1072 @Override 1073 public void onPaused(Activity activity) { 1074 disableForegroundDispatchInternal(activity, true); 1075 } 1076 }; 1077 1078 void disableForegroundDispatchInternal(Activity activity, boolean force) { 1079 try { 1080 sService.setForegroundDispatch(null, null, null); 1081 if (!force && !activity.isResumed()) { 1082 throw new IllegalStateException("You must disable foreground dispatching " + 1083 "while your activity is still resumed"); 1084 } 1085 } catch (RemoteException e) { 1086 attemptDeadServiceRecovery(e); 1087 } 1088 } 1089 1090 /** 1091 * Enable NDEF message push over NFC while this Activity is in the foreground. 1092 * 1093 * <p>You must explicitly call this method every time the activity is 1094 * resumed, and you must call {@link #disableForegroundNdefPush} before 1095 * your activity completes {@link Activity#onPause}. 1096 * 1097 * <p>Strongly recommend to use the new {@link #setNdefPushMessage} 1098 * instead: it automatically hooks into your activity life-cycle, 1099 * so you do not need to call enable/disable in your onResume/onPause. 1100 * 1101 * <p>For NDEF push to function properly the other NFC device must 1102 * support either NFC Forum's SNEP (Simple Ndef Exchange Protocol), or 1103 * Android's "com.android.npp" (Ndef Push Protocol). This was optional 1104 * on Gingerbread level Android NFC devices, but SNEP is mandatory on 1105 * Ice-Cream-Sandwich and beyond. 1106 * 1107 * <p>This method must be called from the main thread. 1108 * 1109 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1110 * 1111 * @param activity foreground activity 1112 * @param message a NDEF Message to push over NFC 1113 * @throws IllegalStateException if the activity is not currently in the foreground 1114 * @deprecated use {@link #setNdefPushMessage} instead 1115 */ 1116 @Deprecated 1117 public void enableForegroundNdefPush(Activity activity, NdefMessage message) { 1118 if (activity == null || message == null) { 1119 throw new NullPointerException(); 1120 } 1121 enforceResumed(activity); 1122 mNfcActivityManager.setNdefPushMessage(activity, message, 0); 1123 } 1124 1125 /** 1126 * Disable NDEF message push over P2P. 1127 * 1128 * <p>After calling {@link #enableForegroundNdefPush}, an activity 1129 * must call this method before its {@link Activity#onPause} callback 1130 * completes. 1131 * 1132 * <p>Strongly recommend to use the new {@link #setNdefPushMessage} 1133 * instead: it automatically hooks into your activity life-cycle, 1134 * so you do not need to call enable/disable in your onResume/onPause. 1135 * 1136 * <p>This method must be called from the main thread. 1137 * 1138 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 1139 * 1140 * @param activity the Foreground activity 1141 * @throws IllegalStateException if the Activity has already been paused 1142 * @deprecated use {@link #setNdefPushMessage} instead 1143 */ 1144 @Deprecated 1145 public void disableForegroundNdefPush(Activity activity) { 1146 if (activity == null) { 1147 throw new NullPointerException(); 1148 } 1149 enforceResumed(activity); 1150 mNfcActivityManager.setNdefPushMessage(activity, null, 0); 1151 mNfcActivityManager.setNdefPushMessageCallback(activity, null, 0); 1152 mNfcActivityManager.setOnNdefPushCompleteCallback(activity, null); 1153 } 1154 1155 /** 1156 * Enable NDEF Push feature. 1157 * <p>This API is for the Settings application. 1158 * @hide 1159 */ 1160 public boolean enableNdefPush() { 1161 try { 1162 return sService.enableNdefPush(); 1163 } catch (RemoteException e) { 1164 attemptDeadServiceRecovery(e); 1165 return false; 1166 } 1167 } 1168 1169 /** 1170 * Disable NDEF Push feature. 1171 * <p>This API is for the Settings application. 1172 * @hide 1173 */ 1174 public boolean disableNdefPush() { 1175 try { 1176 return sService.disableNdefPush(); 1177 } catch (RemoteException e) { 1178 attemptDeadServiceRecovery(e); 1179 return false; 1180 } 1181 } 1182 1183 /** 1184 * Return true if the NDEF Push (Android Beam) feature is enabled. 1185 * <p>This function will return true only if both NFC is enabled, and the 1186 * NDEF Push feature is enabled. 1187 * <p>Note that if NFC is enabled but NDEF Push is disabled then this 1188 * device can still <i>receive</i> NDEF messages, it just cannot send them. 1189 * <p>Applications cannot directly toggle the NDEF Push feature, but they 1190 * can request Settings UI allowing the user to toggle NDEF Push using 1191 * <code>startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS))</code> 1192 * <p>Example usage in an Activity that requires NDEF Push: 1193 * <p><pre> 1194 * protected void onResume() { 1195 * super.onResume(); 1196 * if (!nfcAdapter.isEnabled()) { 1197 * startActivity(new Intent(Settings.ACTION_NFC_SETTINGS)); 1198 * } else if (!nfcAdapter.isNdefPushEnabled()) { 1199 * startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS)); 1200 * } 1201 * }</pre> 1202 * 1203 * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS 1204 * @return true if NDEF Push feature is enabled 1205 */ 1206 public boolean isNdefPushEnabled() { 1207 try { 1208 return sService.isNdefPushEnabled(); 1209 } catch (RemoteException e) { 1210 attemptDeadServiceRecovery(e); 1211 return false; 1212 } 1213 } 1214 1215 /** 1216 * Inject a mock NFC tag.<p> 1217 * Used for testing purposes. 1218 * <p class="note">Requires the 1219 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission. 1220 * @hide 1221 */ 1222 public void dispatch(Tag tag) { 1223 if (tag == null) { 1224 throw new NullPointerException("tag cannot be null"); 1225 } 1226 try { 1227 sService.dispatch(tag); 1228 } catch (RemoteException e) { 1229 attemptDeadServiceRecovery(e); 1230 } 1231 } 1232 1233 /** 1234 * @hide 1235 */ 1236 public void setP2pModes(int initiatorModes, int targetModes) { 1237 try { 1238 sService.setP2pModes(initiatorModes, targetModes); 1239 } catch (RemoteException e) { 1240 attemptDeadServiceRecovery(e); 1241 } 1242 } 1243 1244 /** 1245 * @hide 1246 */ 1247 public INfcAdapterExtras getNfcAdapterExtrasInterface() { 1248 if (mContext == null) { 1249 throw new UnsupportedOperationException("You need a context on NfcAdapter to use the " 1250 + " NFC extras APIs"); 1251 } 1252 try { 1253 return sService.getNfcAdapterExtrasInterface(mContext.getPackageName()); 1254 } catch (RemoteException e) { 1255 attemptDeadServiceRecovery(e); 1256 return null; 1257 } 1258 } 1259 1260 void enforceResumed(Activity activity) { 1261 if (!activity.isResumed()) { 1262 throw new IllegalStateException("API cannot be called while activity is paused"); 1263 } 1264 } 1265 1266 int getSdkVersion() { 1267 if (mContext == null) { 1268 return android.os.Build.VERSION_CODES.GINGERBREAD; // best guess 1269 } else { 1270 return mContext.getApplicationInfo().targetSdkVersion; 1271 } 1272 } 1273 } 1274