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>

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM