1919import android .annotation .SdkConstant ;
2020import android .annotation .SdkConstant .SdkConstantType ;
2121import android .app .ActivityThread ;
22+ import android .content .Context ;
2223import android .content .pm .IPackageManager ;
2324import android .content .pm .PackageManager ;
2425import android .os .IBinder ;
2930/**
3031 * Represents the device's local NFC adapter.
3132 * <p>
32- * Use the static {@link #getDefaultAdapter} method to get the default NFC
33- * Adapter for this Android device. Most Android devices will have only one NFC
34- * Adapter, and {@link #getDefaultAdapter} returns the singleton object.
33+ * Use the helper {@link #getDefaultAdapter(Context)} to get the default NFC
34+ * adapter for this Android device.
3535 */
3636public final class NfcAdapter {
37+ private static final String TAG = "NFC" ;
38+
3739 /**
3840 * Intent to start an activity when a tag is discovered.
3941 */
@@ -161,29 +163,17 @@ public final class NfcAdapter {
161163 */
162164 private static final int DISCOVERY_MODE_CARD_EMULATION = 2 ;
163165
164- private static final String TAG = "NFC" ;
165166
166- // Both guarded by NfcAdapter.class:
167+ // Guarded by NfcAdapter.class
167168 private static boolean sIsInitialized = false ;
168- private static NfcAdapter sAdapter ;
169169
170- // Final after construction , except for attemptDeadServiceRecovery()
171- // when NFC crashes.
172- // Not locked - we accept a best effort attempt when NFC crashes.
173- /*package*/ INfcAdapter mService ;
170+ // Final after first constructor , except for
171+ // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
172+ // recovery
173+ private static INfcAdapter sService ;
174174
175- private NfcAdapter (INfcAdapter service ) {
176- mService = service ;
177- }
175+ private final Context mContext ;
178176
179- /**
180- * Returns the binder interface to the service.
181- * @hide
182- */
183- public INfcAdapter getService () {
184- return mService ;
185- }
186-
187177 /**
188178 * Helper to check if this device has FEATURE_NFC, but without using
189179 * a context.
@@ -204,8 +194,27 @@ private static boolean hasNfcFeature() {
204194 }
205195 }
206196
197+ private static synchronized INfcAdapter setupService () {
198+ if (!sIsInitialized ) {
199+ sIsInitialized = true ;
200+
201+ /* is this device meant to have NFC */
202+ if (!hasNfcFeature ()) {
203+ Log .v (TAG , "this device does not have NFC support" );
204+ return null ;
205+ }
206+
207+ sService = getServiceInterface ();
208+ if (sService == null ) {
209+ Log .e (TAG , "could not retrieve NFC service" );
210+ return null ;
211+ }
212+ }
213+ return sService ;
214+ }
215+
207216 /** get handle to NFC service interface */
208- private static synchronized INfcAdapter getServiceInterface () {
217+ private static INfcAdapter getServiceInterface () {
209218 /* get a handle to NFC service */
210219 IBinder b = ServiceManager .getService ("nfc" );
211220 if (b == null ) {
@@ -214,35 +223,55 @@ private static synchronized INfcAdapter getServiceInterface() {
214223 return INfcAdapter .Stub .asInterface (b );
215224 }
216225
226+ /**
227+ * Helper to get the default NFC Adapter.
228+ * <p>
229+ * Most Android devices will only have one NFC Adapter (NFC Controller).
230+ * <p>
231+ * This helper is the equivalent of:
232+ * <pre>{@code
233+ * NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
234+ * NfcAdapter adapter = manager.getDefaultAdapter();
235+ * }</pre>
236+ * @param context the calling application's context
237+ *
238+ * @return the default NFC adapter, or null if no NFC adapter exists
239+ */
240+ public static NfcAdapter getDefaultAdapter (Context context ) {
241+ /* use getSystemService() instead of just instantiating to take
242+ * advantage of the context's cached NfcManager & NfcAdapter */
243+ NfcManager manager = (NfcManager ) context .getSystemService (Context .NFC_SERVICE );
244+ return manager .getDefaultAdapter ();
245+ }
246+
217247 /**
218248 * Get a handle to the default NFC Adapter on this Android device.
219249 * <p>
220250 * Most Android devices will only have one NFC Adapter (NFC Controller).
221251 *
222252 * @return the default NFC adapter, or null if no NFC adapter exists
253+ * @deprecated use {@link #getDefaultAdapter(Context)}
223254 */
255+ @ Deprecated
224256 public static NfcAdapter getDefaultAdapter () {
225- synchronized (NfcAdapter .class ) {
226- if (sIsInitialized ) {
227- return sAdapter ;
228- }
229- sIsInitialized = true ;
230-
231- /* is this device meant to have NFC */
232- if (!hasNfcFeature ()) {
233- Log .v (TAG , "this device does not have NFC support" );
234- return null ;
235- }
236-
237- INfcAdapter service = getServiceInterface ();
238- if (service == null ) {
239- Log .e (TAG , "could not retrieve NFC service" );
240- return null ;
241- }
257+ Log .w (TAG , "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " +
258+ "NfcAdapter.getDefaultAdapter(Context) instead" , new Exception ());
259+ return new NfcAdapter (null );
260+ }
242261
243- sAdapter = new NfcAdapter (service );
244- return sAdapter ;
262+ /*package*/ NfcAdapter (Context context ) {
263+ if (setupService () == null ) {
264+ throw new UnsupportedOperationException ();
245265 }
266+ mContext = context ;
267+ }
268+
269+ /**
270+ * Returns the binder interface to the service.
271+ * @hide
272+ */
273+ public INfcAdapter getService () {
274+ return sService ;
246275 }
247276
248277 /**
@@ -256,9 +285,9 @@ public void attemptDeadServiceRecovery(Exception e) {
256285 Log .e (TAG , "could not retrieve NFC service during service recovery" );
257286 return ;
258287 }
259- /* assigning to mService is not thread-safe, but this is best-effort code
288+ /* assigning to sService is not thread-safe, but this is best-effort code
260289 * and on a well-behaved system should never happen */
261- mService = service ;
290+ sService = service ;
262291 return ;
263292 }
264293
@@ -275,7 +304,7 @@ public void attemptDeadServiceRecovery(Exception e) {
275304 */
276305 public boolean isEnabled () {
277306 try {
278- return mService .isEnabled ();
307+ return sService .isEnabled ();
279308 } catch (RemoteException e ) {
280309 attemptDeadServiceRecovery (e );
281310 return false ;
@@ -292,7 +321,7 @@ public boolean isEnabled() {
292321 */
293322 public boolean enable () {
294323 try {
295- return mService .enable ();
324+ return sService .enable ();
296325 } catch (RemoteException e ) {
297326 attemptDeadServiceRecovery (e );
298327 return false ;
@@ -311,7 +340,7 @@ public boolean enable() {
311340 */
312341 public boolean disable () {
313342 try {
314- return mService .disable ();
343+ return sService .disable ();
315344 } catch (RemoteException e ) {
316345 attemptDeadServiceRecovery (e );
317346 return false ;
@@ -338,7 +367,7 @@ public boolean disable() {
338367 */
339368 public void setLocalNdefMessage (NdefMessage message ) {
340369 try {
341- mService .localSet (message );
370+ sService .localSet (message );
342371 } catch (RemoteException e ) {
343372 attemptDeadServiceRecovery (e );
344373 }
@@ -353,7 +382,7 @@ public void setLocalNdefMessage(NdefMessage message) {
353382 */
354383 public NdefMessage getLocalNdefMessage () {
355384 try {
356- return mService .localGet ();
385+ return sService .localGet ();
357386 } catch (RemoteException e ) {
358387 attemptDeadServiceRecovery (e );
359388 return null ;
@@ -366,7 +395,7 @@ public NdefMessage getLocalNdefMessage() {
366395 */
367396 public NfcSecureElement createNfcSecureElementConnection () {
368397 try {
369- return new NfcSecureElement (mService .getNfcSecureElementInterface ());
398+ return new NfcSecureElement (sService .getNfcSecureElementInterface ());
370399 } catch (RemoteException e ) {
371400 Log .e (TAG , "createNfcSecureElementConnection failed" , e );
372401 return null ;
0 commit comments