NfcAdapter.java revision e47150e933e6f610546f57183477f324566e521e
1/*
2 * Copyright (C) 2010 The Android Open Source Project Licensed under the Apache
3 * License, Version 2.0 (the "License"); you may not use this file except in
4 * compliance with the License. You may obtain a copy of the License at
5 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
6 * or agreed to in writing, software distributed under the License is
7 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8 * KIND, either express or implied. See the License for the specific language
9 * governing permissions and limitations under the License.
10 */
11
12package android.nfc;
13
14import java.lang.UnsupportedOperationException;
15
16import android.annotation.SdkConstant;
17import android.annotation.SdkConstant.SdkConstantType;
18import android.content.Context;
19import android.nfc.INfcAdapter;
20import android.os.IBinder;
21import android.os.RemoteException;
22import android.os.ServiceManager;
23import android.util.Log;
24
25/**
26 * Represents the device's local NFC adapter.
27 * <p>
28 * Use the static {@link #getDefaultAdapter} method to get the default NFC
29 * Adapter for this Android device. Most Android devices will have only one NFC
30 * Adapter, and {@link #getDefaultAdapter} returns the singleton object.
31 * <p>
32 * {@link NfcAdapter} can be used to create {@link RawTagConnection} or
33 * {@link NdefTagConnection} connections to modify or perform low level access
34 * to NFC Tags.
35 * <p class="note">
36 * <strong>Note:</strong> Some methods require the
37 * {@link android.Manifest.permission#NFC} permission.
38 */
39public final class NfcAdapter {
40    /**
41     * Intent to start an activity when a non-NDEF tag is discovered.
42     * TODO(npelly) finalize decision on using CATEGORY or DATA URI to provide a
43     * hint for applications to filter the tag type.
44     * TODO(npelly) probably combine these two intents since tags aren't that simple
45     */
46    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
47    public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
48
49    /**
50     * Intent to start an activity when a NDEF tag is discovered. TODO(npelly)
51     * finalize decision on using CATEGORY or DATA URI to provide a hint for
52     * applications to filter the tag type.
53     */
54    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
55    public static final String ACTION_NDEF_TAG_DISCOVERED =
56            "android.nfc.action.NDEF_TAG_DISCOVERED";
57
58    /**
59     * Mandatory Tag extra for the ACTION_TAG and ACTION_NDEF_TAG intents.
60     */
61    public static final String EXTRA_TAG = "android.nfc.extra.TAG";
62
63    /**
64     * Broadcast Action: a transaction with a secure element has been detected.
65     * <p>
66     * Always contains the extra field
67     * {@link android.nfc.NfcAdapter#EXTRA_AID}
68     * @hide
69     */
70    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
71    public static final String ACTION_TRANSACTION_DETECTED =
72            "android.nfc.action.TRANSACTION_DETECTED";
73
74    /**
75     * Mandatory byte array extra field in
76     * {@link android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED}.
77     * <p>
78     * Contains the AID of the applet involved in the transaction.
79     * @hide
80     */
81    public static final String EXTRA_AID = "android.nfc.extra.AID";
82
83    /**
84     * LLCP link status: The LLCP link is activated.
85     * @hide
86     */
87    public static final int LLCP_LINK_STATE_ACTIVATED = 0;
88
89    /**
90     * LLCP link status: The LLCP link is deactivated.
91     * @hide
92     */
93    public static final int LLCP_LINK_STATE_DEACTIVATED = 1;
94
95    /**
96     * Broadcast Action: the LLCP link state changed.
97     * <p>
98     * Always contains the extra field
99     * {@link android.nfc.NfcAdapter#EXTRA_LLCP_LINK_STATE_CHANGED}.
100     * @hide
101     */
102    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
103    public static final String ACTION_LLCP_LINK_STATE_CHANGED =
104            "android.nfc.action.LLCP_LINK_STATE_CHANGED";
105
106    /**
107     * Used as int extra field in
108     * {@link android.nfc.NfcAdapter#ACTION_LLCP_LINK_STATE_CHANGED}.
109     * <p>
110     * It contains the new state of the LLCP link.
111     * @hide
112     */
113    public static final String EXTRA_LLCP_LINK_STATE_CHANGED = "android.nfc.extra.LLCP_LINK_STATE";
114
115    /**
116     * Tag Reader Discovery mode
117     * @hide
118     */
119    private static final int DISCOVERY_MODE_TAG_READER = 0;
120
121    /**
122     * NFC-IP1 Peer-to-Peer mode Enables the manager to act as a peer in an
123     * NFC-IP1 communication. Implementations should not assume that the
124     * controller will end up behaving as an NFC-IP1 target or initiator and
125     * should handle both cases, depending on the type of the remote peer type.
126     * @hide
127     */
128    private static final int DISCOVERY_MODE_NFCIP1 = 1;
129
130    /**
131     * Card Emulation mode Enables the manager to act as an NFC tag. Provided
132     * that a Secure Element (an UICC for instance) is connected to the NFC
133     * controller through its SWP interface, it can be exposed to the outside
134     * NFC world and be addressed by external readers the same way they would
135     * with a tag.
136     * <p>
137     * Which Secure Element is exposed is implementation-dependent.
138     *
139     * @hide
140     */
141    private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
142
143    private static final String TAG = "NFC";
144
145    private static boolean sIsInitialized = false;
146    private static NfcAdapter sAdapter;
147
148    private final INfcAdapter mService;
149
150    private NfcAdapter(INfcAdapter service) {
151        mService = service;
152    }
153
154    /**
155     * Get a handle to the default NFC Adapter on this Android device.
156     * <p>
157     * Most Android devices will only have one NFC Adapter (NFC Controller).
158     *
159     * @return the default NFC adapter, or null if no NFC adapter exists
160     */
161    public static NfcAdapter getDefaultAdapter() {
162        synchronized (NfcAdapter.class) {
163            if (sIsInitialized) {
164                return sAdapter;
165            }
166            sIsInitialized = true;
167
168            IBinder b = ServiceManager.getService("nfc");
169            if (b == null) {
170                Log.d(TAG, "NFC Service not available");
171                return null;
172            }
173
174            sAdapter = new NfcAdapter(INfcAdapter.Stub.asInterface(b));
175            return sAdapter;
176        }
177    }
178
179    /**
180     * Return true if this NFC Adapter is enabled to discover new tags.
181     * <p>
182     * If this method returns false, then applications should request the user
183     * turn on NFC tag discovery in Settings.
184     *
185     * @return true if this NFC Adapter is enabled to discover new tags
186     */
187    public boolean isTagDiscoveryEnabled() {
188        try {
189            return mService.isEnabled();
190        } catch (RemoteException e) {
191            Log.e(TAG, "RemoteException in isEnabled()", e);
192            return false;
193        }
194    }
195
196    /**
197     * @hide
198     */
199    public boolean enableTagDiscovery() {
200        try {
201            return mService.enable();
202        } catch (RemoteException e) {
203            Log.e(TAG, "RemoteException in enable()", e);
204            return false;
205        }
206    }
207
208    /**
209     * @hide
210     */
211    public boolean disableTagDiscovery() {
212        try {
213            return mService.disable();
214        } catch (RemoteException e) {
215            Log.e(TAG, "RemoteException in disable()", e);
216            return false;
217        }
218    }
219
220    /**
221     * Set the NDEF Message that this NFC adapter should appear as to Tag
222     * readers.
223     * <p>
224     * Any Tag reader can read the contents of the local tag when it is in
225     * proximity, without any further user confirmation.
226     * <p>
227     * The implementation of this method must either
228     * <ul>
229     * <li>act as a passive tag containing this NDEF message
230     * <li>provide the NDEF message on over LLCP to peer NFC adapters
231     * </ul>
232     * The NDEF message is preserved across reboot.
233     * <p>Requires {@link android.Manifest.permission#NFC} permission.
234     *
235     * @param message NDEF message to make public
236     */
237    public void setLocalNdefMessage(NdefMessage message) {
238        try {
239            mService.localSet(message);
240        } catch (RemoteException e) {
241            Log.e(TAG, "NFC service died", e);
242        }
243    }
244
245    /**
246     * Get the NDEF Message that this adapter appears as to Tag readers.
247     * <p>Requires {@link android.Manifest.permission#NFC} permission.
248     *
249     * @return NDEF Message that is publicly readable
250     */
251    public NdefMessage getLocalNdefMessage() {
252        try {
253            return mService.localGet();
254        } catch (RemoteException e) {
255            Log.e(TAG, "NFC service died", e);
256            return null;
257        }
258    }
259
260    /**
261     * Create a raw tag connection to the default Target
262     * <p>Requires {@link android.Manifest.permission#NFC} permission.
263     */
264    public RawTagConnection createRawTagConnection(Tag tag) {
265        try {
266            return new RawTagConnection(mService, tag);
267        } catch (RemoteException e) {
268            Log.e(TAG, "NFC service died", e);
269            return null;
270        }
271    }
272
273    /**
274     * Create a raw tag connection to the specified Target
275     * <p>Requires {@link android.Manifest.permission#NFC} permission.
276     */
277    public RawTagConnection createRawTagConnection(Tag tag, String target) {
278        try {
279            return new RawTagConnection(mService, tag, target);
280        } catch (RemoteException e) {
281            Log.e(TAG, "NFC service died", e);
282            return null;
283        }
284    }
285
286    /**
287     * Create an NDEF tag connection to the default Target
288     * <p>Requires {@link android.Manifest.permission#NFC} permission.
289     */
290    public NdefTagConnection createNdefTagConnection(NdefTag tag) {
291        try {
292            return new NdefTagConnection(mService, tag);
293        } catch (RemoteException e) {
294            Log.e(TAG, "NFC service died", e);
295            return null;
296        }
297    }
298
299    /**
300     * Create an NDEF tag connection to the specified Target
301     * <p>Requires {@link android.Manifest.permission#NFC} permission.
302     */
303    public NdefTagConnection createNdefTagConnection(NdefTag tag, String target) {
304        try {
305            return new NdefTagConnection(mService, tag, target);
306        } catch (RemoteException e) {
307            Log.e(TAG, "NFC service died", e);
308            return null;
309        }
310    }
311}
312