blob: e8b74377910d2fddff5cba77ecdf07d9aa7ae9b6 [file] [log] [blame]
Nick Pelly590b73b2010-10-12 13:00:50 -07001/*
Daniel Tomas90245642010-11-17 10:07:52 +01002 * 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.
Nick Pelly590b73b2010-10-12 13:00:50 -070015 */
16
17package android.nfc;
18
Jeff Hamiltonbb951c82011-11-08 16:55:13 -060019import java.util.HashMap;
20
Nick Pelly590b73b2010-10-12 13:00:50 -070021import android.annotation.SdkConstant;
22import android.annotation.SdkConstant.SdkConstantType;
Jeff Hamilton52d32032011-01-08 15:31:26 -060023import android.app.Activity;
Nick Pellyfdf90862010-10-18 11:19:41 -070024import android.app.ActivityThread;
Jeff Hamilton52d32032011-01-08 15:31:26 -060025import android.app.OnActivityPausedListener;
26import android.app.PendingIntent;
Nick Pelly50b4d8f2010-12-07 22:40:28 -080027import android.content.Context;
Jeff Hamilton52d32032011-01-08 15:31:26 -060028import android.content.IntentFilter;
Nick Pellyfdf90862010-10-18 11:19:41 -070029import android.content.pm.IPackageManager;
30import android.content.pm.PackageManager;
Nick Pelly1d7e9062012-04-03 17:46:00 -070031import android.net.Uri;
Jeff Hamilton28319c02011-02-09 17:26:47 +090032import android.nfc.tech.MifareClassic;
33import android.nfc.tech.Ndef;
34import android.nfc.tech.NfcA;
35import android.nfc.tech.NfcF;
Martijn Coenen5b1e0322013-09-02 20:38:47 -070036import android.os.Bundle;
Nick Pelly590b73b2010-10-12 13:00:50 -070037import android.os.IBinder;
38import android.os.RemoteException;
39import android.os.ServiceManager;
40import android.util.Log;
41
Nick Pelly590b73b2010-10-12 13:00:50 -070042/**
Nick Pelly74fe6c62011-02-02 22:37:40 -080043 * Represents the local NFC adapter.
Nick Pelly590b73b2010-10-12 13:00:50 -070044 * <p>
Nick Pelly50b4d8f2010-12-07 22:40:28 -080045 * Use the helper {@link #getDefaultAdapter(Context)} to get the default NFC
46 * adapter for this Android device.
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080047 *
48 * <div class="special reference">
49 * <h3>Developer Guides</h3>
50 * <p>For more information about using NFC, read the
51 * <a href="{@docRoot}guide/topics/nfc/index.html">Near Field Communication</a> developer guide.</p>
Scott Mainb38ad762013-10-17 11:57:06 -070052 * <p>To perform basic file sharing between devices, read
53 * <a href="{@docRoot}training/beam-files/index.html">Sharing Files with NFC</a>.
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080054 * </div>
Nick Pelly590b73b2010-10-12 13:00:50 -070055 */
56public final class NfcAdapter {
Nick Pellyc84c89a2011-08-22 22:27:11 -070057 static final String TAG = "NFC";
Nick Pelly50b4d8f2010-12-07 22:40:28 -080058
Nick Pelly590b73b2010-10-12 13:00:50 -070059 /**
Jeff Hamilton641dd622010-12-02 09:16:22 -060060 * Intent to start an activity when a tag with NDEF payload is discovered.
Jeff Hamilton641dd622010-12-02 09:16:22 -060061 *
Jeff Hamilton28319c02011-02-09 17:26:47 +090062 * <p>The system inspects the first {@link NdefRecord} in the first {@link NdefMessage} and
63 * looks for a URI, SmartPoster, or MIME record. If a URI or SmartPoster record is found the
64 * intent will contain the URI in its data field. If a MIME record is found the intent will
65 * contain the MIME type in its type field. This allows activities to register
66 * {@link IntentFilter}s targeting specific content on tags. Activities should register the
67 * most specific intent filters possible to avoid the activity chooser dialog, which can
68 * disrupt the interaction with the tag as the user interacts with the screen.
69 *
70 * <p>If the tag has an NDEF payload this intent is started before
71 * {@link #ACTION_TECH_DISCOVERED}. If any activities respond to this intent neither
Nick Pellyf003e262011-01-31 23:27:37 -080072 * {@link #ACTION_TECH_DISCOVERED} or {@link #ACTION_TAG_DISCOVERED} will be started.
Nick Pellyc97a5522012-01-05 15:13:01 +110073 *
74 * <p>The MIME type or data URI of this intent are normalized before dispatch -
75 * so that MIME, URI scheme and URI host are always lower-case.
Jeff Hamilton641dd622010-12-02 09:16:22 -060076 */
77 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
78 public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
79
80 /**
Jeff Hamilton28319c02011-02-09 17:26:47 +090081 * Intent to start an activity when a tag is discovered and activities are registered for the
82 * specific technologies on the tag.
Jeff Hamilton641dd622010-12-02 09:16:22 -060083 *
Jeff Hamilton28319c02011-02-09 17:26:47 +090084 * <p>To receive this intent an activity must include an intent filter
85 * for this action and specify the desired tech types in a
86 * manifest <code>meta-data</code> entry. Here is an example manfiest entry:
87 * <pre>
Scott Main97e0a1c2012-06-25 11:22:10 -070088 * &lt;activity android:name=".nfc.TechFilter" android:label="NFC/TechFilter"&gt;
89 * &lt;!-- Add a technology filter --&gt;
90 * &lt;intent-filter&gt;
91 * &lt;action android:name="android.nfc.action.TECH_DISCOVERED" /&gt;
92 * &lt;/intent-filter&gt;
Jeff Hamilton641dd622010-12-02 09:16:22 -060093 *
Scott Main97e0a1c2012-06-25 11:22:10 -070094 * &lt;meta-data android:name="android.nfc.action.TECH_DISCOVERED"
95 * android:resource="@xml/filter_nfc"
96 * /&gt;
97 * &lt;/activity&gt;</pre>
Jeff Hamilton28319c02011-02-09 17:26:47 +090098 *
99 * <p>The meta-data XML file should contain one or more <code>tech-list</code> entries
100 * each consisting or one or more <code>tech</code> entries. The <code>tech</code> entries refer
101 * to the qualified class name implementing the technology, for example "android.nfc.tech.NfcA".
102 *
103 * <p>A tag matches if any of the
104 * <code>tech-list</code> sets is a subset of {@link Tag#getTechList() Tag.getTechList()}. Each
105 * of the <code>tech-list</code>s is considered independently and the
106 * activity is considered a match is any single <code>tech-list</code> matches the tag that was
107 * discovered. This provides AND and OR semantics for filtering desired techs. Here is an
108 * example that will match any tag using {@link NfcF} or any tag using {@link NfcA},
109 * {@link MifareClassic}, and {@link Ndef}:
110 *
111 * <pre>
112 * &lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
113 * &lt;!-- capture anything using NfcF --&gt;
114 * &lt;tech-list&gt;
115 * &lt;tech&gt;android.nfc.tech.NfcF&lt;/tech&gt;
116 * &lt;/tech-list&gt;
117 *
118 * &lt;!-- OR --&gt;
119 *
120 * &lt;!-- capture all MIFARE Classics with NDEF payloads --&gt;
121 * &lt;tech-list&gt;
122 * &lt;tech&gt;android.nfc.tech.NfcA&lt;/tech&gt;
123 * &lt;tech&gt;android.nfc.tech.MifareClassic&lt;/tech&gt;
124 * &lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
125 * &lt;/tech-list&gt;
Scott Main97e0a1c2012-06-25 11:22:10 -0700126 * &lt;/resources&gt;</pre>
Jeff Hamilton28319c02011-02-09 17:26:47 +0900127 *
128 * <p>This intent is started after {@link #ACTION_NDEF_DISCOVERED} and before
129 * {@link #ACTION_TAG_DISCOVERED}. If any activities respond to {@link #ACTION_NDEF_DISCOVERED}
130 * this intent will not be started. If any activities respond to this intent
131 * {@link #ACTION_TAG_DISCOVERED} will not be started.
Jeff Hamilton641dd622010-12-02 09:16:22 -0600132 */
133 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
Nick Pellyf003e262011-01-31 23:27:37 -0800134 public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
Jeff Hamilton641dd622010-12-02 09:16:22 -0600135
136 /**
Nick Pelly11b075e2010-10-28 13:39:37 -0700137 * Intent to start an activity when a tag is discovered.
Jeff Hamilton28319c02011-02-09 17:26:47 +0900138 *
139 * <p>This intent will not be started when a tag is discovered if any activities respond to
Jason parks01425362011-05-24 02:57:37 -0700140 * {@link #ACTION_NDEF_DISCOVERED} or {@link #ACTION_TECH_DISCOVERED} for the current tag.
Nick Pelly590b73b2010-10-12 13:00:50 -0700141 */
142 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
143 public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
144
145 /**
Jeff Hamilton6be655c2010-11-12 12:28:16 -0600146 * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED
147 * @hide
148 */
149 public static final String ACTION_TAG_LEFT_FIELD = "android.nfc.action.TAG_LOST";
150
151 /**
Jeff Hamilton28319c02011-02-09 17:26:47 +0900152 * Mandatory extra containing the {@link Tag} that was discovered for the
153 * {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and
154 * {@link #ACTION_TAG_DISCOVERED} intents.
Nick Pelly590b73b2010-10-12 13:00:50 -0700155 */
156 public static final String EXTRA_TAG = "android.nfc.extra.TAG";
157
158 /**
Nick Pellyc97a5522012-01-05 15:13:01 +1100159 * Extra containing an array of {@link NdefMessage} present on the discovered tag.<p>
160 * This extra is mandatory for {@link #ACTION_NDEF_DISCOVERED} intents,
161 * and optional for {@link #ACTION_TECH_DISCOVERED}, and
162 * {@link #ACTION_TAG_DISCOVERED} intents.<p>
163 * When this extra is present there will always be at least one
164 * {@link NdefMessage} element. Most NDEF tags have only one NDEF message,
165 * but we use an array for future compatibility.
Nick Pelly11b075e2010-10-28 13:39:37 -0700166 */
167 public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
168
169 /**
Jeff Hamilton28319c02011-02-09 17:26:47 +0900170 * Optional extra containing a byte array containing the ID of the discovered tag for
171 * the {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and
172 * {@link #ACTION_TAG_DISCOVERED} intents.
Nick Pelly11b075e2010-10-28 13:39:37 -0700173 */
174 public static final String EXTRA_ID = "android.nfc.extra.ID";
175
176 /**
Nick Pelly8d32a012011-08-09 07:03:49 -0700177 * Broadcast Action: The state of the local NFC adapter has been
178 * changed.
179 * <p>For example, NFC has been turned on or off.
Martijn Coenen4ba5eaf2013-01-08 12:49:47 -0800180 * <p>Always contains the extra field {@link #EXTRA_ADAPTER_STATE}
Brad Fitzpatrickafb082d2010-10-18 14:02:58 -0700181 */
Nick Pelly8d32a012011-08-09 07:03:49 -0700182 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
183 public static final String ACTION_ADAPTER_STATE_CHANGED =
184 "android.nfc.action.ADAPTER_STATE_CHANGED";
Brad Fitzpatrickafb082d2010-10-18 14:02:58 -0700185
186 /**
Martijn Coenen4ba5eaf2013-01-08 12:49:47 -0800187 * Used as an int extra field in {@link #ACTION_ADAPTER_STATE_CHANGED}
Nick Pelly8d32a012011-08-09 07:03:49 -0700188 * intents to request the current power state. Possible values are:
189 * {@link #STATE_OFF},
190 * {@link #STATE_TURNING_ON},
191 * {@link #STATE_ON},
192 * {@link #STATE_TURNING_OFF},
Brad Fitzpatrickafb082d2010-10-18 14:02:58 -0700193 */
Nick Pelly8d32a012011-08-09 07:03:49 -0700194 public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE";
195
Nick Pelly8d32a012011-08-09 07:03:49 -0700196 public static final int STATE_OFF = 1;
Nick Pelly8d32a012011-08-09 07:03:49 -0700197 public static final int STATE_TURNING_ON = 2;
Nick Pelly8d32a012011-08-09 07:03:49 -0700198 public static final int STATE_ON = 3;
Nick Pelly8d32a012011-08-09 07:03:49 -0700199 public static final int STATE_TURNING_OFF = 4;
Brad Fitzpatrickafb082d2010-10-18 14:02:58 -0700200
Martijn Coenenc20ed2f2013-08-27 14:32:53 -0700201 /**
Martijn Coenen5b1e0322013-09-02 20:38:47 -0700202 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
Martijn Coenenc20ed2f2013-08-27 14:32:53 -0700203 * <p>
204 * Setting this flag enables polling for Nfc-A technology.
205 */
206 public static final int FLAG_READER_NFC_A = 0x1;
207
208 /**
Martijn Coenen5b1e0322013-09-02 20:38:47 -0700209 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
Martijn Coenenc20ed2f2013-08-27 14:32:53 -0700210 * <p>
211 * Setting this flag enables polling for Nfc-B technology.
212 */
213 public static final int FLAG_READER_NFC_B = 0x2;
214
215 /**
Martijn Coenen5b1e0322013-09-02 20:38:47 -0700216 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
Martijn Coenenc20ed2f2013-08-27 14:32:53 -0700217 * <p>
218 * Setting this flag enables polling for Nfc-F technology.
219 */
220 public static final int FLAG_READER_NFC_F = 0x4;
221
222 /**
Martijn Coenen5b1e0322013-09-02 20:38:47 -0700223 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
Martijn Coenenc20ed2f2013-08-27 14:32:53 -0700224 * <p>
225 * Setting this flag enables polling for Nfc-V (ISO15693) technology.
226 */
227 public static final int FLAG_READER_NFC_V = 0x8;
228
229 /**
Martijn Coenen5b1e0322013-09-02 20:38:47 -0700230 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
Martijn Coenenc20ed2f2013-08-27 14:32:53 -0700231 * <p>
Martijn Coenenb523bfa2013-09-12 13:44:39 +0200232 * Setting this flag enables polling for NfcBarcode technology.
Martijn Coenenc20ed2f2013-08-27 14:32:53 -0700233 */
Martijn Coenenb523bfa2013-09-12 13:44:39 +0200234 public static final int FLAG_READER_NFC_BARCODE = 0x10;
Martijn Coenenc20ed2f2013-08-27 14:32:53 -0700235
236 /**
Martijn Coenen5b1e0322013-09-02 20:38:47 -0700237 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
Martijn Coenenc20ed2f2013-08-27 14:32:53 -0700238 * <p>
239 * Setting this flag allows the caller to prevent the
240 * platform from performing an NDEF check on the tags it
241 * finds.
242 */
243 public static final int FLAG_READER_SKIP_NDEF_CHECK = 0x80;
244
Martijn Coenen5b1e0322013-09-02 20:38:47 -0700245 /**
246 * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
247 * <p>
248 * Setting this flag allows the caller to prevent the
249 * platform from playing sounds when it discovers a tag.
250 */
251 public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 0x100;
252
253 /**
254 * Int Extra for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
255 * <p>
256 * Setting this integer extra allows the calling application to specify
257 * the delay that the platform will use for performing presence checks
258 * on any discovered tag.
259 */
260 public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
261
Martijn Coenen20e8dd92012-04-12 16:37:18 -0700262 /** @hide */
Martijn Coenen1fa2aff2013-02-27 09:21:22 -0800263 public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1;
264
265 /** @hide */
Martijn Coenen20e8dd92012-04-12 16:37:18 -0700266 public static final String ACTION_HANDOVER_TRANSFER_STARTED =
267 "android.nfc.action.HANDOVER_TRANSFER_STARTED";
268
269 /** @hide */
270 public static final String ACTION_HANDOVER_TRANSFER_DONE =
271 "android.nfc.action.HANDOVER_TRANSFER_DONE";
272
273 /** @hide */
274 public static final String EXTRA_HANDOVER_TRANSFER_STATUS =
275 "android.nfc.extra.HANDOVER_TRANSFER_STATUS";
276
277 /** @hide */
278 public static final int HANDOVER_TRANSFER_STATUS_SUCCESS = 0;
279 /** @hide */
280 public static final int HANDOVER_TRANSFER_STATUS_FAILURE = 1;
281
282 /** @hide */
283 public static final String EXTRA_HANDOVER_TRANSFER_URI =
284 "android.nfc.extra.HANDOVER_TRANSFER_URI";
285
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800286 // Guarded by NfcAdapter.class
Nick Pellyc84c89a2011-08-22 22:27:11 -0700287 static boolean sIsInitialized = false;
Nick Pelly590b73b2010-10-12 13:00:50 -0700288
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800289 // Final after first constructor, except for
290 // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
291 // recovery
Nick Pellyc84c89a2011-08-22 22:27:11 -0700292 static INfcAdapter sService;
293 static INfcTag sTagService;
Martijn Coenena7397882013-07-30 20:07:47 -0700294 static INfcCardEmulation sCardEmulationService;
Andres Morales38a7ed02013-11-14 19:02:56 -0800295 static INfcUnlockSettings sNfcUnlockSettingsService;
Nick Pellyc84c89a2011-08-22 22:27:11 -0700296
297 /**
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600298 * The NfcAdapter object for each application context.
299 * There is a 1-1 relationship between application context and
300 * NfcAdapter object.
Nick Pellyc84c89a2011-08-22 22:27:11 -0700301 */
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600302 static HashMap<Context, NfcAdapter> sNfcAdapters = new HashMap(); //guard by NfcAdapter.class
303
304 /**
305 * NfcAdapter used with a null context. This ctor was deprecated but we have
306 * to support it for backwards compatibility. New methods that require context
307 * might throw when called on the null-context NfcAdapter.
308 */
309 static NfcAdapter sNullContextNfcAdapter; // protected by NfcAdapter.class
Nick Pellyc84c89a2011-08-22 22:27:11 -0700310
311 final NfcActivityManager mNfcActivityManager;
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600312 final Context mContext;
Nick Pellyc84c89a2011-08-22 22:27:11 -0700313
314 /**
Scott Mainb38ad762013-10-17 11:57:06 -0700315 * A callback to be invoked when the system finds a tag while the foreground activity is
316 * operating in reader mode.
317 * <p>Register your {@code ReaderCallback} implementation with {@link
318 * NfcAdapter#enableReaderMode} and disable it with {@link
319 * NfcAdapter#disableReaderMode}.
320 * @see NfcAdapter#enableReaderMode
Martijn Coenen5b1e0322013-09-02 20:38:47 -0700321 */
322 public interface ReaderCallback {
323 public void onTagDiscovered(Tag tag);
324 }
325
326 /**
Scott Main2d68a6b2011-09-26 22:59:38 -0700327 * A callback to be invoked when the system successfully delivers your {@link NdefMessage}
328 * to another device.
329 * @see #setOnNdefPushCompleteCallback
Nick Pellyc84c89a2011-08-22 22:27:11 -0700330 */
331 public interface OnNdefPushCompleteCallback {
332 /**
333 * Called on successful NDEF push.
334 *
335 * <p>This callback is usually made on a binder thread (not the UI thread).
336 *
337 * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set
Scott Main2d68a6b2011-09-26 22:59:38 -0700338 * @see #setNdefPushMessageCallback
Nick Pellyc84c89a2011-08-22 22:27:11 -0700339 */
340 public void onNdefPushComplete(NfcEvent event);
341 }
342
343 /**
Scott Main2d68a6b2011-09-26 22:59:38 -0700344 * A callback to be invoked when another NFC device capable of NDEF push (Android Beam)
345 * is within range.
346 * <p>Implement this interface and pass it to {@link
347 * NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()} in order to create an
348 * {@link NdefMessage} at the moment that another device is within range for NFC. Using this
349 * callback allows you to create a message with data that might vary based on the
350 * content currently visible to the user. Alternatively, you can call {@link
351 * #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the
352 * same data.
Nick Pellyc84c89a2011-08-22 22:27:11 -0700353 */
354 public interface CreateNdefMessageCallback {
355 /**
356 * Called to provide a {@link NdefMessage} to push.
357 *
358 * <p>This callback is usually made on a binder thread (not the UI thread).
359 *
360 * <p>Called when this device is in range of another device
361 * that might support NDEF push. It allows the application to
362 * create the NDEF message only when it is required.
363 *
364 * <p>NDEF push cannot occur until this method returns, so do not
365 * block for too long.
366 *
367 * <p>The Android operating system will usually show a system UI
368 * on top of your activity during this time, so do not try to request
369 * input from the user to complete the callback, or provide custom NDEF
370 * push UI. The user probably will not see it.
371 *
372 * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set
373 * @return NDEF message to push, or null to not provide a message
374 */
375 public NdefMessage createNdefMessage(NfcEvent event);
376 }
Nick Pelly590b73b2010-10-12 13:00:50 -0700377
Martijn Coenen20e8dd92012-04-12 16:37:18 -0700378
379 // TODO javadoc
380 public interface CreateBeamUrisCallback {
381 public Uri[] createBeamUris(NfcEvent event);
382 }
383
Nick Pelly590b73b2010-10-12 13:00:50 -0700384 /**
Nick Pellyfdf90862010-10-18 11:19:41 -0700385 * Helper to check if this device has FEATURE_NFC, but without using
386 * a context.
387 * Equivalent to
388 * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)
389 */
390 private static boolean hasNfcFeature() {
391 IPackageManager pm = ActivityThread.getPackageManager();
392 if (pm == null) {
393 Log.e(TAG, "Cannot get package manager, assuming no NFC feature");
394 return false;
395 }
396 try {
397 return pm.hasSystemFeature(PackageManager.FEATURE_NFC);
398 } catch (RemoteException e) {
399 Log.e(TAG, "Package manager query failed, assuming no NFC feature", e);
400 return false;
401 }
402 }
403
Nick Pellyc84c89a2011-08-22 22:27:11 -0700404 /**
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600405 * Returns the NfcAdapter for application context,
406 * or throws if NFC is not available.
407 * @hide
Nick Pellyc84c89a2011-08-22 22:27:11 -0700408 */
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600409 public static synchronized NfcAdapter getNfcAdapter(Context context) {
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800410 if (!sIsInitialized) {
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800411 /* is this device meant to have NFC */
412 if (!hasNfcFeature()) {
413 Log.v(TAG, "this device does not have NFC support");
Nick Pellyc84c89a2011-08-22 22:27:11 -0700414 throw new UnsupportedOperationException();
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800415 }
416
417 sService = getServiceInterface();
418 if (sService == null) {
419 Log.e(TAG, "could not retrieve NFC service");
Nick Pellyc84c89a2011-08-22 22:27:11 -0700420 throw new UnsupportedOperationException();
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800421 }
Nick Pelly3dd6c452011-01-10 18:14:41 +1100422 try {
423 sTagService = sService.getNfcTagInterface();
424 } catch (RemoteException e) {
425 Log.e(TAG, "could not retrieve NFC Tag service");
Nick Pellyc84c89a2011-08-22 22:27:11 -0700426 throw new UnsupportedOperationException();
Nick Pelly3dd6c452011-01-10 18:14:41 +1100427 }
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600428
Martijn Coenena7397882013-07-30 20:07:47 -0700429 try {
430 sCardEmulationService = sService.getNfcCardEmulationInterface();
431 } catch (RemoteException e) {
432 Log.e(TAG, "could not retrieve card emulation service");
433 throw new UnsupportedOperationException();
434 }
435
Andres Morales38a7ed02013-11-14 19:02:56 -0800436 try {
437 sNfcUnlockSettingsService = sService.getNfcUnlockSettingsInterface();
438 } catch (RemoteException e) {
439 Log.e(TAG, "could not retrieve NFC unlock settings service");
440 sNfcUnlockSettingsService = null;
441 }
442
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600443 sIsInitialized = true;
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800444 }
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600445 if (context == null) {
446 if (sNullContextNfcAdapter == null) {
447 sNullContextNfcAdapter = new NfcAdapter(null);
448 }
449 return sNullContextNfcAdapter;
Nick Pellyc84c89a2011-08-22 22:27:11 -0700450 }
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600451 NfcAdapter adapter = sNfcAdapters.get(context);
452 if (adapter == null) {
453 adapter = new NfcAdapter(context);
454 sNfcAdapters.put(context, adapter);
455 }
456 return adapter;
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800457 }
458
Nick Pelly6d55e132010-10-27 01:14:43 -0700459 /** get handle to NFC service interface */
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800460 private static INfcAdapter getServiceInterface() {
Nick Pelly6d55e132010-10-27 01:14:43 -0700461 /* get a handle to NFC service */
462 IBinder b = ServiceManager.getService("nfc");
463 if (b == null) {
464 return null;
465 }
466 return INfcAdapter.Stub.asInterface(b);
467 }
468
Nick Pellyfdf90862010-10-18 11:19:41 -0700469 /**
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800470 * Helper to get the default NFC Adapter.
471 * <p>
472 * Most Android devices will only have one NFC Adapter (NFC Controller).
473 * <p>
474 * This helper is the equivalent of:
Scott Main97e0a1c2012-06-25 11:22:10 -0700475 * <pre>
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800476 * NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
Scott Main97e0a1c2012-06-25 11:22:10 -0700477 * NfcAdapter adapter = manager.getDefaultAdapter();</pre>
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800478 * @param context the calling application's context
479 *
480 * @return the default NFC adapter, or null if no NFC adapter exists
481 */
482 public static NfcAdapter getDefaultAdapter(Context context) {
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600483 if (context == null) {
484 throw new IllegalArgumentException("context cannot be null");
485 }
486 context = context.getApplicationContext();
Nick Pellyb04cce02011-11-21 17:02:02 -0800487 if (context == null) {
488 throw new IllegalArgumentException(
489 "context not associated with any application (using a mock context?)");
490 }
491 /* use getSystemService() for consistency */
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800492 NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
Nick Pellya5193b242011-11-16 16:46:27 -0800493 if (manager == null) {
494 // NFC not available
495 return null;
496 }
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800497 return manager.getDefaultAdapter();
498 }
499
500 /**
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600501 * Legacy NfcAdapter getter, always use {@link #getDefaultAdapter(Context)} instead.<p>
502 * This method was deprecated at API level 10 (Gingerbread MR1) because a context is required
503 * for many NFC API methods. Those methods will fail when called on an NfcAdapter
504 * object created from this method.<p>
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800505 * @deprecated use {@link #getDefaultAdapter(Context)}
Nick Pellya356bf12011-12-13 15:36:31 -0800506 * @hide
Nick Pelly590b73b2010-10-12 13:00:50 -0700507 */
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800508 @Deprecated
Nick Pelly590b73b2010-10-12 13:00:50 -0700509 public static NfcAdapter getDefaultAdapter() {
Nick Pellyc97a5522012-01-05 15:13:01 +1100510 // introduced in API version 9 (GB 2.3)
Nick Pellya356bf12011-12-13 15:36:31 -0800511 // deprecated in API version 10 (GB 2.3.3)
512 // removed from public API in version 16 (ICS MR2)
Nick Pellyc97a5522012-01-05 15:13:01 +1100513 // should maintain as a hidden API for binary compatibility for a little longer
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800514 Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " +
515 "NfcAdapter.getDefaultAdapter(Context) instead", new Exception());
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600516
517 return NfcAdapter.getNfcAdapter(null);
518 }
519
520 NfcAdapter(Context context) {
521 mContext = context;
522 mNfcActivityManager = new NfcActivityManager(this);
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800523 }
Nick Pelly590b73b2010-10-12 13:00:50 -0700524
Nick Pellyc84c89a2011-08-22 22:27:11 -0700525 /**
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600526 * @hide
Nick Pellyc84c89a2011-08-22 22:27:11 -0700527 */
Jeff Hamiltonbb951c82011-11-08 16:55:13 -0600528 public Context getContext() {
529 return mContext;
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800530 }
531
532 /**
533 * Returns the binder interface to the service.
534 * @hide
535 */
536 public INfcAdapter getService() {
Nick Pelly253c5092011-01-13 09:22:57 -0800537 isEnabled(); // NOP call to recover sService if it is stale
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800538 return sService;
Nick Pelly590b73b2010-10-12 13:00:50 -0700539 }
540
Jeff Hamilton6be655c2010-11-12 12:28:16 -0600541 /**
Nick Pelly3dd6c452011-01-10 18:14:41 +1100542 * Returns the binder interface to the tag service.
543 * @hide
544 */
545 public INfcTag getTagService() {
Nick Pelly253c5092011-01-13 09:22:57 -0800546 isEnabled(); // NOP call to recover sTagService if it is stale
Nick Pelly3dd6c452011-01-10 18:14:41 +1100547 return sTagService;
548 }
549
550 /**
Martijn Coenena7397882013-07-30 20:07:47 -0700551 * Returns the binder interface to the card emulation service.
552 * @hide
553 */
554 public INfcCardEmulation getCardEmulationService() {
555 isEnabled();
556 return sCardEmulationService;
557 }
558
559 /**
Andres Morales38a7ed02013-11-14 19:02:56 -0800560 * Returns the binder interface to the NFC unlock service.
561 *
562 * @throws UnsupportedOperationException if the service is not available.
563 * @hide
564 */
565 public INfcUnlockSettings getNfcUnlockSettingsService() throws UnsupportedOperationException {
566 isEnabled();
567
568 if (sNfcUnlockSettingsService == null) {
569 throw new UnsupportedOperationException("NfcUnlockSettingsService not available");
570 }
571
572 return sNfcUnlockSettingsService;
573 }
574
575 /**
Jeff Hamilton6be655c2010-11-12 12:28:16 -0600576 * NFC service dead - attempt best effort recovery
577 * @hide
578 */
579 public void attemptDeadServiceRecovery(Exception e) {
Nick Pelly6d55e132010-10-27 01:14:43 -0700580 Log.e(TAG, "NFC service dead - attempting to recover", e);
581 INfcAdapter service = getServiceInterface();
582 if (service == null) {
583 Log.e(TAG, "could not retrieve NFC service during service recovery");
Nick Pelly3dd6c452011-01-10 18:14:41 +1100584 // nothing more can be done now, sService is still stale, we'll hit
585 // this recovery path again later
Nick Pelly6d55e132010-10-27 01:14:43 -0700586 return;
587 }
Nick Pelly3dd6c452011-01-10 18:14:41 +1100588 // assigning to sService is not thread-safe, but this is best-effort code
589 // and on a well-behaved system should never happen
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800590 sService = service;
Nick Pelly3dd6c452011-01-10 18:14:41 +1100591 try {
592 sTagService = service.getNfcTagInterface();
593 } catch (RemoteException ee) {
594 Log.e(TAG, "could not retrieve NFC tag service during service recovery");
595 // nothing more can be done now, sService is still stale, we'll hit
596 // this recovery path again later
Martijn Coenena7397882013-07-30 20:07:47 -0700597 return;
598 }
599
600 try {
601 sCardEmulationService = service.getNfcCardEmulationInterface();
602 } catch (RemoteException ee) {
603 Log.e(TAG, "could not retrieve NFC card emulation service during service recovery");
Nick Pelly3dd6c452011-01-10 18:14:41 +1100604 }
605
Nick Pelly6d55e132010-10-27 01:14:43 -0700606 return;
607 }
608
Nick Pelly590b73b2010-10-12 13:00:50 -0700609 /**
Nick Pelly7ea5c452010-10-20 18:39:11 -0700610 * Return true if this NFC Adapter has any features enabled.
Nick Pelly590b73b2010-10-12 13:00:50 -0700611 *
Nick Pelly74fe6c62011-02-02 22:37:40 -0800612 * <p>If this method returns false, the NFC hardware is guaranteed not to
Nick Pellycccf01d2011-10-31 14:49:40 -0700613 * generate or respond to any NFC communication over its NFC radio.
614 * <p>Applications can use this to check if NFC is enabled. Applications
615 * can request Settings UI allowing the user to toggle NFC using:
616 * <p><pre>startActivity(new Intent(Settings.ACTION_NFC_SETTINGS))</pre>
Nick Pelly74fe6c62011-02-02 22:37:40 -0800617 *
Nick Pellycccf01d2011-10-31 14:49:40 -0700618 * @see android.provider.Settings#ACTION_NFC_SETTINGS
Nick Pelly74fe6c62011-02-02 22:37:40 -0800619 * @return true if this NFC Adapter has any features enabled
Nick Pelly590b73b2010-10-12 13:00:50 -0700620 */
Nick Pelly7ea5c452010-10-20 18:39:11 -0700621 public boolean isEnabled() {
Nick Pelly590b73b2010-10-12 13:00:50 -0700622 try {
Nick Pelly8d32a012011-08-09 07:03:49 -0700623 return sService.getState() == STATE_ON;
Nick Pelly590b73b2010-10-12 13:00:50 -0700624 } catch (RemoteException e) {
Nick Pelly6d55e132010-10-27 01:14:43 -0700625 attemptDeadServiceRecovery(e);
Nick Pelly590b73b2010-10-12 13:00:50 -0700626 return false;
627 }
628 }
629
630 /**
Nick Pelly8d32a012011-08-09 07:03:49 -0700631 * Return the state of this NFC Adapter.
632 *
633 * <p>Returns one of {@link #STATE_ON}, {@link #STATE_TURNING_ON},
634 * {@link #STATE_OFF}, {@link #STATE_TURNING_OFF}.
635 *
636 * <p>{@link #isEnabled()} is equivalent to
637 * <code>{@link #getAdapterState()} == {@link #STATE_ON}</code>
638 *
639 * @return the current state of this NFC adapter
640 *
641 * @hide
642 */
643 public int getAdapterState() {
644 try {
645 return sService.getState();
646 } catch (RemoteException e) {
647 attemptDeadServiceRecovery(e);
648 return NfcAdapter.STATE_OFF;
649 }
650 }
651
652 /**
Nick Pelly7ea5c452010-10-20 18:39:11 -0700653 * Enable NFC hardware.
Nick Pelly8d32a012011-08-09 07:03:49 -0700654 *
655 * <p>This call is asynchronous. Listen for
656 * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the
657 * operation is complete.
658 *
659 * <p>If this returns true, then either NFC is already on, or
660 * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent
661 * to indicate a state transition. If this returns false, then
662 * there is some problem that prevents an attempt to turn
663 * NFC on (for example we are in airplane mode and NFC is not
664 * toggleable in airplane mode on this platform).
Brad Fitzpatrickafb082d2010-10-18 14:02:58 -0700665 *
Nick Pelly590b73b2010-10-12 13:00:50 -0700666 * @hide
667 */
Nick Pelly7ea5c452010-10-20 18:39:11 -0700668 public boolean enable() {
Nick Pelly590b73b2010-10-12 13:00:50 -0700669 try {
Nick Pelly50b4d8f2010-12-07 22:40:28 -0800670 return sService.enable();
Nick Pelly590b73b2010-10-12 13:00:50 -0700671 } catch (RemoteException e) {
Nick Pelly6d55e132010-10-27 01:14:43 -0700672 attemptDeadServiceRecovery(e);
Nick Pelly590b73b2010-10-12 13:00:50 -0700673 return false;
674 }
675 }
676
677 /**
Nick Pelly7ea5c452010-10-20 18:39:11 -0700678 * Disable NFC hardware.
Nick Pelly8d32a012011-08-09 07:03:49 -0700679 *
680 * <p>No NFC features will work after this call, and the hardware
Nick Pelly7ea5c452010-10-20 18:39:11 -0700681 * will not perform or respond to any NFC communication.
Nick Pelly8d32a012011-08-09 07:03:49 -0700682 *
683 * <p>This call is asynchronous. Listen for
684 * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the
685 * operation is complete.
686 *
687 * <p>If this returns true, then either NFC is already off, or
688 * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent
689 * to indicate a state transition. If this returns false, then
690 * there is some problem that prevents an attempt to turn
691 * NFC off.
Brad Fitzpatrickafb082d2010-10-18 14:02:58 -0700692 *
Nick Pelly590b73b2010-10-12 13:00:50 -0700693 * @hide
694 */
Sunil Jogi3bba8d02012-04-10 13:12:26 -0700695
Nick Pelly7ea5c452010-10-20 18:39:11 -0700696 public boolean disable() {
Nick Pelly590b73b2010-10-12 13:00:50 -0700697 try {
Sunil Jogi3bba8d02012-04-10 13:12:26 -0700698 return sService.disable(true);
Nick Pelly590b73b2010-10-12 13:00:50 -0700699 } catch (RemoteException e) {
Nick Pelly6d55e132010-10-27 01:14:43 -0700700 attemptDeadServiceRecovery(e);
Nick Pelly590b73b2010-10-12 13:00:50 -0700701 return false;
702 }
703 }
704
Martijn Coenen2c103112012-05-15 10:32:15 -0700705 /**
706 * Set one or more {@link Uri}s to send using Android Beam (TM). Every
707 * Uri you provide must have either scheme 'file' or scheme 'content'.
708 *
709 * <p>For the data provided through this method, Android Beam tries to
710 * switch to alternate transports such as Bluetooth to achieve a fast
711 * transfer speed. Hence this method is very suitable
712 * for transferring large files such as pictures or songs.
713 *
714 * <p>The receiving side will store the content of each Uri in
715 * a file and present a notification to the user to open the file
716 * with a {@link android.content.Intent} with action
717 * {@link android.content.Intent#ACTION_VIEW}.
718 * If multiple URIs are sent, the {@link android.content.Intent} will refer
719 * to the first of the stored files.
720 *
721 * <p>This method may be called at any time before {@link Activity#onDestroy},
722 * but the URI(s) are only made available for Android Beam when the
723 * specified activity(s) are in resumed (foreground) state. The recommended
724 * approach is to call this method during your Activity's
725 * {@link Activity#onCreate} - see sample
726 * code below. This method does not immediately perform any I/O or blocking work,
727 * so is safe to call on your main thread.
728 *
729 * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback}
730 * have priority over both {@link #setNdefPushMessage} and
731 * {@link #setNdefPushMessageCallback}.
732 *
733 * <p>If {@link #setBeamPushUris} is called with a null Uri array,
734 * and/or {@link #setBeamPushUrisCallback} is called with a null callback,
735 * then the Uri push will be completely disabled for the specified activity(s).
736 *
737 * <p>Code example:
738 * <pre>
739 * protected void onCreate(Bundle savedInstanceState) {
740 * super.onCreate(savedInstanceState);
741 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
742 * if (nfcAdapter == null) return; // NFC not available on this device
743 * nfcAdapter.setBeamPushUris(new Uri[] {uri1, uri2}, this);
Scott Main97e0a1c2012-06-25 11:22:10 -0700744 * }</pre>
Martijn Coenen2c103112012-05-15 10:32:15 -0700745 * And that is it. Only one call per activity is necessary. The Android
746 * OS will automatically release its references to the Uri(s) and the
747 * Activity object when it is destroyed if you follow this pattern.
748 *
749 * <p>If your Activity wants to dynamically supply Uri(s),
750 * then set a callback using {@link #setBeamPushUrisCallback} instead
751 * of using this method.
752 *
753 * <p class="note">Do not pass in an Activity that has already been through
754 * {@link Activity#onDestroy}. This is guaranteed if you call this API
755 * during {@link Activity#onCreate}.
756 *
Martijn Coenen3b6ecf02012-06-06 13:07:47 -0700757 * <p class="note">If this device does not support alternate transports
758 * such as Bluetooth or WiFI, calling this method does nothing.
759 *
Martijn Coenen2c103112012-05-15 10:32:15 -0700760 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
761 *
762 * @param uris an array of Uri(s) to push over Android Beam
763 * @param activity activity for which the Uri(s) will be pushed
764 */
Martijn Coenen20e8dd92012-04-12 16:37:18 -0700765 public void setBeamPushUris(Uri[] uris, Activity activity) {
Nick Pelly1d7e9062012-04-03 17:46:00 -0700766 if (activity == null) {
767 throw new NullPointerException("activity cannot be null");
768 }
Martijn Coenen2c103112012-05-15 10:32:15 -0700769 if (uris != null) {
770 for (Uri uri : uris) {
771 if (uri == null) throw new NullPointerException("Uri not " +
772 "allowed to be null");
773 String scheme = uri.getScheme();
774 if (scheme == null || (!scheme.equalsIgnoreCase("file") &&
775 !scheme.equalsIgnoreCase("content"))) {
776 throw new IllegalArgumentException("URI needs to have " +
777 "either scheme file or scheme content");
778 }
779 }
780 }
Martijn Coenen20e8dd92012-04-12 16:37:18 -0700781 mNfcActivityManager.setNdefPushContentUri(activity, uris);
782 }
783
Martijn Coenen2c103112012-05-15 10:32:15 -0700784 /**
785 * Set a callback that will dynamically generate one or more {@link Uri}s
786 * to send using Android Beam (TM). Every Uri the callback provides
787 * must have either scheme 'file' or scheme 'content'.
788 *
789 * <p>For the data provided through this callback, Android Beam tries to
790 * switch to alternate transports such as Bluetooth to achieve a fast
791 * transfer speed. Hence this method is very suitable
792 * for transferring large files such as pictures or songs.
793 *
794 * <p>The receiving side will store the content of each Uri in
795 * a file and present a notification to the user to open the file
796 * with a {@link android.content.Intent} with action
797 * {@link android.content.Intent#ACTION_VIEW}.
798 * If multiple URIs are sent, the {@link android.content.Intent} will refer
799 * to the first of the stored files.
800 *
801 * <p>This method may be called at any time before {@link Activity#onDestroy},
802 * but the URI(s) are only made available for Android Beam when the
803 * specified activity(s) are in resumed (foreground) state. The recommended
804 * approach is to call this method during your Activity's
805 * {@link Activity#onCreate} - see sample
806 * code below. This method does not immediately perform any I/O or blocking work,
807 * so is safe to call on your main thread.
808 *
809 * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback}
810 * have priority over both {@link #setNdefPushMessage} and
811 * {@link #setNdefPushMessageCallback}.
812 *
813 * <p>If {@link #setBeamPushUris} is called with a null Uri array,
814 * and/or {@link #setBeamPushUrisCallback} is called with a null callback,
815 * then the Uri push will be completely disabled for the specified activity(s).
816 *
817 * <p>Code example:
818 * <pre>
819 * protected void onCreate(Bundle savedInstanceState) {
820 * super.onCreate(savedInstanceState);
821 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
822 * if (nfcAdapter == null) return; // NFC not available on this device
823 * nfcAdapter.setBeamPushUrisCallback(callback, this);
Scott Main97e0a1c2012-06-25 11:22:10 -0700824 * }</pre>
Martijn Coenen2c103112012-05-15 10:32:15 -0700825 * And that is it. Only one call per activity is necessary. The Android
826 * OS will automatically release its references to the Uri(s) and the
827 * Activity object when it is destroyed if you follow this pattern.
828 *
829 * <p class="note">Do not pass in an Activity that has already been through
830 * {@link Activity#onDestroy}. This is guaranteed if you call this API
831 * during {@link Activity#onCreate}.
832 *
Martijn Coenen3b6ecf02012-06-06 13:07:47 -0700833 * <p class="note">If this device does not support alternate transports
834 * such as Bluetooth or WiFI, calling this method does nothing.
835 *
Martijn Coenen2c103112012-05-15 10:32:15 -0700836 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
837 *
838 * @param callback callback, or null to disable
839 * @param activity activity for which the Uri(s) will be pushed
840 */
Martijn Coenen20e8dd92012-04-12 16:37:18 -0700841 public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) {
842 if (activity == null) {
843 throw new NullPointerException("activity cannot be null");
844 }
845 mNfcActivityManager.setNdefPushContentUriCallback(activity, callback);
Nick Pelly1d7e9062012-04-03 17:46:00 -0700846 }
847
Jeff Hamilton52d32032011-01-08 15:31:26 -0600848 /**
Nick Pelly8ce7a272012-03-21 15:14:09 -0700849 * Set a static {@link NdefMessage} to send using Android Beam (TM).
Nick Pellyc84c89a2011-08-22 22:27:11 -0700850 *
Nick Pelly8ce7a272012-03-21 15:14:09 -0700851 * <p>This method may be called at any time before {@link Activity#onDestroy},
852 * but the NDEF message is only made available for NDEF push when the
853 * specified activity(s) are in resumed (foreground) state. The recommended
854 * approach is to call this method during your Activity's
855 * {@link Activity#onCreate} - see sample
856 * code below. This method does not immediately perform any I/O or blocking work,
857 * so is safe to call on your main thread.
Nick Pellyc84c89a2011-08-22 22:27:11 -0700858 *
859 * <p>Only one NDEF message can be pushed by the currently resumed activity.
860 * If both {@link #setNdefPushMessage} and
Nick Pelly8ce7a272012-03-21 15:14:09 -0700861 * {@link #setNdefPushMessageCallback} are set, then
Nick Pellyc84c89a2011-08-22 22:27:11 -0700862 * the callback will take priority.
863 *
Nick Pelly8ce7a272012-03-21 15:14:09 -0700864 * <p>If neither {@link #setNdefPushMessage} or
865 * {@link #setNdefPushMessageCallback} have been called for your activity, then
866 * the Android OS may choose to send a default NDEF message on your behalf,
867 * such as a URI for your application.
Nick Pellyc84c89a2011-08-22 22:27:11 -0700868 *
Nick Pelly8ce7a272012-03-21 15:14:09 -0700869 * <p>If {@link #setNdefPushMessage} is called with a null NDEF message,
870 * and/or {@link #setNdefPushMessageCallback} is called with a null callback,
871 * then NDEF push will be completely disabled for the specified activity(s).
872 * This also disables any default NDEF message the Android OS would have
Martijn Coenen854e0772012-04-02 14:52:10 -0700873 * otherwise sent on your behalf for those activity(s).
874 *
875 * <p>If you want to prevent the Android OS from sending default NDEF
876 * messages completely (for all activities), you can include a
Scott Main97e0a1c2012-06-25 11:22:10 -0700877 * {@code &lt;meta-data>} element inside the {@code &lt;application>}
Martijn Coenen854e0772012-04-02 14:52:10 -0700878 * element of your AndroidManifest.xml file, like this:
Scott Main97e0a1c2012-06-25 11:22:10 -0700879 * <pre>
880 * &lt;application ...>
881 * &lt;meta-data android:name="android.nfc.disable_beam_default"
882 * android:value="true" />
883 * &lt;/application></pre>
Nick Pelly8ce7a272012-03-21 15:14:09 -0700884 *
885 * <p>The API allows for multiple activities to be specified at a time,
886 * but it is strongly recommended to just register one at a time,
887 * and to do so during the activity's {@link Activity#onCreate}. For example:
888 * <pre>
889 * protected void onCreate(Bundle savedInstanceState) {
890 * super.onCreate(savedInstanceState);
891 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
892 * if (nfcAdapter == null) return; // NFC not available on this device
893 * nfcAdapter.setNdefPushMessage(ndefMessage, this);
Scott Main97e0a1c2012-06-25 11:22:10 -0700894 * }</pre>
Nick Pelly8ce7a272012-03-21 15:14:09 -0700895 * And that is it. Only one call per activity is necessary. The Android
896 * OS will automatically release its references to the NDEF message and the
897 * Activity object when it is destroyed if you follow this pattern.
898 *
899 * <p>If your Activity wants to dynamically generate an NDEF message,
900 * then set a callback using {@link #setNdefPushMessageCallback} instead
901 * of a static message.
902 *
903 * <p class="note">Do not pass in an Activity that has already been through
904 * {@link Activity#onDestroy}. This is guaranteed if you call this API
905 * during {@link Activity#onCreate}.
Nick Pelly82328bf2011-08-30 09:37:25 -0700906 *
Martijn Coenen2c103112012-05-15 10:32:15 -0700907 * <p class="note">For sending large content such as pictures and songs,
908 * consider using {@link #setBeamPushUris}, which switches to alternate transports
909 * such as Bluetooth to achieve a fast transfer rate.
910 *
Nick Pellyc84c89a2011-08-22 22:27:11 -0700911 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
912 *
913 * @param message NDEF message to push over NFC, or null to disable
Nick Pelly8ce7a272012-03-21 15:14:09 -0700914 * @param activity activity for which the NDEF message will be pushed
915 * @param activities optional additional activities, however we strongly recommend
916 * to only register one at a time, and to do so in that activity's
917 * {@link Activity#onCreate}
Nick Pellyc84c89a2011-08-22 22:27:11 -0700918 */
Nick Pelly82328bf2011-08-30 09:37:25 -0700919 public void setNdefPushMessage(NdefMessage message, Activity activity,
920 Activity ... activities) {
Nick Pelly8ce7a272012-03-21 15:14:09 -0700921 int targetSdkVersion = getSdkVersion();
922 try {
923 if (activity == null) {
924 throw new NullPointerException("activity cannot be null");
Nick Pelly82328bf2011-08-30 09:37:25 -0700925 }
Martijn Coenen1fa2aff2013-02-27 09:21:22 -0800926 mNfcActivityManager.setNdefPushMessage(activity, message, 0);
Nick Pelly8ce7a272012-03-21 15:14:09 -0700927 for (Activity a : activities) {
928 if (a == null) {
929 throw new NullPointerException("activities cannot contain null");
930 }
Martijn Coenen1fa2aff2013-02-27 09:21:22 -0800931 mNfcActivityManager.setNdefPushMessage(a, message, 0);
Nick Pelly8ce7a272012-03-21 15:14:09 -0700932 }
933 } catch (IllegalStateException e) {
934 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
935 // Less strict on old applications - just log the error
936 Log.e(TAG, "Cannot call API with Activity that has already " +
937 "been destroyed", e);
938 } else {
939 // Prevent new applications from making this mistake, re-throw
940 throw(e);
941 }
Nick Pellyc84c89a2011-08-22 22:27:11 -0700942 }
943 }
944
945 /**
Martijn Coenen1fa2aff2013-02-27 09:21:22 -0800946 * @hide
947 */
948 public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
949 if (activity == null) {
950 throw new NullPointerException("activity cannot be null");
951 }
952 mNfcActivityManager.setNdefPushMessage(activity, message, flags);
953 }
954
955 /**
Nick Pelly8ce7a272012-03-21 15:14:09 -0700956 * Set a callback that dynamically generates NDEF messages to send using Android Beam (TM).
Nick Pellyc84c89a2011-08-22 22:27:11 -0700957 *
Nick Pelly8ce7a272012-03-21 15:14:09 -0700958 * <p>This method may be called at any time before {@link Activity#onDestroy},
959 * but the NDEF message callback can only occur when the
960 * specified activity(s) are in resumed (foreground) state. The recommended
961 * approach is to call this method during your Activity's
962 * {@link Activity#onCreate} - see sample
963 * code below. This method does not immediately perform any I/O or blocking work,
964 * so is safe to call on your main thread.
Nick Pellyc84c89a2011-08-22 22:27:11 -0700965 *
966 * <p>Only one NDEF message can be pushed by the currently resumed activity.
967 * If both {@link #setNdefPushMessage} and
Nick Pelly8ce7a272012-03-21 15:14:09 -0700968 * {@link #setNdefPushMessageCallback} are set, then
Nick Pellyc84c89a2011-08-22 22:27:11 -0700969 * the callback will take priority.
970 *
Nick Pelly8ce7a272012-03-21 15:14:09 -0700971 * <p>If neither {@link #setNdefPushMessage} or
972 * {@link #setNdefPushMessageCallback} have been called for your activity, then
973 * the Android OS may choose to send a default NDEF message on your behalf,
974 * such as a URI for your application.
Nick Pellyc84c89a2011-08-22 22:27:11 -0700975 *
Nick Pelly8ce7a272012-03-21 15:14:09 -0700976 * <p>If {@link #setNdefPushMessage} is called with a null NDEF message,
977 * and/or {@link #setNdefPushMessageCallback} is called with a null callback,
978 * then NDEF push will be completely disabled for the specified activity(s).
979 * This also disables any default NDEF message the Android OS would have
Martijn Coenen854e0772012-04-02 14:52:10 -0700980 * otherwise sent on your behalf for those activity(s).
981 *
982 * <p>If you want to prevent the Android OS from sending default NDEF
983 * messages completely (for all activities), you can include a
Scott Main97e0a1c2012-06-25 11:22:10 -0700984 * {@code &lt;meta-data>} element inside the {@code &lt;application>}
Martijn Coenen854e0772012-04-02 14:52:10 -0700985 * element of your AndroidManifest.xml file, like this:
Scott Main97e0a1c2012-06-25 11:22:10 -0700986 * <pre>
987 * &lt;application ...>
988 * &lt;meta-data android:name="android.nfc.disable_beam_default"
989 * android:value="true" />
990 * &lt;/application></pre>
Nick Pelly8ce7a272012-03-21 15:14:09 -0700991 *
992 * <p>The API allows for multiple activities to be specified at a time,
993 * but it is strongly recommended to just register one at a time,
994 * and to do so during the activity's {@link Activity#onCreate}. For example:
995 * <pre>
996 * protected void onCreate(Bundle savedInstanceState) {
997 * super.onCreate(savedInstanceState);
998 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
999 * if (nfcAdapter == null) return; // NFC not available on this device
1000 * nfcAdapter.setNdefPushMessageCallback(callback, this);
Scott Main97e0a1c2012-06-25 11:22:10 -07001001 * }</pre>
Nick Pelly8ce7a272012-03-21 15:14:09 -07001002 * And that is it. Only one call per activity is necessary. The Android
1003 * OS will automatically release its references to the callback and the
1004 * Activity object when it is destroyed if you follow this pattern.
1005 *
1006 * <p class="note">Do not pass in an Activity that has already been through
1007 * {@link Activity#onDestroy}. This is guaranteed if you call this API
1008 * during {@link Activity#onCreate}.
Martijn Coenen2c103112012-05-15 10:32:15 -07001009 * <p class="note">For sending large content such as pictures and songs,
1010 * consider using {@link #setBeamPushUris}, which switches to alternate transports
1011 * such as Bluetooth to achieve a fast transfer rate.
Nick Pellyc84c89a2011-08-22 22:27:11 -07001012 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
1013 *
1014 * @param callback callback, or null to disable
Nick Pelly8ce7a272012-03-21 15:14:09 -07001015 * @param activity activity for which the NDEF message will be pushed
1016 * @param activities optional additional activities, however we strongly recommend
1017 * to only register one at a time, and to do so in that activity's
1018 * {@link Activity#onCreate}
Nick Pellyc84c89a2011-08-22 22:27:11 -07001019 */
Nick Pelly82328bf2011-08-30 09:37:25 -07001020 public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
Nick Pellyc84c89a2011-08-22 22:27:11 -07001021 Activity ... activities) {
Nick Pelly8ce7a272012-03-21 15:14:09 -07001022 int targetSdkVersion = getSdkVersion();
1023 try {
1024 if (activity == null) {
1025 throw new NullPointerException("activity cannot be null");
Nick Pelly82328bf2011-08-30 09:37:25 -07001026 }
Martijn Coenen1fa2aff2013-02-27 09:21:22 -08001027 mNfcActivityManager.setNdefPushMessageCallback(activity, callback, 0);
Nick Pelly8ce7a272012-03-21 15:14:09 -07001028 for (Activity a : activities) {
1029 if (a == null) {
1030 throw new NullPointerException("activities cannot contain null");
1031 }
Martijn Coenen1fa2aff2013-02-27 09:21:22 -08001032 mNfcActivityManager.setNdefPushMessageCallback(a, callback, 0);
Nick Pelly8ce7a272012-03-21 15:14:09 -07001033 }
1034 } catch (IllegalStateException e) {
1035 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
1036 // Less strict on old applications - just log the error
1037 Log.e(TAG, "Cannot call API with Activity that has already " +
1038 "been destroyed", e);
1039 } else {
1040 // Prevent new applications from making this mistake, re-throw
1041 throw(e);
1042 }
Nick Pellyc84c89a2011-08-22 22:27:11 -07001043 }
1044 }
1045
1046 /**
Martijn Coenen1fa2aff2013-02-27 09:21:22 -08001047 * @hide
1048 */
1049 public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
1050 int flags) {
1051 if (activity == null) {
1052 throw new NullPointerException("activity cannot be null");
1053 }
1054 mNfcActivityManager.setNdefPushMessageCallback(activity, callback, flags);
1055 }
1056
1057 /**
Nick Pelly8ce7a272012-03-21 15:14:09 -07001058 * Set a callback on successful Android Beam (TM).
Nick Pellyc84c89a2011-08-22 22:27:11 -07001059 *
Nick Pelly8ce7a272012-03-21 15:14:09 -07001060 * <p>This method may be called at any time before {@link Activity#onDestroy},
1061 * but the callback can only occur when the
1062 * specified activity(s) are in resumed (foreground) state. The recommended
1063 * approach is to call this method during your Activity's
1064 * {@link Activity#onCreate} - see sample
1065 * code below. This method does not immediately perform any I/O or blocking work,
1066 * so is safe to call on your main thread.
Nick Pellyc84c89a2011-08-22 22:27:11 -07001067 *
Nick Pelly8ce7a272012-03-21 15:14:09 -07001068 * <p>The API allows for multiple activities to be specified at a time,
1069 * but it is strongly recommended to just register one at a time,
1070 * and to do so during the activity's {@link Activity#onCreate}. For example:
1071 * <pre>
1072 * protected void onCreate(Bundle savedInstanceState) {
1073 * super.onCreate(savedInstanceState);
1074 * NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
1075 * if (nfcAdapter == null) return; // NFC not available on this device
1076 * nfcAdapter.setOnNdefPushCompleteCallback(callback, this);
Scott Main97e0a1c2012-06-25 11:22:10 -07001077 * }</pre>
Nick Pelly8ce7a272012-03-21 15:14:09 -07001078 * And that is it. Only one call per activity is necessary. The Android
1079 * OS will automatically release its references to the callback and the
1080 * Activity object when it is destroyed if you follow this pattern.
1081 *
1082 * <p class="note">Do not pass in an Activity that has already been through
1083 * {@link Activity#onDestroy}. This is guaranteed if you call this API
1084 * during {@link Activity#onCreate}.
Nick Pelly82328bf2011-08-30 09:37:25 -07001085 *
Nick Pellyc84c89a2011-08-22 22:27:11 -07001086 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
1087 *
1088 * @param callback callback, or null to disable
Nick Pelly8ce7a272012-03-21 15:14:09 -07001089 * @param activity activity for which the NDEF message will be pushed
1090 * @param activities optional additional activities, however we strongly recommend
1091 * to only register one at a time, and to do so in that activity's
1092 * {@link Activity#onCreate}
Nick Pellyc84c89a2011-08-22 22:27:11 -07001093 */
1094 public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback,
Nick Pelly82328bf2011-08-30 09:37:25 -07001095 Activity activity, Activity ... activities) {
Nick Pelly8ce7a272012-03-21 15:14:09 -07001096 int targetSdkVersion = getSdkVersion();
1097 try {
1098 if (activity == null) {
1099 throw new NullPointerException("activity cannot be null");
Nick Pelly82328bf2011-08-30 09:37:25 -07001100 }
Nick Pelly8ce7a272012-03-21 15:14:09 -07001101 mNfcActivityManager.setOnNdefPushCompleteCallback(activity, callback);
1102 for (Activity a : activities) {
1103 if (a == null) {
1104 throw new NullPointerException("activities cannot contain null");
1105 }
1106 mNfcActivityManager.setOnNdefPushCompleteCallback(a, callback);
1107 }
1108 } catch (IllegalStateException e) {
1109 if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
1110 // Less strict on old applications - just log the error
1111 Log.e(TAG, "Cannot call API with Activity that has already " +
1112 "been destroyed", e);
1113 } else {
1114 // Prevent new applications from making this mistake, re-throw
1115 throw(e);
1116 }
Nick Pellyc84c89a2011-08-22 22:27:11 -07001117 }
1118 }
1119
1120 /**
Nick Pelly74fe6c62011-02-02 22:37:40 -08001121 * Enable foreground dispatch to the given Activity.
Jeff Hamilton52d32032011-01-08 15:31:26 -06001122 *
Nick Pelly74fe6c62011-02-02 22:37:40 -08001123 * <p>This will give give priority to the foreground activity when
1124 * dispatching a discovered {@link Tag} to an application.
1125 *
Jeff Hamilton167d9e42011-02-09 12:27:01 +09001126 * <p>If any IntentFilters are provided to this method they are used to match dispatch Intents
1127 * for both the {@link NfcAdapter#ACTION_NDEF_DISCOVERED} and
1128 * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. Since {@link NfcAdapter#ACTION_TECH_DISCOVERED}
1129 * relies on meta data outside of the IntentFilter matching for that dispatch Intent is handled
1130 * by passing in the tech lists separately. Each first level entry in the tech list represents
1131 * an array of technologies that must all be present to match. If any of the first level sets
1132 * match then the dispatch is routed through the given PendingIntent. In other words, the second
1133 * level is ANDed together and the first level entries are ORed together.
Nick Pelly74fe6c62011-02-02 22:37:40 -08001134 *
Jeff Hamilton167d9e42011-02-09 12:27:01 +09001135 * <p>If you pass {@code null} for both the {@code filters} and {@code techLists} parameters
1136 * that acts a wild card and will cause the foreground activity to receive all tags via the
1137 * {@link NfcAdapter#ACTION_TAG_DISCOVERED} intent.
Nick Pelly74fe6c62011-02-02 22:37:40 -08001138 *
Jeff Hamilton167d9e42011-02-09 12:27:01 +09001139 * <p>This method must be called from the main thread, and only when the activity is in the
1140 * foreground (resumed). Also, activities must call {@link #disableForegroundDispatch} before
1141 * the completion of their {@link Activity#onPause} callback to disable foreground dispatch
1142 * after it has been enabled.
Jeff Hamilton52d32032011-01-08 15:31:26 -06001143 *
Nick Pelly39cf3a42011-02-07 17:04:21 +09001144 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
1145 *
Jeff Hamilton52d32032011-01-08 15:31:26 -06001146 * @param activity the Activity to dispatch to
1147 * @param intent the PendingIntent to start for the dispatch
Jeff Hamilton9f20cd72011-01-23 12:14:42 -06001148 * @param filters the IntentFilters to override dispatching for, or null to always dispatch
Jeff Hamilton167d9e42011-02-09 12:27:01 +09001149 * @param techLists the tech lists used to perform matching for dispatching of the
1150 * {@link NfcAdapter#ACTION_TECH_DISCOVERED} intent
Nick Pelly74fe6c62011-02-02 22:37:40 -08001151 * @throws IllegalStateException if the Activity is not currently in the foreground
Jeff Hamilton52d32032011-01-08 15:31:26 -06001152 */
1153 public void enableForegroundDispatch(Activity activity, PendingIntent intent,
Jeff Hamiltond88e9aa2011-01-24 14:53:00 -06001154 IntentFilter[] filters, String[][] techLists) {
Jeff Hamilton9f20cd72011-01-23 12:14:42 -06001155 if (activity == null || intent == null) {
Jeff Hamilton52d32032011-01-08 15:31:26 -06001156 throw new NullPointerException();
1157 }
1158 if (!activity.isResumed()) {
Nick Pellyc84c89a2011-08-22 22:27:11 -07001159 throw new IllegalStateException("Foreground dispatch can only be enabled " +
Jeff Hamilton52d32032011-01-08 15:31:26 -06001160 "when your activity is resumed");
1161 }
1162 try {
Jeff Hamiltond88e9aa2011-01-24 14:53:00 -06001163 TechListParcel parcel = null;
1164 if (techLists != null && techLists.length > 0) {
1165 parcel = new TechListParcel(techLists);
1166 }
Jeff Hamilton52d32032011-01-08 15:31:26 -06001167 ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
Jeff Hamiltonce3224c2011-01-17 11:05:03 -08001168 mForegroundDispatchListener);
Nick Pellyc84c89a2011-08-22 22:27:11 -07001169 sService.setForegroundDispatch(intent, filters, parcel);
Jeff Hamilton52d32032011-01-08 15:31:26 -06001170 } catch (RemoteException e) {
1171 attemptDeadServiceRecovery(e);
1172 }
1173 }
1174
1175 /**
Nick Pelly74fe6c62011-02-02 22:37:40 -08001176 * Disable foreground dispatch to the given activity.
Jeff Hamilton33ff2402011-01-17 07:59:03 -08001177 *
Nick Pelly74fe6c62011-02-02 22:37:40 -08001178 * <p>After calling {@link #enableForegroundDispatch}, an activity
1179 * must call this method before its {@link Activity#onPause} callback
1180 * completes.
Jeff Hamilton52d32032011-01-08 15:31:26 -06001181 *
Jeff Hamilton33ff2402011-01-17 07:59:03 -08001182 * <p>This method must be called from the main thread.
Nick Pelly74fe6c62011-02-02 22:37:40 -08001183 *
Nick Pelly39cf3a42011-02-07 17:04:21 +09001184 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
1185 *
Nick Pelly74fe6c62011-02-02 22:37:40 -08001186 * @param activity the Activity to disable dispatch to
1187 * @throws IllegalStateException if the Activity has already been paused
Jeff Hamilton52d32032011-01-08 15:31:26 -06001188 */
1189 public void disableForegroundDispatch(Activity activity) {
Jeff Hamiltonce3224c2011-01-17 11:05:03 -08001190 ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity,
1191 mForegroundDispatchListener);
Jeff Hamilton52d32032011-01-08 15:31:26 -06001192 disableForegroundDispatchInternal(activity, false);
1193 }
1194
Jeff Hamiltonce3224c2011-01-17 11:05:03 -08001195 OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() {
Jeff Hamilton33ff2402011-01-17 07:59:03 -08001196 @Override
1197 public void onPaused(Activity activity) {
1198 disableForegroundDispatchInternal(activity, true);
1199 }
Jeff Hamiltonce3224c2011-01-17 11:05:03 -08001200 };
Jeff Hamilton33ff2402011-01-17 07:59:03 -08001201
Jeff Hamilton52d32032011-01-08 15:31:26 -06001202 void disableForegroundDispatchInternal(Activity activity, boolean force) {
1203 try {
Nick Pellyc84c89a2011-08-22 22:27:11 -07001204 sService.setForegroundDispatch(null, null, null);
Jeff Hamilton52d32032011-01-08 15:31:26 -06001205 if (!force && !activity.isResumed()) {
Nick Pellyc84c89a2011-08-22 22:27:11 -07001206 throw new IllegalStateException("You must disable foreground dispatching " +
Jeff Hamilton52d32032011-01-08 15:31:26 -06001207 "while your activity is still resumed");
1208 }
1209 } catch (RemoteException e) {
1210 attemptDeadServiceRecovery(e);
1211 }
1212 }
1213
Nick Pelly590b73b2010-10-12 13:00:50 -07001214 /**
Martijn Coenenc20ed2f2013-08-27 14:32:53 -07001215 * Limit the NFC controller to reader mode while this Activity is in the foreground.
1216 *
1217 * <p>In this mode the NFC controller will only act as an NFC tag reader/writer,
1218 * thus disabling any peer-to-peer (Android Beam) and card-emulation modes of
1219 * the NFC adapter on this device.
1220 *
1221 * <p>Use {@link #FLAG_READER_SKIP_NDEF_CHECK} to prevent the platform from
1222 * performing any NDEF checks in reader mode. Note that this will prevent the
1223 * {@link Ndef} tag technology from being enumerated on the tag, and that
1224 * NDEF-based tag dispatch will not be functional.
1225 *
Martijn Coenenc20ed2f2013-08-27 14:32:53 -07001226 * <p>For interacting with tags that are emulated on another Android device
1227 * using Android's host-based card-emulation, the recommended flags are
1228 * {@link #FLAG_READER_NFC_A} and {@link #FLAG_READER_SKIP_NDEF_CHECK}.
1229 *
1230 * @param activity the Activity that requests the adapter to be in reader mode
Martijn Coenen5b1e0322013-09-02 20:38:47 -07001231 * @param callback the callback to be called when a tag is discovered
Martijn Coenenc20ed2f2013-08-27 14:32:53 -07001232 * @param flags Flags indicating poll technologies and other optional parameters
Martijn Coenen5b1e0322013-09-02 20:38:47 -07001233 * @param extras Additional extras for configuring reader mode.
Martijn Coenenc20ed2f2013-08-27 14:32:53 -07001234 */
Martijn Coenen5b1e0322013-09-02 20:38:47 -07001235 public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,
1236 Bundle extras) {
1237 mNfcActivityManager.enableReaderMode(activity, callback, flags, extras);
Martijn Coenenc20ed2f2013-08-27 14:32:53 -07001238 }
1239
1240 /**
1241 * Restore the NFC adapter to normal mode of operation: supporting
1242 * peer-to-peer (Android Beam), card emulation, and polling for
1243 * all supported tag technologies.
1244 *
1245 * @param activity the Activity that currently has reader mode enabled
1246 */
1247 public void disableReaderMode(Activity activity) {
1248 mNfcActivityManager.disableReaderMode(activity);
1249 }
1250
1251 /**
Nick Pellyc84c89a2011-08-22 22:27:11 -07001252 * Enable NDEF message push over NFC while this Activity is in the foreground.
Nick Pelly74fe6c62011-02-02 22:37:40 -08001253 *
Nick Pellyc84c89a2011-08-22 22:27:11 -07001254 * <p>You must explicitly call this method every time the activity is
1255 * resumed, and you must call {@link #disableForegroundNdefPush} before
1256 * your activity completes {@link Activity#onPause}.
1257 *
1258 * <p>Strongly recommend to use the new {@link #setNdefPushMessage}
1259 * instead: it automatically hooks into your activity life-cycle,
1260 * so you do not need to call enable/disable in your onResume/onPause.
1261 *
1262 * <p>For NDEF push to function properly the other NFC device must
1263 * support either NFC Forum's SNEP (Simple Ndef Exchange Protocol), or
1264 * Android's "com.android.npp" (Ndef Push Protocol). This was optional
1265 * on Gingerbread level Android NFC devices, but SNEP is mandatory on
1266 * Ice-Cream-Sandwich and beyond.
Nick Pelly74fe6c62011-02-02 22:37:40 -08001267 *
1268 * <p>This method must be called from the main thread.
Jeff Hamilton9f20cd72011-01-23 12:14:42 -06001269 *
Nick Pelly39cf3a42011-02-07 17:04:21 +09001270 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
1271 *
Nick Pellyc84c89a2011-08-22 22:27:11 -07001272 * @param activity foreground activity
1273 * @param message a NDEF Message to push over NFC
1274 * @throws IllegalStateException if the activity is not currently in the foreground
1275 * @deprecated use {@link #setNdefPushMessage} instead
Jeff Hamilton33ff2402011-01-17 07:59:03 -08001276 */
Nick Pellyc84c89a2011-08-22 22:27:11 -07001277 @Deprecated
1278 public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
1279 if (activity == null || message == null) {
Jeff Hamilton33ff2402011-01-17 07:59:03 -08001280 throw new NullPointerException();
1281 }
Nick Pellyc84c89a2011-08-22 22:27:11 -07001282 enforceResumed(activity);
Martijn Coenen1fa2aff2013-02-27 09:21:22 -08001283 mNfcActivityManager.setNdefPushMessage(activity, message, 0);
Jason parks01425362011-05-24 02:57:37 -07001284 }
1285
1286 /**
Nick Pelly74fe6c62011-02-02 22:37:40 -08001287 * Disable NDEF message push over P2P.
Jeff Hamilton33ff2402011-01-17 07:59:03 -08001288 *
Nick Pelly74fe6c62011-02-02 22:37:40 -08001289 * <p>After calling {@link #enableForegroundNdefPush}, an activity
1290 * must call this method before its {@link Activity#onPause} callback
1291 * completes.
Jeff Hamilton33ff2402011-01-17 07:59:03 -08001292 *
Nick Pellyc84c89a2011-08-22 22:27:11 -07001293 * <p>Strongly recommend to use the new {@link #setNdefPushMessage}
1294 * instead: it automatically hooks into your activity life-cycle,
1295 * so you do not need to call enable/disable in your onResume/onPause.
1296 *
Jeff Hamilton33ff2402011-01-17 07:59:03 -08001297 * <p>This method must be called from the main thread.
Nick Pelly74fe6c62011-02-02 22:37:40 -08001298 *
Nick Pelly39cf3a42011-02-07 17:04:21 +09001299 * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
1300 *
Nick Pelly74fe6c62011-02-02 22:37:40 -08001301 * @param activity the Foreground activity
1302 * @throws IllegalStateException if the Activity has already been paused
Nick Pellyc84c89a2011-08-22 22:27:11 -07001303 * @deprecated use {@link #setNdefPushMessage} instead
Jeff Hamilton33ff2402011-01-17 07:59:03 -08001304 */
Nick Pellyc97a5522012-01-05 15:13:01 +11001305 @Deprecated
Jeff Hamiltonce3224c2011-01-17 11:05:03 -08001306 public void disableForegroundNdefPush(Activity activity) {
Nick Pellyc84c89a2011-08-22 22:27:11 -07001307 if (activity == null) {
1308 throw new NullPointerException();
1309 }
1310 enforceResumed(activity);
Martijn Coenen1fa2aff2013-02-27 09:21:22 -08001311 mNfcActivityManager.setNdefPushMessage(activity, null, 0);
1312 mNfcActivityManager.setNdefPushMessageCallback(activity, null, 0);
Nick Pellyc84c89a2011-08-22 22:27:11 -07001313 mNfcActivityManager.setOnNdefPushCompleteCallback(activity, null);
Jeff Hamilton33ff2402011-01-17 07:59:03 -08001314 }
1315
Nick Pellyc84c89a2011-08-22 22:27:11 -07001316 /**
Nick Pellyc84c89a2011-08-22 22:27:11 -07001317 * Enable NDEF Push feature.
1318 * <p>This API is for the Settings application.
1319 * @hide
1320 */
1321 public boolean enableNdefPush() {
Martijn Coenen6d748942011-07-21 09:34:25 +02001322 try {
Nick Pellyc84c89a2011-08-22 22:27:11 -07001323 return sService.enableNdefPush();
Martijn Coenen6d748942011-07-21 09:34:25 +02001324 } catch (RemoteException e) {
1325 attemptDeadServiceRecovery(e);
1326 return false;
1327 }
1328 }
1329
1330 /**
Nick Pellyc84c89a2011-08-22 22:27:11 -07001331 * Disable NDEF Push feature.
1332 * <p>This API is for the Settings application.
Martijn Coenen6d748942011-07-21 09:34:25 +02001333 * @hide
1334 */
Nick Pellyc84c89a2011-08-22 22:27:11 -07001335 public boolean disableNdefPush() {
Martijn Coenen6d748942011-07-21 09:34:25 +02001336 try {
Nick Pellyc84c89a2011-08-22 22:27:11 -07001337 return sService.disableNdefPush();
Martijn Coenen6d748942011-07-21 09:34:25 +02001338 } catch (RemoteException e) {
1339 attemptDeadServiceRecovery(e);
1340 return false;
1341 }
1342 }
1343
1344 /**
Nick Pellycccf01d2011-10-31 14:49:40 -07001345 * Return true if the NDEF Push (Android Beam) feature is enabled.
1346 * <p>This function will return true only if both NFC is enabled, and the
1347 * NDEF Push feature is enabled.
1348 * <p>Note that if NFC is enabled but NDEF Push is disabled then this
1349 * device can still <i>receive</i> NDEF messages, it just cannot send them.
1350 * <p>Applications cannot directly toggle the NDEF Push feature, but they
1351 * can request Settings UI allowing the user to toggle NDEF Push using
1352 * <code>startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS))</code>
1353 * <p>Example usage in an Activity that requires NDEF Push:
1354 * <p><pre>
1355 * protected void onResume() {
1356 * super.onResume();
1357 * if (!nfcAdapter.isEnabled()) {
1358 * startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));
1359 * } else if (!nfcAdapter.isNdefPushEnabled()) {
1360 * startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS));
1361 * }
Scott Main97e0a1c2012-06-25 11:22:10 -07001362 * }</pre>
Martijn Coenen6d748942011-07-21 09:34:25 +02001363 *
Nick Pellycccf01d2011-10-31 14:49:40 -07001364 * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS
Nick Pellyc84c89a2011-08-22 22:27:11 -07001365 * @return true if NDEF Push feature is enabled
Martijn Coenen6d748942011-07-21 09:34:25 +02001366 */
Nick Pellyc84c89a2011-08-22 22:27:11 -07001367 public boolean isNdefPushEnabled() {
Martijn Coenen6d748942011-07-21 09:34:25 +02001368 try {
Nick Pellyc84c89a2011-08-22 22:27:11 -07001369 return sService.isNdefPushEnabled();
Martijn Coenen6d748942011-07-21 09:34:25 +02001370 } catch (RemoteException e) {
1371 attemptDeadServiceRecovery(e);
1372 return false;
1373 }
1374 }
1375
1376 /**
Nick Pellyc97a5522012-01-05 15:13:01 +11001377 * Inject a mock NFC tag.<p>
1378 * Used for testing purposes.
1379 * <p class="note">Requires the
1380 * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
1381 * @hide
1382 */
Nick Pelly1f5badc2012-01-24 13:22:58 -08001383 public void dispatch(Tag tag) {
Nick Pellyc97a5522012-01-05 15:13:01 +11001384 if (tag == null) {
1385 throw new NullPointerException("tag cannot be null");
1386 }
1387 try {
Nick Pelly1f5badc2012-01-24 13:22:58 -08001388 sService.dispatch(tag);
Nick Pellyc97a5522012-01-05 15:13:01 +11001389 } catch (RemoteException e) {
1390 attemptDeadServiceRecovery(e);
1391 }
1392 }
1393
1394 /**
Daniel Tomas90245642010-11-17 10:07:52 +01001395 * @hide
1396 */
Martijn Coenen188cddb2012-01-31 22:16:15 -08001397 public void setP2pModes(int initiatorModes, int targetModes) {
1398 try {
1399 sService.setP2pModes(initiatorModes, targetModes);
1400 } catch (RemoteException e) {
1401 attemptDeadServiceRecovery(e);
1402 }
1403 }
1404
1405 /**
1406 * @hide
1407 */
Nick Pelly367f41f2011-03-08 11:43:30 -08001408 public INfcAdapterExtras getNfcAdapterExtrasInterface() {
Jeff Hamiltonbb951c82011-11-08 16:55:13 -06001409 if (mContext == null) {
1410 throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
1411 + " NFC extras APIs");
1412 }
Daniel Tomas90245642010-11-17 10:07:52 +01001413 try {
Jeff Hamiltonbb951c82011-11-08 16:55:13 -06001414 return sService.getNfcAdapterExtrasInterface(mContext.getPackageName());
Daniel Tomas90245642010-11-17 10:07:52 +01001415 } catch (RemoteException e) {
Nick Pelly367f41f2011-03-08 11:43:30 -08001416 attemptDeadServiceRecovery(e);
Daniel Tomas90245642010-11-17 10:07:52 +01001417 return null;
1418 }
1419 }
Nick Pellyc84c89a2011-08-22 22:27:11 -07001420
1421 void enforceResumed(Activity activity) {
1422 if (!activity.isResumed()) {
1423 throw new IllegalStateException("API cannot be called while activity is paused");
1424 }
1425 }
Nick Pelly8ce7a272012-03-21 15:14:09 -07001426
1427 int getSdkVersion() {
1428 if (mContext == null) {
1429 return android.os.Build.VERSION_CODES.GINGERBREAD; // best guess
1430 } else {
1431 return mContext.getApplicationInfo().targetSdkVersion;
1432 }
1433 }
Nick Pelly590b73b2010-10-12 13:00:50 -07001434}