Implementar la funcionalidad de lectura de NFC en aplicaciones Uniapp para Android presenta desafíos únicos, pero abre posibilidades valiosas para escenarios como el control de acceso, la identificación de empleados y el seguimiento de logística. La clave reside en aprovechar la capacidad de invocación nativa de Uniapp para interactuar directamente con las APIs de NFC de Android.
Preparación fundamental del entorno
Antes de escribir una línea de código, es crucial validar dos aspectos: el hardware y la configuración.
En primer lugar, confirme que su dispositivo Android soporta NFC y que la tarjeta IC objetivo es del tipo Mifare Classic (M1). Una herramienta como "NFC Tools" puede verificar ambos. En segundo lugar, la aplicación debe solicitar explícitamente los permisos necesarios. Esto se configura en el archivo manifest.json dentro de la sección app-plus.
"app-plus": {
"distribute": {
"android": {
"permissions": [
"android.permission.NFC",
"android.permission.VIBRATE"
],
"features": [
"android.hardware.nfc"
]
}
}
}
Comprender el mecanismo de despacho en primer plano (Foreground Dispatch) de Android es esencial. Este sistema garantiza que su aplicación reciba los eventos de NFC cuando está en uso, evitando conflictos con otras aplicaciones compatibles. La lógica de la aplicación debe iniciar este despacho al enfocarse y desactivarlo al perder el enfoque.
Construcción de un módulo gestionador de NFC
Para mantener un código limpio y reutilizable, encapsule toda la lógica relacionada con el NFC en un módulo separado. El siguiente ejemplo muestra una clase que gestiona el ciclo de vida del adaptador NFC y el proceso de lectura.
// modules/nfc-handler.js
const { importClass } = plus.android;
const AndroidContext = importClass("android.content.Context");
const NfcAdapter = importClass("android.nfc.NfcAdapter");
const AndroidIntent = importClass("android.content.Intent");
const PendingIntent = importClass("android.app.PendingIntent");
const SUPPORTED_TECHS = [
["android.nfc.tech.NfcA"],
["android.nfc.tech.MifareClassic"]
];
export default class NfcHandler {
constructor(activity) {
this.activity = activity;
this.adapter = null;
this.isEnabled = false;
this.onTagDiscovered = null;
this.initAdapter();
}
initAdapter() {
const nfcManager = this.activity.getSystemService(AndroidContext.NFC_SERVICE);
this.adapter = NfcAdapter.getDefaultAdapter(this.activity);
if (!this.adapter) {
throw new Error("NFC adapter not available.");
}
}
enableForegroundDispatch() {
if (!this.isEnabled) {
const intent = new AndroidIntent(this.activity, this.activity.getClass());
intent.addFlags(AndroidIntent.FLAG_ACTIVITY_SINGLE_TOP);
const pendingIntent = PendingIntent.getActivity(
this.activity,
0,
intent,
PendingIntent.FLAG_MUTABLE
);
const filters = null;
this.adapter.enableForegroundDispatch(
this.activity,
pendingIntent,
filters,
SUPPORTED_TECHS
);
this.isEnabled = true;
}
}
disableForegroundDispatch() {
if (this.isEnabled) {
this.adapter.disableForegroundDispatch(this.activity);
this.isEnabled = false;
}
}
handleIntent(intent) {
const tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (tag && this.onTagDiscovered) {
const uid = this.bytesToHex(tag.getId());
this.onTagDiscovered(uid);
}
}
bytesToHex(bytes) {
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join(':').toUpperCase();
}
destroy() {
this.disableForegroundDispatch();
this.onTagDiscovered = null;
}
}
Integración en el ciclo de vida de la página Uniapp
La integración correcta con los ciclos de vida de la página es vital para un comportamiento fiable. Inicie el despacho en onShow y desactívelo en onHide o onUnload. Procese la intención del NFC en el evento de carga inicial o cuando la página recibe foco.
// pages/index.vue
import NfcHandler from '@/modules/nfc-handler.js';
export default {
data() {
return {
nfcManager: null,
cardUid: null,
statusMessage: ''
};
},
onShow() {
if (this.nfcManager) {
this.nfcManager.enableForegroundDispatch();
}
},
onHide() {
if (this.nfcManager) {
this.nfcManager.disableForegroundDispatch();
}
},
onUnload() {
if (this.nfcManager) {
this.nfcManager.destroy();
}
},
onLoad() {
try {
const mainActivity = plus.android.runtimeMainActivity();
this.nfcManager = new NfcHandler(mainActivity);
this.nfcManager.onTagDiscovered = (uid) => {
this.cardUid = uid;
this.statusMessage = `Tarjeta detectada: ${uid}`;
// Aquí puede añadir lógica adicional, como enviar el UID a su backend.
if (navigator.vibrate) {
navigator.vibrate(100);
}
};
this.nfcManager.enableForegroundDispatch();
} catch (error) {
this.statusMessage = `Error NFC: ${error.message}`;
}
},
onNewIntent(intent) {
if (this.nfcManager) {
this.nfcManager.handleIntent(intent);
}
}
}
Este enfoque proporciona una base robusta para aplicaciones que requieren lectura de tarjetas IC en el ecosistema Android mediante Uniapp, separando claramente las preocupaciones de hardware, lógica de negocio e interfaz de usuario.