最近在做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();
}
}
};