UNPKG

unfc

Version:

A framework-agnostic NFC package for reading/writing NFC tags in web apps and PWAs

182 lines (181 loc) 6.54 kB
/** * NFC implementation that communicates with a native Android app via a bridge * This provides better integration with Capacitor Android projects */ export class AndroidBridgeNfc { constructor() { this.listeners = {}; this.isBridgeAvailable = false; // Look for the bridge in the global scope // The native app needs to inject this object this.bridge = window.nativeAndroidNfcBridge || {}; this.isBridgeAvailable = !!(this.bridge.isNfcEnabled && this.bridge.startNfcScan); // Set up message listener for tag detection events from native app if (this.isBridgeAvailable) { window.addEventListener("message", this.handleNativeMessage.bind(this)); console.log("Android NFC bridge initialized"); } else { console.warn("Android NFC bridge not found"); } } handleNativeMessage(event) { if (!event.data || typeof event.data !== "object") return; // Handle tag detected message from native app if (event.data.type === "nfcTagDetected" && event.data.tag) { const tagListeners = this.listeners["tagDetected"] || []; const tag = event.data.tag; for (const listener of tagListeners) { listener(tag); } } // Handle NFC status change from native app if (event.data.type === "nfcStatusChanged" && event.data.enabled !== undefined) { const statusListeners = this.listeners["nfcStatusChanged"] || []; for (const listener of statusListeners) { listener({ enabled: !!event.data.enabled }); } } } async isEnabled() { if (!this.isBridgeAvailable) { return { enabled: false }; } try { const enabled = await this.bridge.isNfcEnabled(); return { enabled }; } catch (error) { console.error("Error checking NFC status through bridge:", error); return { enabled: false }; } } async openSettings() { if (!this.isBridgeAvailable || !this.bridge.openNfcSettings) { throw new Error("NFC settings cannot be opened - bridge not available"); } try { await this.bridge.openNfcSettings(); } catch (error) { console.error("Error opening NFC settings through bridge:", error); throw error; } } async startScanSession(options) { if (!this.isBridgeAvailable) { throw new Error("NFC scan cannot be started - bridge not available"); } try { await this.bridge.startNfcScan(JSON.stringify(options || {})); } catch (error) { console.error("Error starting NFC scan through bridge:", error); throw error; } } async stopScanSession() { if (!this.isBridgeAvailable || !this.bridge.stopNfcScan) { return; // Just silently return if bridge not available } try { await this.bridge.stopNfcScan(); } catch (error) { console.error("Error stopping NFC scan through bridge:", error); } } async write(options) { if (!this.isBridgeAvailable || !this.bridge.writeNfcTag) { throw new Error("NFC write is not supported - bridge not available"); } try { await this.bridge.writeNfcTag(JSON.stringify(options)); } catch (error) { console.error("Error writing NFC tag through bridge:", error); throw error; } } async makeReadOnly() { if (!this.isBridgeAvailable || !this.bridge.makeNfcTagReadOnly) { throw new Error("makeReadOnly is not implemented in the Android bridge"); } try { await this.bridge.makeNfcTagReadOnly(); } catch (error) { console.error("Error making NFC tag read-only through bridge:", error); throw error; } } async format() { if (!this.isBridgeAvailable || !this.bridge.formatNfcTag) { throw new Error("format is not implemented in the Android bridge"); } try { await this.bridge.formatNfcTag(); } catch (error) { console.error("Error formatting NFC tag through bridge:", error); throw error; } } async erase() { if (!this.isBridgeAvailable || !this.bridge.eraseNfcTag) { throw new Error("erase is not implemented in the Android bridge"); } try { await this.bridge.eraseNfcTag(); } catch (error) { console.error("Error erasing NFC tag through bridge:", error); throw error; } } async share(options) { if (!this.isBridgeAvailable || !this.bridge.shareNfcData) { throw new Error("share is not implemented in the Android bridge"); } try { await this.bridge.shareNfcData(JSON.stringify(options)); } catch (error) { console.error("Error sharing NFC data through bridge:", error); throw error; } } async stopSharing() { if (!this.isBridgeAvailable || !this.bridge.stopNfcSharing) { throw new Error("stopSharing is not implemented in the Android bridge"); } try { await this.bridge.stopNfcSharing(); } catch (error) { console.error("Error stopping NFC sharing through bridge:", error); throw error; } } async addListener(eventName, listenerFunc) { if (!this.listeners[eventName]) { this.listeners[eventName] = []; } this.listeners[eventName].push(listenerFunc); return { remove: async () => { this.removeListener(eventName, listenerFunc); }, }; } removeListener(eventName, listenerFunc) { if (this.listeners[eventName]) { this.listeners[eventName] = this.listeners[eventName].filter((listener) => listener !== listenerFunc); } } async removeAllListeners() { this.listeners = {}; } }