1.先新建一個nfc.js文件。
let Context = plus.android.importClass("android.content.Context"); let NfcManager = plus.android.importClass("android.nfc.NfcManager"); let NfcAdapter = plus.android.importClass("android.nfc.NfcAdapter"); let Settings= plus.android.importClass("android.provider.Settings"); let Intent = plus.android.importClass("android.content.Intent"); let Parcelable = plus.android.importClass("android.os.Parcelable"); let PendingIntent = plus.android.importClass('android.app.PendingIntent'); let IntentFilter = plus.android.importClass('android.content.IntentFilter'); let NdefRecord = plus.android.importClass("android.nfc.NdefRecord"); let NdefMessage = plus.android.importClass("android.nfc.NdefMessage"); let Tag = plus.android.importClass("android.nfc.Tag"); let MifareClassic = plus.android.importClass("android.nfc.tech.MifareClassic"); let invoke = plus.android.invoke; const Nfc={ //所需要的數據 data:{ sector:0,//0號扇區 keyVal:'f1e2d3c4b5a6',//扇區密碼 status:'read',//當前操作方式:是讀卡 還是 寫卡 WriteData:'',//當status為write時生效。需要寫入的數字。長度不能超過32位。只能為數字 block:1,//當status為write時生效。需要寫入0號扇區的幾號塊 keyType:'A',//驗證方式 nfcAdapter:null, ICUID:'',//卡片ID main:null, intent:null, IntervalId:null, callback:null,//回調事件 techListsArray:[ ["android.nfc.tech.IsoDep"], ["android.nfc.tech.NfcA"], ["android.nfc.tech.NfcB"], ["android.nfc.tech.NfcF"], ["android.nfc.tech.NfcV"], ["android.nfc.tech.Ndef"], ["android.nfc.tech.NdefFormatable"], ["android.nfc.tech.MifareClassic"], ["android.nfc.tech.MifareUltralight"] ] }, //初始化 Into:function (){ this.data.main=plus.android.runtimeMainActivity(); var nfchManager = this.data.main.getSystemService(Context.NFC_SERVICE); var nfcAdapter = nfchManager.getDefaultAdapter(); if(!nfcAdapter.isEnabled()){ this.data.intent= new Intent(Settings.ACTION_NFC_SETTINGS); this.data.main.startActivity(this.data.intent); } var intent = new Intent(this.data.main, this.data.main.getClass()); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); var pendingIntent = PendingIntent.getActivity(this.data.main, 0, intent, 0); var ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED"); ndef.addDataType("*/*"); var intentFiltersArray = [ndef]; nfcAdapter.enableForegroundDispatch(this.data.main, pendingIntent, intentFiltersArray, this.data.techListsArray); this.data.nfcAdapter=nfcAdapter; }, //取消操作 nfcclose:function(){ if(this.data.nfcAdapter) this.data.nfcAdapter.disableForegroundDispatch(this.data.main); this.data.nfcAdapter=null; clearInterval(this.data.IntervalId); }, //輪詢獲取當前NFC設備觸發的事件 handle_nfc_data:function(){ console.log('輪訓中') var intent = this.data.main.getIntent(); if(intent.getAction()=="android.nfc.action.TECH_DISCOVERED"){ clearInterval(this.data.IntervalId); if(this.data.status==='read') { console.log('開始讀取信息') this._readData(intent); } else{ console.log('開始寫入數據') this._WriteData(intent); } } }, //讀取設備 _readData:function(intent){ setTimeout(function () { uni.hideLoading(); }, 2000); var tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); var techList = tag.getTechList(); var bisMfc=false; for(var i=0;i<techList.length;i++){ if(techList[i].indexOf('MifareClassic')>=0){ bisMfc=true; break; } } if(!bisMfc){ uni.hideLoading(); uni.showModal({ content: "卡片類型錯誤", showCancel: false }); return; } var mfc=MifareClassic.get(tag); if(!mfc){ uni.hideLoading(); uni.showModal({ content: "卡片獲取錯誤", showCancel: false }); return; } mfc.setTimeout(3000); if(!mfc.isConnected()){ try{ invoke(mfc,'connect'); }catch(e){ uni.hideLoading(); uni.showModal({ content: "卡片連接錯誤", showCancel: false }); return; } } try{ this.data.ICUID=this.ByteArrayToHexString(tag.getId()); var cmdBytes=this.HexStringToByteArray(this.data.keyVal); var auth=false; if(this.data.keyType=="A"){ auth=invoke(mfc,"authenticateSectorWithKeyA",parseInt(this.data.sector),cmdBytes); }else{ auth=invoke(mfc,"authenticateSectorWithKeyB",parseInt(this.data.sector),cmdBytes); } if(!auth){ uni.hideLoading(); uni.showModal({ content: "請靠近一點", showCancel: false }); return; } var arr=[] for (var i = 0; i < 4; i++) { var data = mfc.readBlock(i); console.log('當前'+i+"號塊:讀取的內容:"+data) arr.push(this.ByteArrayToHexString(data)) } mfc.close(); uni.showModal({ content: "扇區讀取成功", showCancel: false }); //this.nfcclose(); this.data.callback(arr) }catch(e){ console.error(e); }finally{ mfc.close(); } }, //寫入數據 _WriteData:function(intent){ uni.hideLoading(); uni.showLoading({ title: '正在寫入中.請勿移開' }); var tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); var techList = tag.getTechList(); var bisMfc=false; for(var i=0;i<techList.length;i++){ if(techList[i].indexOf('MifareClassic')>=0){ bisMfc=true; break; } } if(!bisMfc){ uni.hideLoading(); uni.showModal({ content: "卡片類型錯誤", showCancel: false }); return; } var mfc=MifareClassic.get(tag); if(!mfc){ uni.hideLoading(); uni.showModal({ content: "卡片獲取錯誤", showCancel: false }); return; } mfc.setTimeout(3000); if(!mfc.isConnected()){ try{ invoke(mfc,'connect'); }catch(e){ uni.hideLoading(); uni.showModal({ content: "卡片連接錯誤", showCancel: false }); return; } } try{ this.data.ICUID=this.ByteArrayToHexString(tag.getId()); console.log(this.data.keyVal) var cmdBytes=this.HexStringToByteArray(this.data.keyVal); var auth=false; if(this.data.keyType=="A"){ auth=invoke(mfc,"authenticateSectorWithKeyA",parseInt(this.data.sector),cmdBytes); }else{ auth=invoke(mfc,"authenticateSectorWithKeyB",parseInt(this.data.sector),cmdBytes); } if(!auth){ uni.hideLoading(); uni.showModal({ content: "請靠近一點", showCancel: false }); return; } //開始寫入指定塊 //mfc.writeBlock(this.data.block,this.HexStringToByteArray("11111111100000000000000000000000")); mfc.writeBlock(this.data.block,this.HexStringToByteArray(this.data.WriteData)); //驗證是否寫入成功 var data = mfc.readBlock(this.data.block); console.log(this.ByteArrayToHexString(data)) console.log(this.data.WriteData) if(this.ByteArrayToHexString(data)===this.data.WriteData) { uni.hideLoading(); mfc.close(); uni.showModal({ content: "寫入完成", showCancel: false }); this.data.callback({status:1,msg:'寫入成功'}) }else{ console.log('寫入失敗') this.data.callback({status:0,msg:'寫入失敗'}) } }catch(e){ console.error(e); }finally{ mfc.close(); } }, ByteArrayToHexString:function(inarray) { var i, j, inn; var hex = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F']; var 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; }, HexStringToByteArray:function(instr) { var hexA = new Array(); var pos = 0; var len = instr.length/2; for(var i=0; i<len; i++) { var s = instr.substr(pos, 2); var v = parseInt(s, 16); if(v>=128) v=v-256; hexA.push(v); pos += 2; } return hexA; }, //對外開放的讀取事件 readData:function(){ //輸入請靠近設備 uni.showLoading({ title: '請靠近設備' }); this.data.status="read" var that=this this.data.IntervalId = setInterval(function(){ that.handle_nfc_data(); },1000); }, //對外開放的寫入事件 //傳一個需要寫入的數據 writeData:function(value){ //輸入請靠近設備 this.data.status="write" uni.showLoading({ title: '請靠近設備' }); if(value.length>32) { uni.showModal({ content: "寫入數據長度不能超過32位", showCancel: false }); } for(var i=value.length;i<32;i++) { value+='0'; } console.log(value); console.log(value.length) this.data.WriteData=value var that=this this.data.IntervalId = setInterval(function(){ that.handle_nfc_data(); },1000); } } export default Nfc
2.調用Demo
<template> <view class="uni-common-mt"> <button type="primary" @click="readcard">讀卡操作</button> <view class="uni-form-item uni-column"> <view class="title">輸入需要寫入的內容</view> <input type="number" class="uni-input" v-model="value" placeholder="請輸入寫入的內容" /> </view> <button type="primary" @click="writecard">寫卡操作</button> <view> <text>{{arr}}</text> </view> </view> </template> <script> import nfc from '@/components/nfc/Nfc.js' export default { data() { return { value: '888999', arr:[] } }, onLoad: function() { console.log('當頁面啟動后') //初始化 nfc.Into(); }, methods: { update(e) { console(e) //e是子組件傳遞過來的值,就是子組件的index }, dataAction() { this.$refs.main.childMethod() //這是頁面觸發子組件的方法 //main是組件的ref }, readcard: function() { console.log('調用讀卡功能') var that=this nfc.readData(); nfc.data.callback = function(e) { console.log(e) that.arr=e; } }, writecard: function() { console.log('調用寫卡功能') nfc.writeData(this.value); nfc.data.callback = function(e) { console.log(e) } } } } </script> <style> </style>