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