最近在做Android扫描nfc设备的项目 发现只有一次扫描读取数据 一次扫描写入数据的情况 而没有一次扫描写入数据之后直接读取出来的需求 在这里记录一下
1.获取nfc设备支持的类型 有Nfca,Nfcv,Ndef,Isodep,MifareUltralight等 我们客户端需要知道nfc芯片支持的类型然后去做读写操作
以ndef为例下面为示例代码
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// 为了保证getIntent获取的是最新的
setIntent(intent);
if (startScan) {
//1.获取Tag对象
String action = intent.getAction();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) ||
NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) ||
NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
boolean result = writeTag(tag, intent);
Log.e("yanwei", "写标签标签成功..............................." + result);
}
}
}
/**
* 写数据
*
* @param tag 标签
* @return
*/
public boolean writeTag(Tag tag, Intent intent) {
String str[] = tag.getTechList();
if (str != null) {
if (str.length > 0) {
boolean supportNdef = false;
for (int i = 0; i < str.length; i++) {
if ("android.nfc.tech.Ndef".equals(str[i])) {
supportNdef = true;
}
Log.e("yanwei", "detectedTag = " + str[i]);
}
if (!supportNdef) {
Log.e("yanwei", "不支持ndef");
Toast.makeText(mContext, "芯片不支持ndef格式", Toast.LENGTH_SHORT).show();
} else {
}
}
}
NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{createRecord()});
try {
Ndef ndef = Ndef.get(tag);
if (ndef != null) {
int size = ndefMessage.toByteArray().length;
if (size > ndef.getMaxSize()) {
Log.e("yanwei ", "写不下 -- size = " + size + " , maxSize = " + ndef.getMaxSize());
}
ndef.connect();
if (!ndef.isWritable()) {
Log.e("yanwei ", "标签不可写入");
return false;
}
ndef.writeNdefMessage(ndefMessage);
Message msg = new Message();
msg.obj = intent;
mHandler.sendMessageDelayed(msg, 350);
return true;
} else {
NdefFormatable ndefFormatable = NdefFormatable.get(tag);
if (ndefFormatable != null) {
ndefFormatable.connect();
ndefFormatable.format(ndefMessage);
Log.e("yanwei", "type = " + "ndefFormatable");
return true;
} else {
Log.e("yanwei", "ndefFormatable不支持");
return false;
}
}
} catch (Exception e) {
startScan = false;
popWindow.dismiss();
Toast.makeText(mContext, "写入设备数据失败", Toast.LENGTH_LONG).show();
Log.e("yanwei", "Exception = " + e.getMessage() + " ,, " + e.getLocalizedMessage() + " ,, ");
}
return false;
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.e("yanwei", "3.5ms");
Intent intent = (Intent) msg.obj;
Parcelable[] rawMessage = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage[] ndefMessages = null;
// 判断是哪种类型的数据 默认为NDEF格式
if (rawMessage != null) {
ndefMessages = new NdefMessage[rawMessage.length];
for (int i = 0; i < rawMessage.length; i++) {
ndefMessages[i] = (NdefMessage) rawMessage[i];
}
}
NdefMessage ndefMessage = null;
if (ndefMessages.length > 0) {
ndefMessage = ndefMessages[0];
}
if (ndefMessage != null) {
NdefRecord record = ndefMessage.getRecords()[0];
parseTextRecord(record);
} else {
Log.e("yanwei", "ndefMessage == null");
startScan = false;
popWindow.dismiss();
Toast.makeText(mContext, "读取设备数据失败", Toast.LENGTH_LONG).show();
}
}
};
实际上我们通过onNewIntent方法回调接收到nfc相关的intent之后 Android设备就与nfc芯片创建了链接 不管你用哪种格式的数据(nfca,nfcv,ndef....)
他们都有一个创建链接的方法 例如:ndef.connect(); 创建链接之后 调用写入的方法开始写入 本例为350ms之后去intent中读取数据,也可以通过msg传值ndef来进行读取
msg.obg = ndef; Ndef ndef = (Ndef)msg.obg; NdefMessage message = ndef.getNdefMessage();这样读取 具体看你自己的需求 这样就可以写入数据之后 马上读取出数据了
而不用再次扫描设备 希望能帮到你
经过一番修改 发现了很多需要优化的地方
1.ndef读写数据的时候 需要在子线程中操作
2.在写入数据 350ms后(这个延时是用来给硬件接收我们写入数据之后操作的时长),判断ndef的链接状态,ndef.isConnect();如果返回false
说明当前链接已经中断,继续调用读取方法会报android.nfc.TagLostException异常 Android系统会默认开启第二次扫描
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
//1.获取Tag对象
String action = intent.getAction();
Log.e(TAG, "onNewIntent = " + action);
if (startScan) {
mIntent = intent;
startScan = false;
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) ||
NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) ||
NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
boolean result = writeTag();
Log.e(TAG, "写标签标签成功..............................." + result);
}
}
}
/**
* 写数据
*
* @return
*/
public boolean writeTag() {
String str[] = tag.getTechList();
if (str != null) {
if (str.length > 0) {
boolean supportNdef = false;
for (int i = 0; i < str.length; i++) {
if ("android.nfc.tech.Ndef".equals(str[i])) {
supportNdef = true;
}
Log.e(TAG, "detectedTag = " + str[i]);
}
if (!supportNdef) {
Log.e(TAG, "不支持ndef");
Toast.makeText(mContext, "芯片不支持ndef格式", Toast.LENGTH_SHORT).show();
} else {
}
}
}
final NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{createRecord()});
try {
final Ndef ndef = Ndef.get(tag);
if (ndef != null) {
int size = ndefMessage.toByteArray().length;
if (size > ndef.getMaxSize()) {
Log.e(TAG, "写不下 -- size = " + size + " , maxSize = " + ndef.getMaxSize());
}
ndef.connect();
if (!ndef.isWritable()) {
Log.e(TAG, "标签不可写入");
return false;
}
new Thread(new Runnable() {
@Override
public void run() {
try {
ndef.writeNdefMessage(ndefMessage);
Thread.sleep(350);
boolean isConnect = ndef.isConnected();
Log.e(TAG, "isConnect = " + isConnect);
NdefMessage ndefMsg = ndef.getNdefMessage();
Message msg = new Message();
msg.obj = ndefMsg;
msg.what = 0;
mHandler.sendMessage(msg);
ndef.close();
} catch (FormatException e) {
e.printStackTrace();
Log.e(TAG, "FormatException = " + e);
mHandler.sendEmptyMessage(1);
return;
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "IOException = " + e);
mHandler.sendEmptyMessage(1);
return;
} catch (InterruptedException e) {
e.printStackTrace();
Log.e(TAG, "InterruptedException = " + e);
mHandler.sendEmptyMessage(1);
return;
}
}
}).start();
return true;
} else {
NdefFormatable ndefFormatable = NdefFormatable.get(tag);
if (ndefFormatable != null) {
ndefFormatable.connect();
ndefFormatable.format(ndefMessage);
Log.e(TAG, "type = " + "ndefFormatable");
return true;
} else {
Log.e(TAG, "ndefFormatable不支持");
return false;
}
}
} catch (Exception e) {
startScan = false;
popWindow.dismiss();
Toast.makeText(mContext, "写入设备数据失败", Toast.LENGTH_LONG).show();
Log.e(TAG, "Exception = " + e.getMessage() + " ,, " + e.getLocalizedMessage() + " ,, ");
}
return false;
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.e(TAG, "350ms");
if (msg.what == 0) {
NdefMessage ndefMessage = (NdefMessage) msg.obj;
if (ndefMessage != null) {
NdefRecord record = ndefMessage.getRecords()[0];
parseTextRecord(record);
} else {
Log.e(TAG, "ndefMessage == null");
startScan = false;
popWindow.dismiss();
Toast.makeText(mContext, "读取设备数据失败", Toast.LENGTH_LONG).show();
}
} else {
startScan = false;
popWindow.dismiss();
Toast.makeText(mContext, "通讯失败", Toast.LENGTH_LONG).show();
}
}
};