// 包路径 const package_NdefRecord = 'android.nfc.NdefRecord'; const package_NdefMessage = 'android.nfc.NdefMessage'; const package_TECH_DISCOVERED = 'android.nfc.action.TECH_DISCOVERED'; const package_Intent = 'android.content.Intent'; const package_Activity = 'android.app.Activity'; const package_PendingIntent = 'android.app.PendingIntent'; const package_IntentFilter = 'android.content.IntentFilter'; const package_NfcAdapter = 'android.nfc.NfcAdapter'; const package_Ndef = 'android.nfc.tech.Ndef'; const package_NdefFormatable = 'android.nfc.tech.NdefFormatable'; const package_Parcelable = 'android.os.Parcelable'; const package_String = 'java.lang.String'; let NfcAdapter; let NdefRecord; let NdefMessage; let Uri; let readyWriteData = false; let readyRead = false; let readySetPwd = false; let readyDelPwd = false; let readyGetNfcState = false; let readyWriteAndLock = false; let noNFC = false; let techListsArray = [ ['android.nfc.tech.IsoDep'], ['android.nfc.tech.NfcA'], ['android.nfc.tech.NfcB'], ['android.nfc.tech.NfcF'], ['android.nfc.tech.Nfcf'], ['android.nfc.tech.NfcV'], ['android.net.Uri'], ['android.nfc.tech.NdefFormatable'], ['android.nfc.tech.MifareClassi'], ['android.nfc.tech.MifareUltralight'] ]; let UriPrefixMap = []; UriPrefixMap[0x00] = ''; UriPrefixMap[0x01] = 'http://www.'; UriPrefixMap[0x02] = 'https://www.'; UriPrefixMap[0x03] = 'http://'; UriPrefixMap[0x04] = 'https://'; UriPrefixMap[0x05] = 'tel:'; UriPrefixMap[0x06] = 'mailto:'; UriPrefixMap[0x07] = 'ftp://anonymous:anonymous@'; UriPrefixMap[0x08] = 'ftp://ftp.'; UriPrefixMap[0x09] = 'ftps://'; let writeUri = 'http://www.beswell.com'; // 要写入的数据 let readResult = ''; // NFC读取到的数据 let pwdBytes = [1, 2, 3, 4]; // 待写入的密码 let pwdDefault = [0xFF, 0xFF, 0xFF, 0xFF] // 清除密码后设置的默认值 export default { listenNFCStatus: function() { let that = this; try { let main = plus.android.runtimeMainActivity(); let Intent = plus.android.importClass('android.content.Intent'); let Activity = plus.android.importClass('android.app.Activity'); let PendingIntent = plus.android.importClass('android.app.PendingIntent'); let IntentFilter = plus.android.importClass('android.content.IntentFilter'); Uri = plus.android.importClass('android.net.Uri'); NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter'); let nfcAdapter = NfcAdapter.getDefaultAdapter(main); if (nfcAdapter == null) { uni.showToast({ title: '设备不支持NFC!', icon: 'none' }) noNFC = true; return; } if (!nfcAdapter.isEnabled()) { uni.showToast({ title: '请在系统设置中先启用NFC功能!', icon: 'none' }); noNFC = true; return; } else { noNFC = false; } let intent = new Intent(main, main.getClass()); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); let pendingIntent = PendingIntent.getActivity(main, 0, intent, 0); let ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED"); ndef.addDataType("*/*"); let intentFiltersArray = [ndef]; plus.globalEvent.addEventListener('newintent', function() { console.log('newintent running'); // 监听 NFC setTimeout(()=>{ that.nfcRuning() }, 100); }); plus.globalEvent.addEventListener('pause', function(e) { console.log('pause running'); if (nfcAdapter) { //关闭前台调度系统 //恢复默认状态 nfcAdapter.disableForegroundDispatch(main); } }); plus.globalEvent.addEventListener('resume', function(e) { console.log('resume running'); if (nfcAdapter) { //开启前台调度系统 nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray); } }); nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray); } catch (e) { console.error(e); } }, nfcRuning: function() { NdefRecord = plus.android.importClass("android.nfc.NdefRecord"); NdefMessage = plus.android.importClass("android.nfc.NdefMessage"); let main = plus.android.runtimeMainActivity(); let intent = main.getIntent(); // let intent = plus.android.invoke(main, 'getIntent'); let that = this; console.log("action type:" + intent.getAction()); if (package_TECH_DISCOVERED == intent.getAction()) { if (readyWriteData) { that.write(intent); readyWriteData = false; } else if (readyRead) { that.read(intent); readyRead = false; } else if (readySetPwd) { that.setPassword(intent); readySetPwd = false; } else if (readyDelPwd) { that.delPassword(intent); readyDelPwd = false; } else if (readyGetNfcState) { that.getState(intent); readyGetNfcState = false; } else if (readyWriteAndLock) { let result = that.write(intent); if (result == 999) { // 已设置密码保护 readyWriteAndLock = false; return } setTimeout(()=>{ that.setPassword(intent) }, 100); readyWriteAndLock = false; } else { that.read(intent); readyRead = false; } } }, write(intent) { try { toast('请勿移开标签 正在写入...'); console.log("NFC写入内容 writeUri = " + writeUri); // let textBytes = plus.android.invoke(writeUri, "getBytes"); let uri = Uri.parse(writeUri) let message = new NdefMessage([new NdefRecord.createUri(uri)]); console.log("==== message ===>", message) let Ndef = plus.android.importClass('android.nfc.tech.Ndef'); let NdefFormatable = plus.android.importClass('android.nfc.tech.NdefFormatable'); let tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); let MifareUltralight = plus.android.importClass('android.nfc.tech.MifareUltralight'); let mfc = MifareUltralight.get(tag); if (mfc != null) { mfc.connect(); let responseAuth0 = mfc.readPages(0x29) console.log("responseAuth0=" + JSON.stringify(responseAuth0)); if (responseAuth0[3] == 0x00) { toast('已设置密码保护,无法写入数据'); return 999; } mfc.close(); } let ndef = Ndef.get(tag); if (ndef != null) { // 待写入的数据长度 let size = message.toByteArray().length; ndef.connect(); if (!ndef.isWritable()) { ndef.close(); toast('tag不允许写入!'); return; } if (ndef.getMaxSize() < size) { ndef.close(); toast('文件大小超出容量!'); return; } ndef.writeNdefMessage(message); ndef.close(); toast('写入数据成功!'); return; } else { let format = NdefFormatable.get(tag); if (format != null) { try { format.connect(); format.format(message); format.close(); toast('格式化tag并且写入message'); return; } catch (e) { toast('格式化tag失败.'); return; } } else { toast('Tag不支持NDEF'); return; } } } catch (e) { toast('写入失败'); console.log("error=" + e); } }, read(intent) { toast('请勿移开标签正在读取数据'); let that = this; // NFC id let bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID); let nfc_id = that.byteArrayToHexString(bytesId); // console.log('nfc_id: ' + nfc_id); // let Parcelable = plus.android.importClass("android.os.Parcelable"); // tmp add // let Tag = plus.android.importClass('android.nfc.Tag'); // let Ndef = plus.android.importClass('android.nfc.tech.Ndef'); // let tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); // let ndef = Ndef.get(tag); // let nfc_type = that.byteArrayToHexString(ndef.getType()); // console.log('nfc_type:"' + nfc_type + '"') let rawmsgs = intent.getParcelableArrayExtra("android.nfc.extra.NDEF_MESSAGES"); // let rawmsgs = plus.android.invoke(intent, 'getParcelableArrayExtra', 'android.nfc.extra.NDEF_MESSAGES'); // let rawmsgs = intent.getParcelableArrayExtra(); if (rawmsgs != null && rawmsgs.length > 0) { // console.log('rawmsgs:"' + JSON.stringify(rawmsgs) + '"') let records = rawmsgs[0].getRecords(); // let records = plus.android.invoke(rawmsgs[0], 'getRecords'); let tnf = records[0].getTnf(); // let tnf = plus.android.invoke(records[0], 'getTnf'); // console.log('tnf = ' + JSON.stringify(tnf)) // console.log('TNF_WELL_KNOWN = ' + JSON.stringify(NdefRecord.TNF_WELL_KNOWN)) // console.log('TNF_ABSOLUTE_URI = ' + JSON.stringify(NdefRecord.TNF_ABSOLUTE_URI)) let recordType = records[0].getType(); // console.log('recordType = ' + JSON.stringify(recordType)) // console.log('RTD_URI = ' + JSON.stringify(NdefRecord.RTD_URI)) let result = records[0].getPayload(); let data = '' if (tnf.__UUID__ == NdefRecord.TNF_WELL_KNOWN.value) { console.log('tnf == TNF_WELL_KNOWN') if (recordType == NdefRecord.RTD_URI) { // URI based on payload // 在URI Record Payload中,第一个字节指明URI的ID码,对应 UriPrefixMap console.log('recordType == NdefRecord.RTD_URI') // console.log('result[0]:"' + result[0] + '"') let uriPrefix = UriPrefixMap[result[0]] console.log('uriPrefix:"' + uriPrefix + '"') result.shift() // 去除URI的ID码 data = plus.android.newObject("java.lang.String", result); data = uriPrefix + data } // } else if (tnf.__UUID__ == NdefRecord.TNF_ABSOLUTE_URI.value) { // console.log('tnf == TNF_ABSOLUTE_URI') } else { console.log('tnf:"' + tnf + '"') data = plus.android.newObject("java.lang.String", result); } // console.log('result:"' + result + '"') // console.log('NFC 数据:"' + data + '"') // toast('NFC 数据:' + data); // plus.runtime.openURL(data, function(res) { // console.log("打开浏览器路径失败!----", res); // }); // return data; readResult = { id: nfc_id, data: data }; } else { // toast('没有读取到数据'); readResult = { id: nfc_id, data: '' }; } console.log('NFC 数据:' + JSON.stringify(readResult)); uni.$emit('NfcRead', readResult) }, setPassword(intent) { try { toast('请勿移开标签 正在设置密码...'); let MifareUltralight = plus.android.importClass('android.nfc.tech.MifareUltralight'); let tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); let mfc = MifareUltralight.get(tag); if (mfc != null) { mfc.connect(); // let response = plus.android.invoke(mfc, 'transceive', [0x1B, pwdDefault[0], pwdDefault[1], pwdDefault[2], pwdDefault[3]]) // // let response = mfc.transceive([0x1B, pwdDefault[0], pwdDefault[1], pwdDefault[2], pwdDefault[3]]) // console.log("询问登录 response=" + JSON.stringify(response)); //pack置为默认 mfc.writePage(0x2C, [0x00, 0x00, 0x00, 0x00]) // set PWD: 设置密码为用户设置的密码 mfc.writePage(0x2B, pwdBytes) // 设置Auth0 auth0实际控制是否启用密码保护 设置为00表示从第0页开始提供保护 // let responseAuth0 = mfc.readPages(0x29) // console.log("responseAuth0=" + JSON.stringify(responseAuth0)); mfc.writePage(0x29, [0x04, 0x00, 0x00, 0x00]) mfc.close(); toast('设置密码成功!'); return; } else { toast('Tag不支持MifareUltralight'); return; } } catch (e) { toast('设置密码失败'); console.log("设置密码失败 error=" + e); } }, delPassword(intent) { try { toast('请勿移开标签 正在清除密码...'); let MifareUltralight = plus.android.importClass('android.nfc.tech.MifareUltralight'); let tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); let mfc = MifareUltralight.get(tag); // let mfc2 = plus.android.invoke(MifareUltralight, 'get', tag) // to do if (mfc != null) { mfc.connect(); //js不支持无符号整数,无法传输大于0X7F的值 // mfc.writePage(0x08, [0x01, 0x02, 0x03, 0x04]) // mfc.writePage(0x09, [0x7D, 0x7E, 0x7F, (0x80>>>0)]) // mfc.writePage(0x0A, [0x80>>>0, 0x81>>>0, 0xFE>>>0, 0xFF>>>0]) // return //用用户设置的密码询问登录 // let response = plus.android.invoke(mfc, 'transceive', [0x1B, pwdBytes[0], pwdBytes[1], pwdBytes[2], pwdBytes[3]]) let response = mfc.transceive([0x1B, pwdBytes[0], pwdBytes[1], pwdBytes[2], pwdBytes[3]]) console.log("询问登录 response=" + JSON.stringify(response)); if (response != null) { // if (response[0] == 0x00 && response[1] == 0x00) { if (response == '0,0') { console.log("密码校验正确"); } else { mfc.close(); console.log("密码校验失败"); toast('密码校验失败'); return } } else { mfc.close(); console.log("询问登录 response 无效"); toast('密码验证失败 或 未设置密码'); return } //pack置为默认 mfc.writePage(0x2C, [0x00, 0x00, 0x00, 0x00]) // set PWD: 设置密码为默认密码 mfc.writePage(0x2B, pwdDefault) // set AUTHLIM: //将AUTHLIM(第42页,字节0,位2-0)设置为失败的最大密码验证尝试次数 mfc.writePage(0x2A, [0x00, 0x05, 0x00, 0x00]) // 设置Auth0 auth0实际控制是否启用密码保护 设置为FF表示禁用密码保护 // let responseAuth0 = mfc.readPages(0x29) // console.log("responseAuth0=" + JSON.stringify(responseAuth0)); // mfc.writePage(0x29, [0x04, 0x00, 0x00, 0xFF]) //js不支持无符号整数,无法传输大于0X7F的值 mfc.writePage(0x29, [0x04, 0x00, 0x00, 0x7F]) mfc.close(); toast('清除密码成功!'); return; } else { toast('Tag不支持MifareUltralight'); return; } } catch (e) { toast('清除密码失败'); console.log("清除密码失败 error=" + e); } }, getState(intent) { try { toast('请勿移开标签 正在获取NFC状态...'); let MifareUltralight = plus.android.importClass('android.nfc.tech.MifareUltralight'); let tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); let mfc = MifareUltralight.get(tag); if (mfc != null) { mfc.connect(); let responseAuth0 = mfc.readPages(0x29) console.log("responseAuth0=" + JSON.stringify(responseAuth0)); if (responseAuth0[3] == 0x00) { toast('已设置密码保护'); } else if (responseAuth0[3] == 0x7F || responseAuth0[3] == 0xFF || responseAuth0[3] == -1) { toast('尚未设置密码保护'); } else { toast('NFC状态未知:' + JSON.stringify(responseAuth0)); } mfc.close(); return; } else { toast('Tag不支持MifareUltralight'); return; } } catch (e) { toast('获取NFC状态失败'); console.log("获取NFC状态失败 error=" + e); } }, byteArrayToHexString: function(inarray) { // converts byte arrays to string let i, j, inn; let hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"]; let out = ""; for (j = 0; j < inarray.length; ++j) { inn = inarray[j] & 0xff; i = (inn >>> 4) & 0x0f; out += hex[i]; i = inn & 0x0f; out += hex[i]; } return out; }, writeData: function() { if (noNFC) { toast('请检查设备是否支持并开启 NFC 功能!'); return; } // 监听事件,触发条件 readyWriteData = true; toast('请将NFC标签靠近!'); }, readData: function() { if (noNFC) { toast('请检查设备是否支持并开启 NFC 功能!'); return; } // 监听事件,触发条件 readyRead = true; toast('请将NFC标签靠近!'); }, setPwdData: function() { if (noNFC) { toast('请检查设备是否支持并开启 NFC 功能!');S return; } // 监听事件,触发条件 readySetPwd = true; toast('请将NFC标签靠近!'); }, delPwdData: function() { if (noNFC) { toast('请检查设备是否支持并开启 NFC 功能!'); return; } // 监听事件,触发条件 readyDelPwd = true; toast('请将NFC标签靠近!'); }, getNfcState: function() { if (noNFC) { toast('请检查设备是否支持并开启 NFC 功能!'); return; } // 监听事件,触发条件 readyGetNfcState = true; toast('请将NFC标签靠近!'); }, writeAndLock: function() { if (noNFC) { toast('请检查设备是否支持并开启 NFC 功能!'); return; } // 监听事件,触发条件 readyWriteAndLock = true; toast('请将NFC标签靠近!'); }, // 输入文本改变 inputChanage: function(res) { console.log("正在编辑写入数据...", res) writeUri = res } } function toast(content) { uni.showToast({ title: content, icon: 'none' }) }