uniapp安卓端调用nfc获取设备的文本

43 阅读3分钟
import { initNFC, startRead, closeNFC } from '@/utils/nfc.js';
 
const prepareSeal = async (seal, position) => {
    // 调用拍照, 拍照失败, 直接返回
    const photoUrl = await takePhoto()
    if (!photoUrl) return
 
    initNFC(async (e) => {
        if (!e.uid || !e.text) {
            toast.error('NFC 读取失败')
            return
        }
 
        try {
            const data = {
                transportOrderId: info.value.transportOrderId,
                vehicleNumber: info.value.selfPickupVehicle,
                unsealImage: photoUrl,
                chipUid: e.uid.replace(/:/g, '').toUpperCase(),
                encryptedDataHash: e.text,
                unsealPosition: `${position}号口`,
                userId: uni.getStorageSync('userInfo').userId,
            }
            const res = await getNfcUnlockApi(data)
            if (res.code === 200) {
                await refresh()
                toast.success('解封成功')
            } else {
                toast.error( res.msg || '解封失败')
            }
        } catch (error) {
            console.log(error)
        } finally {
            closeNFC()
        }
    })
 
    startRead();
}
 
 
onUnmounted(() => {
    closeNFC()
})



 
// 全局变量(与你原代码保持一致)
let NfcAdapter = null;
let NdefRecord = null;
let NdefMessage = null;
let nfcAdapter = null;
let mainActivity = null;
let waiting = null;
let readyRead = false; // 仅保留读取状态
let readCallback = null; // 读取结果回调
 
/**
 * 初始化NFC监听
 * @param {Function} cb - 读取结果回调函数
 */
export function initNFC(cb) {
    if (uni.getSystemInfoSync().platform !== 'android') {
        plus.nativeUI.toast('仅支持安卓设备');
        return;
    }
    readCallback = cb; // 保存回调
 
    try {
        // 获取UniApp主Activity(App端关键)
        mainActivity = plus.android.runtimeMainActivity();
        const Intent = plus.android.importClass('android.content.Intent');
        const PendingIntent = plus.android.importClass('android.app.PendingIntent');
        const IntentFilter = plus.android.importClass('android.content.IntentFilter');
        NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');
 
        // 初始化NFC适配器
        nfcAdapter = NfcAdapter.getDefaultAdapter(mainActivity);
        if (!nfcAdapter) {
            plus.nativeUI.toast('设备不支持NFC');
            return;
        }
        if (!nfcAdapter.isEnabled()) {
            plus.nativeUI.toast('请在系统设置中开启NFC');
            return;
        }
 
        // 配置Intent
        const intent = new Intent(mainActivity, mainActivity.getClass());
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
 
        const pendingIntent = PendingIntent.getActivity(mainActivity, 0, intent, PendingIntent.FLAG_MUTABLE);
 
 
        // 配置过滤器
        const ndefFilter = new IntentFilter("android.nfc.action.TECH_DISCOVERED");
        ndefFilter.addDataType("*/*");
        const intentFiltersArray = [ndefFilter];
 
        // 支持的NFC技术类型
        const 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"]
        ];
 
        // 移除旧的事件监听,避免重复注册
        plus.globalEvent.removeEventListener("newintent", handleNfcData);
        // 注册新的事件监听
        plus.globalEvent.addEventListener("newintent", handleNfcData, false);
 
        // 页面生命周期
        plus.globalEvent.addEventListener("pause", function () {
            if (nfcAdapter) {
                nfcAdapter.disableForegroundDispatch(mainActivity);
                console.log('pause: 关闭NFC前台调度');
            }
        }, false);
 
        plus.globalEvent.addEventListener("resume", function () {
            if (nfcAdapter) {
                nfcAdapter.enableForegroundDispatch(mainActivity, pendingIntent, intentFiltersArray, techListsArray);
                console.log('resume: 重启NFC前台调度');
            }
        }, false);
 
        // 初始启用前台调度
        nfcAdapter.enableForegroundDispatch(mainActivity, pendingIntent, intentFiltersArray, techListsArray);
        console.log('NFC初始化完成,等待标签');
 
    } catch (e) {
        console.error('NFC初始化失败:', e);
        plus.nativeUI.toast('NFC初始化失败');
    }
}
 
/**
 * 处理NFC数据
 */
function handleNfcData() {
    if (!readyRead || !readCallback) return;
 
    try {
        NdefRecord = plus.android.importClass("android.nfc.NdefRecord");
        NdefMessage = plus.android.importClass("android.nfc.NdefMessage");
        const intent = mainActivity.getIntent();
 
        console.log("action type:" + intent.getAction());
        if ("android.nfc.action.TECH_DISCOVERED" === intent.getAction()) {
            __read(intent); // 只执行读取逻辑
        }
    } catch (e) {
        console.error('处理NFC数据失败:', e);
        plus.nativeUI.toast('读取失败');
        if (waiting) waiting.close();
        readyRead = false;
        readCallback({ error: '处理数据失败: ' + e.message });
        // 出错时也关闭NFC
        closeNFC();
    }
}
 
/**
 * 读取NFC内容(增加UID获取)
 */
function __read(intent) {
    waiting.setTitle('请勿移开标签\n正在读取数据...');
    try {
        // 获取标签对象,用于读取UID
        const tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        plus.android.importClass(tag); // 绑定原生方法
 
        // 获取并转换UID
        let uid = '';
        if (tag && tag.getId) {
            const uidBytes = tag.getId();
            uid = bytesToHex(uidBytes);
        }
 
        // 读取NDEF内容
        const Parcelable = plus.android.importClass("android.os.Parcelable");
        const rawmsgs = intent.getParcelableArrayExtra("android.nfc.extra.NDEF_MESSAGES");
 
        if (!rawmsgs || rawmsgs.length === 0) {
            plus.nativeUI.toast('未检测到NDEF数据');
            // 即使没有文本数据,也返回UID
            readCallback({ uid, error: '未检测到NDEF数据' });
            waiting.close();
            readyRead = false;
            closeNFC(); // 读取完成后关闭
            return;
        }
 
        const records = rawmsgs[0].getRecords();
        if (!records || records.length === 0) {
            plus.nativeUI.toast('未找到NDEF记录');
            readCallback({ uid, error: '未找到NDEF记录' });
            waiting.close();
            readyRead = false;
            closeNFC(); // 读取完成后关闭
            return;
        }
 
        const result = records[0].getPayload();
        const text = plus.android.newObject("java.lang.String", result);
 
        // 读取成功,返回UID和文本
        readCallback({ uid, text });
        plus.nativeUI.toast('读取成功');
 
    } catch (e) {
        console.error('读取NFC失败:', e);
        plus.nativeUI.toast('读取失败');
        readCallback({ error: '读取失败: ' + e.message });
    } finally {
        waiting.close();
        readyRead = false;
        closeNFC(); // 最终确保关闭NFC
    }
}
 
/**
 * 字节数组转16进制字符串(用于UID转换)
 */
function bytesToHex(bytes) {
    if (!bytes) return '';
    const hexChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
    let hex = '';
    for (let i = 0; i < bytes.length; i++) {
        const value = bytes[i] & 0xFF;
        hex += hexChars[value >> 4] + hexChars[value & 0x0F];
        if (i < bytes.length - 1) hex += ':';
    }
    return hex;
}
 
/**
 * 开始读取
 */
export function startRead() {
    if (!nfcAdapter) {
        plus.nativeUI.toast('请先初始化NFC');
        return;
    }
    readyRead = true;
    waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");
}
 
/**
 * 关闭NFC(清理资源)
 */
export function closeNFC() {
    if (nfcAdapter && mainActivity) {
        nfcAdapter.disableForegroundDispatch(mainActivity);
        plus.globalEvent.removeEventListener("newintent", handleNfcData);
    }
    if (waiting) waiting.close();
    readyRead = false;
    // 不清除回调,以便接收最后一次结果
    console.log('NFC已关闭');
}
 
// UniApp plusready后自动初始化(可选)
plus.globalEvent.addEventListener('plusready', function () {
    console.log('plusready: NFC模块准备就绪');
}, false);