坑
在ionic掃一掃與NFC功能開發(fā)要點(diǎn)我們介紹了如何引入NFC插件,即通過NFC的addNdefListener事件來監(jiān)聽楣颠,下面我們來說說這個(gè)插件踩了哪些坑
多次響應(yīng)
我們通過this.nfc.addNdefListener().subscribe()來對(duì)nfc返回的observer對(duì)象注冊回調(diào)笛洛,然而實(shí)際調(diào)試過程中夏志,一次NFC接觸事件竟然調(diào)用回調(diào)函數(shù)多次,沒辦法苛让,我們只好通過flag來控制沟蔑,回調(diào)過一次以后,就不讓其執(zhí)行了狱杰,并且在合適的地方重置該狀態(tài)溉贿。
console.log("接收到NFC事件,此時(shí)標(biāo)記為" + this.global.NfcFlag);
if (!this.global.NfcFlag) {
console.log("請(qǐng)等待上一次處理結(jié)束");
return false;
}
this.global.NfcFlag = false;
console.log("識(shí)別到的NFC標(biāo)記為:" + JSON.stringify(data));
if (data && data.tag && data.tag.id && data.tag.ndefMessage && data.tag.ndefMessage.length) {
let payload = data.tag.ndefMessage[0]["payload"];
//標(biāo)記語言字段的長度
let langLength = payload[0] & 63;
//跳過語言標(biāo)記
let tagContent = this.nfc.bytesToString(payload).slice(langLength + 1);
console.log('成功掃描到NFC標(biāo)簽內(nèi)容:' + tagContent);
if (tagContent) {
//拿到tagContent浦旱,解析id
let ucode = this.getCode(tagContent, 'ucode');
if (ucode) {
//解析到正確的ucode,開始鑒權(quán)
this.checkLegality(ucode);
} else {
//解析失敗
this.errorUcode(tagContent);
}
} else {
this.errorUcode(tagContent);
}
} else {
//無法識(shí)別的tag
this.errorUcode("");
}
第一次進(jìn)入頁面不響應(yīng)
這個(gè)問題確實(shí)困擾了我比較長時(shí)間宇色,通過android studio查看日志發(fā)現(xiàn),第一次其實(shí)有響應(yīng)颁湖,只是沒有進(jìn)入我們在subscribe里注冊的回調(diào)宣蠕。后來查閱相關(guān)資料(請(qǐng)見參考文獻(xiàn))才發(fā)現(xiàn),在插件的java實(shí)現(xiàn)中抢蚀,第一次解析到的是ACTION_NDEF_DISCOVERED,此時(shí)addTagDiscoveredListener能捕獲到該實(shí)際镰禾,而addNdefListener并不響應(yīng)皿曲!然而addTagDiscoveredListener無法得到ndef數(shù)據(jù)吴侦,只能得到tag信息备韧。通過比較和實(shí)驗(yàn)织堂,最后我們綁定原生事件來解決該問題:
document.addEventListener("ndef-mime", this.nfcListenerSubscribe.bind(this), false);
document.addEventListener("tag", this.nfcListenerSubscribe.bind(this), false);
這里我們也綁定了tag事件易阳,來對(duì)非ndef標(biāo)簽也進(jìn)行監(jiān)聽潦俺,這樣即便是空白卡拒课,或者其他卡比如公交卡徐勃,也會(huì)進(jìn)入到我們的應(yīng)用而不會(huì)啟動(dòng)應(yīng)用詢問窗口了。
多次寫數(shù)據(jù)會(huì)crash
主要可能還是內(nèi)存問題捕发,我們需要在頁面離開時(shí),取消事件綁定:
ionViewWillLeave() {
document.removeEventListener("ndef-mime", this.nfcListenerSubscribe, false);
document.removeEventListener("tag", this.nfcListenerSubscribe, false);
}
NFC識(shí)別后結(jié)果頁動(dòng)畫異常
這個(gè)問題比較詭異很魂,直接從NFC跳轉(zhuǎn)過來扎酷,對(duì)數(shù)據(jù)進(jìn)行處理并做一定的動(dòng)畫來演示整個(gè)過程,第一遍是可以的遏匆,反復(fù)執(zhí)行動(dòng)畫則出現(xiàn)動(dòng)畫卡頓異常法挨。然而從其他頁面跳轉(zhuǎn)則無此問題,初步分析是因?yàn)轫撁婧蚇FC插件共享一個(gè)進(jìn)程導(dǎo)致資源不足幅聘,這里我們經(jīng)過反復(fù)測試凡纳,用一個(gè)hack來解決。具體方案是定義一個(gè)標(biāo)志位帝蒿,當(dāng)NFC識(shí)別成功后修改該標(biāo)志位荐糜。在頁面ionViewDidEnter中,定義一個(gè)定時(shí)器葛超,監(jiān)控到該值改變即跳轉(zhuǎn)頁面:
let timer = setInterval(()=>{
if(this.chipInfo.tagid) {
clearInterval(timer);
timer = null;
this.navCtrl.push(BarcodeResultPage, {
tagid: this.chipInfo.tagid,
signature: this.chipInfo.signature,
ucode: this.chipInfo.ucode
});
}
}, 80);
這里使用Observable或者事件通知更優(yōu)雅暴氏,然而這兩種方式?jīng)]有解決該問題,具體原因可能還是之前分析的绣张,和NFC模塊共享進(jìn)程資源所導(dǎo)致答渔。
其他
我們剛剛提到了在合適的時(shí)候重置狀態(tài)位,由于我們的操作都是頁面跳轉(zhuǎn)侥涵,因此我們在離開頁面和進(jìn)入頁面時(shí)進(jìn)行狀態(tài)為設(shè)置沼撕,即
ionViewWillLeave() {
console.log("即將離開NFC頁面");
this.global.NfcFlag = false;
}
ionViewDidEnter() {
this.global.NfcFlag = true; //允許NFC
console.log("在進(jìn)入頁面時(shí)重置flag為true,又可以處理NFC事件了芜飘!");
}
這里使用ionViewDidEnter或者ionViewWillEnter而不放在構(gòu)造函數(shù)中务豺,是為了防止下一個(gè)頁面返回時(shí)不會(huì)重新構(gòu)造,但是可以響應(yīng)以上兩個(gè)函數(shù)嗦明。