BasicTagTechnology.java revision a71354d76689802152c33af257092d639c03c421
1590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/*
2590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Copyright (C) 2010 The Android Open Source Project
3590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *
4590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * you may not use this file except in compliance with the License.
6590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * You may obtain a copy of the License at
7590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *
8590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *
10590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Unless required by applicable law or agreed to in writing, software
11590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * See the License for the specific language governing permissions and
14590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * limitations under the License.
15590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */
16590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
17590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellypackage android.nfc;
18590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
19590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport java.io.IOException;
20590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
21590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.os.RemoteException;
22590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.util.Log;
23590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
24590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/**
25c9f7890a203a013646650a695157277df81b6a17Scott Main * A low-level connection to a {@link Tag} target.
26c9f7890a203a013646650a695157277df81b6a17Scott Main * <p>You can acquire this kind of connection with {@link NfcAdapter#createRawTagConnection
27c9f7890a203a013646650a695157277df81b6a17Scott Main * createRawTagConnection()}. Use the connection to send and receive data with {@link #transceive
28c9f7890a203a013646650a695157277df81b6a17Scott Main * transceive()}.
29590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p>
30c9f7890a203a013646650a695157277df81b6a17Scott Main * Applications must implement their own protocol stack on top of {@link #transceive transceive()}.
31590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *
32c9f7890a203a013646650a695157277df81b6a17Scott Main * <p class="note"><strong>Note:</strong>
33e47150e933e6f610546f57183477f324566e521eNick Pelly * Use of this class requires the {@link android.Manifest.permission#NFC}
34c9f7890a203a013646650a695157277df81b6a17Scott Main * permission.
35590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */
36590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellypublic class RawTagConnection {
37590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
38590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /*package*/ final INfcAdapter mService;
39590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /*package*/ final INfcTag mTagService;
40590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /*package*/ final Tag mTag;
41590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /*package*/ boolean mIsConnected;
42a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau    /*package*/ String mSelectedTarget;
43590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
44590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private static final String TAG = "NFC";
45590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
46a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau    /* package private */ RawTagConnection(INfcAdapter service, Tag tag, String target) throws RemoteException {
47a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau        String[] targets = tag.getRawTargets();
48a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau        int i;
49a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau
50a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau        // Check target validity
51a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau        for (i=0;i<targets.length;i++) {
52a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau            if (target.equals(targets[i])) {
53a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau                break;
54a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau            }
55a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau        }
56a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau        if (i >= targets.length) {
57a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau            // Target not found
58a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau            throw new IllegalArgumentException();
59a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau        }
60a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau
61590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        mService = service;
62590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        mTagService = service.getNfcTagInterface();
63590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        mService.openTagConnection(tag);  // TODO(nxp): don't connect until connect()
64590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        mTag = tag;
65a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau        mSelectedTarget = target;
66a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau    }
67a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau
68a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau    /* package private */ RawTagConnection(INfcAdapter service, Tag tag) throws RemoteException {
69a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau        this(service, tag, tag.getRawTargets()[0]);
70590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
71590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
72590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
73c9f7890a203a013646650a695157277df81b6a17Scott Main     * Get the {@link Tag} this connection is associated with.
74e47150e933e6f610546f57183477f324566e521eNick Pelly     * <p>Requires {@link android.Manifest.permission#NFC} permission.
75590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
76590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public Tag getTag() {
77590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        return mTag;
78590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
79590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
80e47150e933e6f610546f57183477f324566e521eNick Pelly    /**
81e47150e933e6f610546f57183477f324566e521eNick Pelly     * <p>Requires {@link android.Manifest.permission#NFC} permission.
82e47150e933e6f610546f57183477f324566e521eNick Pelly     */
83590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public String getTagTarget() {
84a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau        return mSelectedTarget;
85590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
86590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
87590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
88c9f7890a203a013646650a695157277df81b6a17Scott Main     * Helper to indicate if {@link #transceive transceive()} calls might succeed.
89590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * <p>
90590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * Does not cause RF activity, and does not block.
91e47150e933e6f610546f57183477f324566e521eNick Pelly     * <p>Requires {@link android.Manifest.permission#NFC} permission.
92c9f7890a203a013646650a695157277df81b6a17Scott Main     * @return true if {@link #connect} has completed successfully and the {@link Tag} is believed
93c9f7890a203a013646650a695157277df81b6a17Scott Main     * to be within range. Applications must still handle {@link java.io.IOException}
94c9f7890a203a013646650a695157277df81b6a17Scott Main     * while using {@link #transceive transceive()}, in case connection is lost after this method
95c9f7890a203a013646650a695157277df81b6a17Scott Main     * returns true.
96590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
97590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public boolean isConnected() {
98a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau        if (!mIsConnected) {
99a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau            return false;
100a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau        }
101a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau
102a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau        try {
103a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau            return mTagService.isPresent(mTag.mNativeHandle);
104a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau        } catch (RemoteException e) {
105a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau            Log.e(TAG, "NFC service died", e);
106a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau            return false;
107a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau        }
108590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
109590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
110590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
111c9f7890a203a013646650a695157277df81b6a17Scott Main     * Connect to the {@link Tag} associated with this connection.
112590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * <p>
113590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * This method blocks until the connection is established.
114590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * <p>
115c9f7890a203a013646650a695157277df81b6a17Scott Main     * {@link #close} can be called from another thread to cancel this connection
116590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * attempt.
117e47150e933e6f610546f57183477f324566e521eNick Pelly     * <p>Requires {@link android.Manifest.permission#NFC} permission.
118590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * @throws IOException if the target is lost, or connect canceled
119590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
120590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public void connect() throws IOException {
121590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        //TODO(nxp): enforce exclusivity
122590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        mIsConnected = true;
123590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
124590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
125590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
126c9f7890a203a013646650a695157277df81b6a17Scott Main     * Close this connection.
127590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * <p>
128c9f7890a203a013646650a695157277df81b6a17Scott Main     * Causes blocking operations such as {@link #transceive transceive()} or {@link #connect} to
129c9f7890a203a013646650a695157277df81b6a17Scott Main     * be canceled and immediately throw {@link java.io.IOException}.
130590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * <p>
131c9f7890a203a013646650a695157277df81b6a17Scott Main     * Once this method is called, this object cannot be re-used and should be discarded. Further
132c9f7890a203a013646650a695157277df81b6a17Scott Main     * calls to {@link #transceive transceive()} or {@link #connect} will fail.
133e47150e933e6f610546f57183477f324566e521eNick Pelly     * <p>Requires {@link android.Manifest.permission#NFC} permission.
134590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
135590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public void close() {
136590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        mIsConnected = false;
137590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        try {
138590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            mTagService.close(mTag.mNativeHandle);
139590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        } catch (RemoteException e) {
140590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            Log.e(TAG, "NFC service died", e);
141590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
142590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
143590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
144590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
145c9f7890a203a013646650a695157277df81b6a17Scott Main     * Send data to a tag and receive the response.
146590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * <p>
147590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * This method will block until the response is received. It can be canceled
148c9f7890a203a013646650a695157277df81b6a17Scott Main     * with {@link #close}.
149e47150e933e6f610546f57183477f324566e521eNick Pelly     * <p>Requires {@link android.Manifest.permission#NFC} permission.
150590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     *
151590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * @param data bytes to send
152590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * @return bytes received in response
153590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * @throws IOException if the target is lost or connection closed
154590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
155590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public byte[] transceive(byte[] data) throws IOException {
156590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        try {
157590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            byte[] response = mTagService.transceive(mTag.mNativeHandle, data);
158590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            if (response == null) {
159590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly                throw new IOException("transcieve failed");
160590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            }
161590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            return response;
162590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        } catch (RemoteException e) {
163590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            Log.e(TAG, "NFC service died", e);
164590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            throw new IOException("NFC service died");
165590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
166590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
167590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly}
168