uni-app调用NFC读写加密扇区功能。
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>