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>

  

posted @ 2021-07-26 10:00  王彬-效率开发  阅读(1988)  评论(1编辑  收藏  举报