uniapp 记录一下NFC 安卓35targetSDK 打包之后识别无效

74 阅读2分钟
const package_NfcAdapter = 'android.nfc.NfcAdapter';
import { useBluetoothStore } from '@/store/bluetooth'


let NfcAdapter;
let NdefRecord;
let NdefMessage;
let readyWriteData = false;
let readyRead = false;
let noNFC = false;
let techListsArray = [
	['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']
];

let text = '{id:123,name:nfc,site:cssmini.com}';
let readResult = '';

export default {
	listenNFCStatus() {
		try {
			let main = plus.android.runtimeMainActivity();
			let Intent = plus.android.importClass('android.content.Intent');
			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) {
				toast('Device does not support NFC');
				noNFC = true;
				return;
			}

			if (!nfcAdapter.isEnabled()) {
				toast('Please enable NFC in system settings');
				noNFC = true;
				return;
			} else {
				noNFC = false;
			}

			let intent = new Intent(main, main.getClass());
			intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

			let pendingIntent = PendingIntent.getActivity(main, 0, intent, PendingIntent.FLAG_MUTABLE);
//PendingIntent.FLAG_MUTABLE主要是这个  原博主写的是直接写死0但是安卓12+不能再这样写了,这个表示为可改变PendingIntent.FLAG_IMMUTABLE不可改变
			let techFilter = new IntentFilter("android.nfc.action.TECH_DISCOVERED");
			let ndefFilter = new IntentFilter("android.nfc.action.NDEF_DISCOVERED");
			techFilter.addDataType("*/*");
			ndefFilter.addDataType("*/*");
			let intentFiltersArray = [techFilter, ndefFilter];

			plus.globalEvent.addEventListener('newintent', () => {
				console.log('[NFC] newintent received');
				setTimeout(() => {
					this.nfcRuning();
				}, 1000);
			});

			plus.globalEvent.addEventListener('pause', () => {
				console.log('[NFC] app paused, disable foreground dispatch');
				if (nfcAdapter) nfcAdapter.disableForegroundDispatch(main);
			});

			plus.globalEvent.addEventListener('resume', () => {
				console.log('[NFC] app resumed, enable foreground dispatch');
				if (nfcAdapter) {
					nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
				}
			});

			nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
		} catch (e) {
			console.error('[NFC] 初始化异常:', e);
		}
	},


	nfcRuning() {
		try {
			NdefRecord = plus.android.importClass("android.nfc.NdefRecord");
			NdefMessage = plus.android.importClass("android.nfc.NdefMessage");

			const main = plus.android.runtimeMainActivity();
			const intent = main.getIntent();
			const action = intent.getAction();

			console.log('[NFC] Action:', action);

			if (
				action === "android.nfc.action.TECH_DISCOVERED" ||
				action === "android.nfc.action.NDEF_DISCOVERED"
			) {
				if (readyWriteData) {
					this.write(intent);
					readyWriteData = false;
				} else if (readyRead) {
					this.read(intent);
					readyRead = false;
				}
			}
		} catch (e) {
			console.error('[NFC] nfcRuning异常:', e);
		}
	},

	write(intent) {
		try {
			toast('请勿移开标签,正在写入...');
			console.log('[NFC] 准备写入:', text);

			const textBytes = plus.android.invoke(text, "getBytes");
			const textRecord = new NdefRecord(
				NdefRecord.TNF_MIME_MEDIA,
				plus.android.invoke("text/plain", "getBytes"),
				plus.android.invoke("", "getBytes"),
				textBytes
			);

			const message = new NdefMessage([textRecord]);
			const Ndef = plus.android.importClass('android.nfc.tech.Ndef');
			const NdefFormatable = plus.android.importClass('android.nfc.tech.NdefFormatable');

			const tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
			const ndef = Ndef.get(tag);

			if (ndef) {
				const size = message.toByteArray().length;
				ndef.connect();
				if (!ndef.isWritable()) {
					toast('标签不可写');
					return;
				}
				if (ndef.getMaxSize() < size) {
					toast('数据超过容量');
					return;
				}
				ndef.writeNdefMessage(message);
				toast('写入成功');
			} else {
				const format = NdefFormatable.get(tag);
				if (format) {
					format.connect();
					format.format(message);
					toast('格式化并写入成功');
				} else {
					toast('不支持NDEF格式');
				}
			}
		} catch (e) {
			console.error('[NFC] 写入失败:', e);
			toast('写入失败');
		}
	},

	read(intent) {
		const bluetoothStore = useBluetoothStore()
		try {

			const NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');
			const Parcelable = plus.android.importClass("android.os.Parcelable");

			const bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
			const nfc_id = this.byteArrayToHexString(bytesId);

			console.log('[NFC] 标签ID:', typeof (nfc_id), nfc_id);
			bluetoothStore.NfcId = nfc_id;
			console.log('[NFC] Pinia标签ID:', bluetoothStore.NfcId);
			const rawmsgs = intent.getParcelableArrayExtra("android.nfc.extra.NDEF_MESSAGES");

			if (rawmsgs && rawmsgs.length > 0) {
				const records = rawmsgs[0].getRecords();
				const result = records[0].getPayload();
				const data = plus.android.newObject("java.lang.String", result);
				const jsData = data + ""; // 转成 JS 字符串
				console.log('[NFC] 标签数据:', jsData);

				const match = jsData.match(/[?&]chk=([^&]+)/);
				const chk = match ? match[1] : null;
				console.log('[NFC] 提取到 chk:', chk);


			} else {
				console.warn('[NFC] 标签没有 NDEF 数据');
				// toast('没有读取到数据');
			}
		} catch (e) {
			console.error('[NFC] 读取失败:', e);
			toast('Reading failed');
		}
	},

	byteArrayToHexString(inarray) {
		let out = "";
		for (let j = 0; j < inarray.length; ++j) {
			const v = inarray[j] & 0xff;
			out += (v < 16 ? "0" : "") + v.toString(16).toUpperCase();
		}
		return out;
	},

	writeData() {
		if (noNFC) {
			// toast('Please check whether the device supports and enables the NFC function');
			return;
		}
		readyWriteData = true;
		toast('Please bring the NFC tag close');
	},

	readData() {
		if (noNFC) {
			// toast('Please check whether the device supports and enables the NFC function');
			return;
		}
		readyRead = true;
		toast('Please bring the NFC tag close');
	}
};

function toast(content) {
	uni.showToast({
		title: content,
		icon: 'none',
		duration: 2000
	});
}