我正在编写和Android应用程序通过ISO15693与RF430FRL152H设备进行通信。此应用程序尝试复制使用TRF7970A与设备通信的现有Qt C ++可执行文件。
如果设置了选项标志,我一直无法编写单个块,从而导致android.nfc.TagLostException。
TRF7970A可执行文件遵循TRF7960评估模式文档,该文档指出写单块(0x21)必须设置选项标志(0x40)。
我在自己的应用中观察到此行为以及来自TI论坛的示例Android应用:https://e2e.ti.com/support/wireless_connectivity/nfc_rfid/f/667/p/469938/1688321#1688321
Android Issue Tracker上的2011年帖子提到了Android的nfcV的一些问题,并在通用芯片上写了块,包括TI:https://code.google.com/p/android/issues/detail?id=15608
在我的应用程序中,这确实可以防止android.nfc.TagLostException,并且不会返回错误标志。但是,当我在固件通用控制寄存器中启用和设置中断字段时,我没有观察到预期的行为,所以我不确定这是一个完整的解决方案。
为了使问题更加复杂,从TRF7970A可执行文件中的写命令中删除选项标志继续正常工作。
这是编写单个块的正确方法吗? Android和TI设备之间是否存在已知问题,特别是RF430FRL152H?
public class MainActivity extends AppCompatActivity {
static final String LOG_TAG = MainActivity.class.getSimpleName();
NfcAdapter mNfcAdapter;
NfcV mNfcV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
}
private void enableForegroundDispatch() {
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
final IntentFilter intentFilter = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
IntentFilter[] intentFilters = new IntentFilter[] { intentFilter };
String[][] techListArray = new String[][] { new String[] { NfcV.class.getName() }};
mNfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFilters, techListArray);
}
@Override
public void onPause() {
super.onPause();
mNfcAdapter.disableForegroundDispatch(this);
}
@Override
public void onResume() {
super.onResume();
enableForegroundDispatch();
}
@Override
protected void onNewIntent(Intent intent) {
switch(intent.getAction())
{
case NfcAdapter.ACTION_TECH_DISCOVERED:
onNfcTagDiscoveredAction(intent);
break;
default:
break;
}
}
private void onNfcTagDiscoveredAction(Intent intent) {
if(mNfcV != null) {
return;
}
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
mNfcV = NfcV.get(tag);
AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
mNfcV.connect();
// TRF7970A "010C00030410002101000000" Register Write Request
// TRF7970A "0109000304F0000000" AGC Toggle
// TRF7970A "0109000304F1FF0000" AM PM Toggle
// TRF7970A "010B000304142401000000" ISO 15693 Inventory request
final byte[] INVENTORY = new byte[] { (byte) 0x24, (byte) 0x01, (byte) 0x00 };
byte[] inventoryResult = mNfcV.transceive(INVENTORY);
Log.d(LOG_TAG, "Inventory complete");
// TRF7970A "010C00030418002312010000"
final byte[] READ_MULTIPLE_BLOCK = new byte[] { (byte)0x00, (byte)0x23, (byte)0x12, (byte)0x01 };
byte[] readResult = mNfcV.transceive(READ_MULTIPLE_BLOCK);
Log.d(LOG_TAG, "Read multiple block complete, result length: " + readResult.length);
// TRF7970A "010F000304180221ff95fe00000000" Request mode
final byte[] WRITE_SINGLE_BLOCK_NO_OPTION = new byte[] { (byte)0x02, (byte)0x21, (byte)0xff, (byte)0x95, (byte)0xfe, (byte)0x00, (byte)0x00 };
byte[] noOptionResult = mNfcV.transceive(WRITE_SINGLE_BLOCK_NO_OPTION);
Log.d(LOG_TAG, "Wrote no option, result length: " + noOptionResult.length);
// TRF7970 "010F00030418402101010100000000" Request Mode
final byte[] WRITE_SINGLE_BLOCK_OPTION = new byte[] { (byte)0x40, (byte)0x21, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00, (byte)0x00 };
byte[] optionResult = mNfcV.transceive(WRITE_SINGLE_BLOCK_OPTION);
Log.d(LOG_TAG, "Wrote with option, result length: " + optionResult.length);
}
catch(Exception e) {
Log.d(LOG_TAG, "Exception: " + e.toString());
}
return null;
}
@Override
protected void onPostExecute(Void result)
{
mNfcV = null;
}
};
asyncTask.execute();
}
}