艳阳照 發表於 2021-7-26 10:00:00

uni-app调用NFC读写加密扇区功能。

<p>1.先新建一个nfc.js文件。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">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 = ;
      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</span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">techList</span><span style="color: rgba(255, 0, 0, 1)">.length;i++){
            if(techList.indexOf('MifareClassic')</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">=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 </span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)"> 4</span><span style="color: rgba(255, 0, 0, 1)">; i++) {
                var data </span><span style="color: rgba(0, 0, 255, 1)">= mfc.readBlock(i);
                </span><span style="color: rgba(255, 0, 0, 1)">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 </span><span style="color: rgba(0, 0, 255, 1)">= intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
      </span><span style="color: rgba(255, 0, 0, 1)">var techList </span><span style="color: rgba(0, 0, 255, 1)">= tag.getTechList();
      </span><span style="color: rgba(255, 0, 0, 1)">var bisMfc</span><span style="color: rgba(0, 0, 255, 1)">=false;
      </span><span style="color: rgba(255, 0, 0, 1)">for(var i</span><span style="color: rgba(0, 0, 255, 1)">=0;i&lt;techList.length;i++){
            </span><span style="color: rgba(255, 0, 0, 1)">if(techList.indexOf('MifareClassic')</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">=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</span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">inarray</span><span style="color: rgba(255, 0, 0, 1)">.length; ++j) {
            inn </span><span style="color: rgba(0, 0, 255, 1)">= inarray </span><span style="color: rgba(255, 0, 0, 1)">&amp; 0xff;
            i </span><span style="color: rgba(0, 0, 255, 1)">= (inn </span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">&gt;&gt; 4) &amp; 0x0f;
            out += hex;
            i = inn &amp; 0x0f;
            out += hex;
      }
      return out;
    },
    HexStringToByteArray:function(instr) {
      var hexA = new Array();
      var pos = 0;
      var len = instr.length/2;
      for(var i=0; i</span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">len</span><span style="color: rgba(255, 0, 0, 1)">; i++)
      {
            var s </span><span style="color: rgba(0, 0, 255, 1)">= instr.substr(pos, </span><span style="color: rgba(255, 0, 0, 1)">2);
            var v </span><span style="color: rgba(0, 0, 255, 1)">= parseInt(s, </span><span style="color: rgba(255, 0, 0, 1)">16);
            if(v</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">=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&gt;32)
      {
            uni.showModal({
                content: "写入数据长度不能超过32位",
                showCancel: false
            });
      }
      for(var i=value.length;i</span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">32</span><span style="color: rgba(255, 0, 0, 1)">;i++)
      {
            value+</span><span style="color: rgba(0, 0, 255, 1)">='0';
      </span><span style="color: rgba(255, 0, 0, 1)">}
      console.log(value);
      console.log(value.length)
      
      this.data.WriteData</span><span style="color: rgba(0, 0, 255, 1)">=value
      </span><span style="color: rgba(255, 0, 0, 1)">var that</span><span style="color: rgba(0, 0, 255, 1)">=this
      </span><span style="color: rgba(255, 0, 0, 1)">this.data.IntervalId </span><span style="color: rgba(0, 0, 255, 1)">= setInterval(function(){
            </span><span style="color: rgba(255, 0, 0, 1)">that.handle_nfc_data();
      },1000);
    }
}

export default Nfc</span></pre>
</div>
<p>2.调用Demo</p>
<div class="cnblogs_Highlighter">
<pre class="brush:html;gutter:true;">&lt;template&gt;
        &lt;view class="uni-common-mt"&gt;
                &lt;button type="primary" @click="readcard"&gt;读卡操作&lt;/button&gt;


                &lt;view class="uni-form-item uni-column"&gt;
                        &lt;view class="title"&gt;输入需要写入的内容&lt;/view&gt;
                        &lt;input type="number" class="uni-input" v-model="value" placeholder="请输入写入的内容" /&gt;
                &lt;/view&gt;

                &lt;button type="primary" @click="writecard"&gt;写卡操作&lt;/button&gt;

                &lt;view&gt;
                        &lt;text&gt;{{arr}}&lt;/text&gt;
                &lt;/view&gt;
        &lt;/view&gt;
&lt;/template&gt;

&lt;script&gt;
        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)
                                }
                        }
                }
        }
&lt;/script&gt;

&lt;style&gt;
&lt;/style&gt;
</pre>
</div>
<p>  </p><br><br>
来源:https://www.cnblogs.com/wangbin0582/p/15060173.html
頁: [1]
查看完整版本: uni-app调用NFC读写加密扇区功能。