读取芯片卡ID
/*
* desc:封装NFC功能,实现安卓设备对NFC标签读取卡号,支持android5.0及以上版本,仅支持 android 平台
*/
// 包路径
const package_NdefRecord = 'android.nfc.NdefRecord';
const package_NdefMessage = 'android.nfc.NdefMessage';
const package_TECH_DISCOVERED = 'android.nfc.action.TECH_DISCOVERED';
const package_Intent = 'android.content.Intent';
const package_Activity = 'android.app.Activity';
const package_PendingIntent = 'android.app.PendingIntent';
const package_IntentFilter = 'android.content.IntentFilter';
const package_NfcAdapter = 'android.nfc.NfcAdapter';
const package_Ndef = 'android.nfc.tech.Ndef';
const package_NdefFormatable = 'android.nfc.tech.NdefFormatable';
const package_Parcelable = 'android.os.Parcelable';
const package_String = 'java.lang.String';
let NfcAdapter;
let NdefRecord;
let NdefMessage;
let techListsArray = [
['android.nfc.tech.IsoDep'],
['android.nfc.tech.NfcA'],
['android.nfc.tech.NfcB'],
['android.nfc.tech.NfcF'],
['android.nfc.tech.Nfcf'],
['android.nfc.tech.NfcV'],
['android.nfc.tech.NdefFormatable'],
['android.nfc.tech.MifareClassi'],
['android.nfc.tech.MifareUltralight']
];
let readyRead = false;
export default {
nfcGetId: function(obj) {
let that = this;
try {
let main = plus.android.runtimeMainActivity();
let Intent = plus.android.importClass('android.content.Intent');
let Activity = plus.android.importClass('android.app.Activity');
let PendingIntent = plus.android.importClass('android.app.PendingIntent');
let IntentFilter = plus.android.importClass('android.content.IntentFilter');
NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');
let nfcAdapter = NfcAdapter.getDefaultAdapter(main);
if (nfcAdapter == null) {
uni.showToast({
title: '设备不支持NFC!',
icon: 'none'
})
return;
}
if (!nfcAdapter.isEnabled()) {
uni.showToast({
title: '请在系统设置中先启用NFC功能!',
icon: 'none'
});
return;
}
let intent = new Intent(main, main.getClass());
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
let pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);
let ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");
ndef.addDataType("*/*");
let intentFiltersArray = [ndef];
plus.globalEvent.addEventListener('newintent', function() {
console.log('newintent running');
// 监听 NFC
setTimeout(function() {
NdefRecord = plus.android.importClass("android.nfc.NdefRecord");
NdefMessage = plus.android.importClass("android.nfc.NdefMessage");
let main = plus.android.runtimeMainActivity();
let intent = main.getIntent();
//let that = this;
console.log("action type:" + intent.getAction());
if (package_TECH_DISCOVERED == intent.getAction()) {
if (readyRead) {
uni.showToast({
title: '请勿移开标签正在读取数据',
icon: 'none'
});
//let that = this;
// NFC id
let bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
let nfc_id = that.byteArrayToHexString(bytesId);
console.log('nfc_id:'+ nfc_id);
obj.success(nfc_id);
readyRead = false;
}
}
}, 1000);
});
plus.globalEvent.addEventListener('pause', function(e) {
console.log('pause running');
if (nfcAdapter) {
//关闭前台调度系统
//恢复默认状态
nfcAdapter.disableForegroundDispatch(main);
}
});
plus.globalEvent.addEventListener('resume', function(e) {
console.log('resume running');
if (nfcAdapter) {
//开启前台调度系统
nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
}
});
nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
// 监听事件,触发条件
readyRead = true;
uni.showToast({
title: '请将NFC标签靠近!',
icon: 'none'
});
} catch (e) {
console.error(e);
obj.fail(e);
} finally{
obj.complete();
}
},
byteArrayToHexString: function(inarray) {
let i, j, inn;
let hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
let 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;
},
}
先勾选权限
判断当前设备是否支持NFC以及是否打开了NFC功能
var main = plus.android.runtimeMainActivity();
var NfcAdapter = plus.android.importClass("android.nfc.NfcAdapter");
var _nfcAdapter = NfcAdapter.getDefaultAdapter(main);
console.log('NFC',_nfcAdapter)
if (_nfcAdapter == null) {
console.log("本手机不支持NFC")
} else if (_nfcAdapter.isEnabled() == false) {
console.log("NFC功能未打开")
} else {
console.log('okokokok')
}
页面使用
import nfc from "@/common/nfc.js" //nfc代码放js文件里
onLoad(){
nfc.Into()
},
onReady() {
console.log('onready')
let that = this
nfc.data.callback = function(data){
console.log('getId', data)
uni.$emit('refreshNFC', { refresh: true , data: data});
uni.navigateBack()
}
},
onShow(){
nfc.readData()
},
onHide() {
nfc.nfcclose()
},
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: 13, //0号扇区
initVal:'FFFFFFFFFFFF',
keyValA: '837210987622', //扇区密码
keyValB: '12BBADDAEA11',
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();
console.log(intent.getAction())
if (intent.getAction() == "android.nfc.action.TECH_DISCOVERED") {
// console.log('222222')
clearInterval(this.data.IntervalId);
// intent.setAction('android.intent.action.MAIN')
if (this.data.status === 'read') {
console.log('开始读取信息')
this._readData(intent);
} else {
// console.log('开始写入数据')
this._WriteData(intent);
}
}
},
// 16进制转10进制
hex2int:function(val) {
var len = val.length;
var callVal ="";
for (var i = 0; i < len; i++) {
callVal += val[i];
}
return parseInt(callVal,16);
},
// byte转16进制
Bytes2Str: function(arrBytes) {
var str = "";
for (var i = 0; i < arrBytes.length; i++) {
var tmp;
var num = arrBytes[i];
if (num < 0) {
//此处填坑,当byte因为符合位导致数值为负时候,需要对数据进行处理
tmp = (255 + num + 1).toString(16);
} else {
tmp = num.toString(16);
}
if (tmp.length == 1) {
tmp = "0" + tmp;
}
if (i > 0) {
str += ":" + tmp;
} else {
str += tmp;
}
}
return str;
},
//读取设备
_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 cmdBytesA = this.HexStringToByteArray(this.data.keyValA);
var cmdBytesB = this.HexStringToByteArray(this.data.keyValB);
var initBytes = this.HexStringToByteArray(this.data.initVal)
var auth = false;
if (invoke(mfc, "authenticateSectorWithKeyA", parseInt(this.data.sector), cmdBytesA)) {
console.log("aaaaaaaaaaaaaaaaaaaaaa")
console.log(invoke(mfc, "authenticateSectorWithKeyA", parseInt(this.data.sector), cmdBytesA))
auth = true;
// return;
} else if(invoke(mfc, "authenticateSectorWithKeyB", parseInt(this.data.sector), cmdBytesB)) {
console.log("bbbbbbbbbbbb")
auth = true;
// return;
}
// console.log(invoke(mfc, "authenticateSectorWithKeyA", parseInt(this.data.sector), cmdBytesA))
console.log(8888888888)
console.log(invoke(mfc, "authenticateSectorWithKey", parseInt(this.data.sector), initBytes))
if(
!invoke(mfc, "authenticateSectorWithKeyA", parseInt(this.data.sector), cmdBytesA) &&
!invoke(mfc, "authenticateSectorWithKeyB", parseInt(this.data.sector), cmdBytesB)){
uni.hideLoading();
uni.showModal({
content: "未发卡",
showCancel: false
});
return;
}
if (!auth) {
uni.hideLoading();
uni.showModal({
content: "请靠近一点",
showCancel: false
});
return;
}
console.log('666666')
console.log(auth)
var data = mfc.readBlock(52);
var str = this.Bytes2Str(data);
var arr = str.split(":");
var callValue = this.hex2int(arr.splice(0,5)); //车用截取 前4位 液化与工业 截取前5位
console.log("值:" + str)
this.data.callback(callValue);
mfc.close();
// this.nfcclose();
// uni.showModal({
// content: "扇区读取成功",
// showCancel: false
// });
} 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";
this.data.IntervalId = setInterval(()=>{
this.handle_nfc_data();
}, 1000);
},
}
export default Nfc