BasicTagTechnology.java revision 0d27f999f4b1ad51da11946800b40d2978fc6326
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 176be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonpackage android.nfc.technology; 18590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 19590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport java.io.IOException; 20590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 216be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.INfcAdapter; 226be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.INfcTag; 236be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.NfcAdapter; 246be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.Tag; 254049f9d00a86f848d42d2429068496b31a6795adMartijn Coenenimport android.nfc.ErrorCodes; 26590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.os.RemoteException; 27590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.util.Log; 28590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 29590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/** 306be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * A base class for tag technologies that are built on top of transceive(). 31590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 326be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton/* package */ abstract class BasicTagTechnology implements TagTechnology { 33590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 34590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /*package*/ final Tag mTag; 35590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /*package*/ boolean mIsConnected; 366be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton /*package*/ int mSelectedTechnology; 376d55e1342fc35c26dd97700ae791b34668266018Nick Pelly private final NfcAdapter mAdapter; 386d55e1342fc35c26dd97700ae791b34668266018Nick Pelly 396d55e1342fc35c26dd97700ae791b34668266018Nick Pelly // Following fields are final after construction, except for 406d55e1342fc35c26dd97700ae791b34668266018Nick Pelly // during attemptDeadServiceRecovery() when NFC crashes. 416d55e1342fc35c26dd97700ae791b34668266018Nick Pelly // Not locked - we accept a best effort attempt when NFC crashes. 426d55e1342fc35c26dd97700ae791b34668266018Nick Pelly /*package*/ INfcAdapter mService; 436d55e1342fc35c26dd97700ae791b34668266018Nick Pelly /*package*/ INfcTag mTagService; 44590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 45590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private static final String TAG = "NFC"; 46590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 476be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton /** 486be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * @hide 496be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton */ 506be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton public BasicTagTechnology(NfcAdapter adapter, Tag tag, int tech) throws RemoteException { 516be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton int[] techList = tag.getTechnologyList(); 52a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau int i; 53a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau 54a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau // Check target validity 556be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton for (i = 0; i < techList.length; i++) { 566be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton if (tech == techList[i]) { 57a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau break; 58a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau } 59a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau } 606be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton if (i >= techList.length) { 616be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton // Technology not found 626be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton throw new IllegalArgumentException("Technology " + tech + " not present on tag " + tag); 63a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau } 64a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau 656d55e1342fc35c26dd97700ae791b34668266018Nick Pelly mAdapter = adapter; 666be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton mService = mAdapter.getService(); 671253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen try { 681253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen mTagService = mService.getNfcTagInterface(); 691253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen } catch (RemoteException e) { 701253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen attemptDeadServiceRecovery(e); 711253ebc74a8453a88dc47a2b698145098d201681Martijn Coenen } 72590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly mTag = tag; 736be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton mSelectedTechnology = tech; 74a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau } 75a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau 766be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton /** 776be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * @hide 786be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton */ 796be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton public BasicTagTechnology(NfcAdapter adapter, Tag tag) throws RemoteException { 806be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton this(adapter, tag, tag.getTechnologyList()[0]); 816d55e1342fc35c26dd97700ae791b34668266018Nick Pelly } 826d55e1342fc35c26dd97700ae791b34668266018Nick Pelly 836d55e1342fc35c26dd97700ae791b34668266018Nick Pelly /** NFC service dead - attempt best effort recovery */ 846d55e1342fc35c26dd97700ae791b34668266018Nick Pelly /*package*/ void attemptDeadServiceRecovery(Exception e) { 856d55e1342fc35c26dd97700ae791b34668266018Nick Pelly mAdapter.attemptDeadServiceRecovery(e); 866d55e1342fc35c26dd97700ae791b34668266018Nick Pelly /* assigning to mService is not thread-safe, but this is best-effort code 876d55e1342fc35c26dd97700ae791b34668266018Nick Pelly * and on a well-behaved system should never happen */ 886be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton mService = mAdapter.getService(); 896d55e1342fc35c26dd97700ae791b34668266018Nick Pelly try { 906d55e1342fc35c26dd97700ae791b34668266018Nick Pelly mTagService = mService.getNfcTagInterface(); 916d55e1342fc35c26dd97700ae791b34668266018Nick Pelly } catch (RemoteException e2) { 926d55e1342fc35c26dd97700ae791b34668266018Nick Pelly Log.e(TAG, "second RemoteException trying to recover from dead NFC service", e2); 936d55e1342fc35c26dd97700ae791b34668266018Nick Pelly } 94590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 95590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 96590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /** 97c9f7890a203a013646650a695157277df81b6a17Scott Main * Get the {@link Tag} this connection is associated with. 98e47150e933e6f610546f57183477f324566e521eNick Pelly * <p>Requires {@link android.Manifest.permission#NFC} permission. 99590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 1006be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton @Override 101590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly public Tag getTag() { 102590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return mTag; 103590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 104590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 1054049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen public void checkConnected() { 1064049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen if ((mTag.getConnectedTechnology() != getTechnologyId()) || 1074049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen (mTag.getConnectedTechnology() == -1)) { 1084049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen throw new IllegalStateException("Call connect() first!"); 1094049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } 1104049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } 1114049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen 112e47150e933e6f610546f57183477f324566e521eNick Pelly /** 113e47150e933e6f610546f57183477f324566e521eNick Pelly * <p>Requires {@link android.Manifest.permission#NFC} permission. 114e47150e933e6f610546f57183477f324566e521eNick Pelly */ 1156be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton @Override 1166be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton public int getTechnologyId() { 1176be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton return mSelectedTechnology; 118590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 119590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 120590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /** 121c9f7890a203a013646650a695157277df81b6a17Scott Main * Helper to indicate if {@link #transceive transceive()} calls might succeed. 122590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p> 123590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Does not cause RF activity, and does not block. 124e47150e933e6f610546f57183477f324566e521eNick Pelly * <p>Requires {@link android.Manifest.permission#NFC} permission. 125c9f7890a203a013646650a695157277df81b6a17Scott Main * @return true if {@link #connect} has completed successfully and the {@link Tag} is believed 126c9f7890a203a013646650a695157277df81b6a17Scott Main * to be within range. Applications must still handle {@link java.io.IOException} 127c9f7890a203a013646650a695157277df81b6a17Scott Main * while using {@link #transceive transceive()}, in case connection is lost after this method 128c9f7890a203a013646650a695157277df81b6a17Scott Main * returns true. 129590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 130590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly public boolean isConnected() { 131a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau if (!mIsConnected) { 132a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau return false; 133a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau } 134a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau 135a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau try { 1366be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton return mTagService.isPresent(mTag.getServiceHandle()); 137a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau } catch (RemoteException e) { 1386d55e1342fc35c26dd97700ae791b34668266018Nick Pelly attemptDeadServiceRecovery(e); 139a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau return false; 140a71354d76689802152c33af257092d639c03c421Sylvain Fonteneau } 141590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 142590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 143590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /** 144c9f7890a203a013646650a695157277df81b6a17Scott Main * Connect to the {@link Tag} associated with this connection. 145590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p> 146590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * This method blocks until the connection is established. 147590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p> 148c9f7890a203a013646650a695157277df81b6a17Scott Main * {@link #close} can be called from another thread to cancel this connection 149590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * attempt. 150e47150e933e6f610546f57183477f324566e521eNick Pelly * <p>Requires {@link android.Manifest.permission#NFC} permission. 151590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * @throws IOException if the target is lost, or connect canceled 152590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 1536be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton @Override 154590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly public void connect() throws IOException { 1554049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen try { 1564049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen int errorCode = mTagService.connect(mTag.getServiceHandle(), getTechnologyId()); 1574049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen 1584049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen if (errorCode == ErrorCodes.SUCCESS) { 1594049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen // Store this in the tag object 1604049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen mTag.setConnectedTechnology(getTechnologyId()); 1614049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen mIsConnected = true; 1624049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } else { 1634049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen throw new IOException(); 1644049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } 1654049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } catch (RemoteException e) { 1664049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen attemptDeadServiceRecovery(e); 1670d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen throw new IOException("NFC service died"); 1680d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen } 1690d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen } 1700d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen 1710d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen /** 1720d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen * Re-connect to the {@link Tag} associated with this connection. 1730d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen * <p> 1740d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen * Reconnecting to a tag can be used to reset the state of the tag itself. 1750d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen * This method blocks until the connection is re-established. 1760d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen * <p> 1770d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen * {@link #close} can be called from another thread to cancel this connection 1780d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen * attempt. 1790d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen * <p>Requires {@link android.Manifest.permission#NFC} permission. 1800d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen * @throws IOException if the target is lost, or connect canceled 1810d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen */ 1820d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen @Override 1830d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen public void reconnect() throws IOException { 1840d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen if (!mIsConnected) { 1850d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen throw new IllegalStateException("Technology not connected yet"); 1860d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen } else { 1870d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen try { 1880d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen int errorCode = mTagService.reconnect(mTag.getServiceHandle()); 1890d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen 1900d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen if (errorCode != ErrorCodes.SUCCESS) { 1910d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen mIsConnected = false; 1920d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen mTag.setTechnologyDisconnected(); 1930d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen throw new IOException(); 1940d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen } 1950d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen } catch (RemoteException e) { 1960d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen mIsConnected = false; 1970d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen mTag.setTechnologyDisconnected(); 1980d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen attemptDeadServiceRecovery(e); 1990d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen throw new IOException("NFC service died"); 2000d27f999f4b1ad51da11946800b40d2978fc6326Martijn Coenen } 2014049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } 202590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 203590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 204590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /** 205c9f7890a203a013646650a695157277df81b6a17Scott Main * Close this connection. 206590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p> 207c9f7890a203a013646650a695157277df81b6a17Scott Main * Causes blocking operations such as {@link #transceive transceive()} or {@link #connect} to 208c9f7890a203a013646650a695157277df81b6a17Scott Main * be canceled and immediately throw {@link java.io.IOException}. 209590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p> 210c9f7890a203a013646650a695157277df81b6a17Scott Main * Once this method is called, this object cannot be re-used and should be discarded. Further 211c9f7890a203a013646650a695157277df81b6a17Scott Main * calls to {@link #transceive transceive()} or {@link #connect} will fail. 212e47150e933e6f610546f57183477f324566e521eNick Pelly * <p>Requires {@link android.Manifest.permission#NFC} permission. 213590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 2146be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton @Override 215590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly public void close() { 216590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly try { 217b79173f6602359d00a1a89f4d6505a44d461d796Martijn Coenen /* Note that we don't want to physically disconnect the tag, 218b79173f6602359d00a1a89f4d6505a44d461d796Martijn Coenen * but just reconnect to it to reset its state 219b79173f6602359d00a1a89f4d6505a44d461d796Martijn Coenen */ 220b79173f6602359d00a1a89f4d6505a44d461d796Martijn Coenen mTagService.reconnect(mTag.getServiceHandle()); 221590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } catch (RemoteException e) { 2226d55e1342fc35c26dd97700ae791b34668266018Nick Pelly attemptDeadServiceRecovery(e); 2234049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen } finally { 2244049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen mIsConnected = false; 2254049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen mTag.setTechnologyDisconnected(); 226590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 227590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 228590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 229590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /** 230c9f7890a203a013646650a695157277df81b6a17Scott Main * Send data to a tag and receive the response. 231590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * <p> 232590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * This method will block until the response is received. It can be canceled 233c9f7890a203a013646650a695157277df81b6a17Scott Main * with {@link #close}. 234e47150e933e6f610546f57183477f324566e521eNick Pelly * <p>Requires {@link android.Manifest.permission#NFC} permission. 235590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * 236590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * @param data bytes to send 237590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * @return bytes received in response 238590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * @throws IOException if the target is lost or connection closed 239590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */ 240590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly public byte[] transceive(byte[] data) throws IOException { 2414049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen checkConnected(); 2424049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen 243590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly try { 244fc5a3b6cfb85679e82a39730c7154b55b0711a0cMartijn Coenen byte[] response = mTagService.transceive(mTag.getServiceHandle(), data, true); 245590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly if (response == null) { 246fc5a3b6cfb85679e82a39730c7154b55b0711a0cMartijn Coenen throw new IOException("transceive failed"); 247590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 248590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return response; 249590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } catch (RemoteException e) { 2506d55e1342fc35c26dd97700ae791b34668266018Nick Pelly attemptDeadServiceRecovery(e); 251590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly throw new IOException("NFC service died"); 252590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 253590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 254590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly} 255