added ios support

This commit is contained in:
mohamad 2025-03-04 21:32:53 +01:00
parent 0ff7c427e0
commit 37fc6f8b57
5 changed files with 566 additions and 84 deletions

273
README.md
View File

@ -1,6 +1,6 @@
# Universal NFC # Universal NFC
A framework-agnostic NFC package for reading and writing NFC tags in web applications and Progressive Web Apps (PWAs). This library provides a consistent API for working with NFC across different environments, with a focus on ease of use and developer experience. A framework-agnostic NFC package for reading and writing NFC tags in web applications and Progressive Web Apps (PWAs), with iOS support options. This library provides a consistent API for working with NFC across different environments, with a focus on ease of use and developer experience.
[![npm version](https://img.shields.io/npm/v/universal-nfc.svg)](https://www.npmjs.com/package/universal-nfc) [![npm version](https://img.shields.io/npm/v/universal-nfc.svg)](https://www.npmjs.com/package/universal-nfc)
[![license](https://img.shields.io/npm/l/universal-nfc.svg)](https://github.com/yourusername/universal-nfc/blob/main/LICENSE) [![license](https://img.shields.io/npm/l/universal-nfc.svg)](https://github.com/yourusername/universal-nfc/blob/main/LICENSE)
@ -14,6 +14,7 @@ A framework-agnostic NFC package for reading and writing NFC tags in web applica
- 📊 TypeScript support with comprehensive type definitions - 📊 TypeScript support with comprehensive type definitions
- 🔄 Simple and advanced APIs for different use cases - 🔄 Simple and advanced APIs for different use cases
- 🔌 Based on the Web NFC API standard - 🔌 Based on the Web NFC API standard
- 🍎 iOS support via native bridge integration
## Installation ## Installation
@ -29,10 +30,15 @@ yarn add universal-nfc
## Platform Compatibility ## Platform Compatibility
| Feature | Chrome for Android (89+) | Chrome for Desktop | Safari iOS | Firefox | Edge | | Feature | Chrome for Android (89+) | Chrome for Desktop | Safari iOS | Native iOS Apps | Native Android Apps | Firefox | Edge |
| ----------- | ------------------------ | ------------------ | ---------- | ------- | ---- | |--------------|------------------------|------------------|-----------|----------------|----------------|---------|------|
| Reading NFC | ✅ | ❌ | ❌ | ❌ | ❌ | | Reading NFC | ✅ | ❌ | ❌ | ✅* | ✅ | ❌ | ❌ |
| Writing NFC | ✅ | ❌ | ❌ | ❌ | ❌ | | Writing NFC | ✅ | ❌ | ❌ | ✅* | ✅ | ❌ | ❌ |
\*iOS support requires a native app with an embedded WebView and bridge implementation.
**Requirements for Web NFC:** **Requirements for Web NFC:**
@ -41,6 +47,15 @@ yarn add universal-nfc
- Device with NFC hardware - Device with NFC hardware
- NFC enabled in device settings - NFC enabled in device settings
**Requirements for iOS NFC:**
- iOS 11+ device with NFC hardware
- Native iOS app with NFC entitlements
- Core NFC framework integration
- Custom bridge implementation (see iOS Integration section)
## Basic Usage ## Basic Usage
### Reading NFC Tags (Simple API) ### Reading NFC Tags (Simple API)
@ -48,47 +63,45 @@ yarn add universal-nfc
The simplest way to read NFC tags: The simplest way to read NFC tags:
```javascript ```javascript
import { SimpleNfc } from "universal-nfc"; import { SimpleNfc } from 'universal-nfc';
const nfcReader = new SimpleNfc(); const nfcReader = new SimpleNfc();
async function startReading() { async function startReading() {
// First check if NFC is available // First check if NFC is available
const available = await nfcReader.isAvailable(); const available = await nfcReader.isAvailable();
if (!available) { if (!available) {
console.log("NFC is not available on this device/browser"); console.log('NFC is not available on this device/browser');
return; return;
} }
try { try {
// Start reading NFC tags with a callback // Start reading NFC tags with a callback
await nfcReader.startReading((content, type) => { await nfcReader.startReading((content, type) => {
console.log(`Read ${type} content:`, content); console.log(`Read ${type} content:`, content);
// 'type' will be 'text', 'url', or 'other' // 'type' will be 'text', 'url', or 'other'
if (type === "url") { if (type === 'url') {
// Handle URL // Handle URL
window.open(content, "_blank"); window.open(content, '_blank');
} else { } else {
// Handle text or other content // Handle text or other content
document.getElementById("result").textContent = content; document.getElementById('result').textContent = content;
} }
}); });
console.log("Scan started - tap an NFC tag"); console.log('Scan started - tap an NFC tag');
} catch (error) { } catch (error) {
console.error("Error starting NFC scan:", error); console.error('Error starting NFC scan:', error);
} }
} }
function stopReading() { function stopReading() {
nfcReader.stopReading(); nfcReader.stopReading();
console.log("NFC reading stopped"); console.log('NFC reading stopped');
} }
// Call startReading() when your app is ready to scan
// Call stopReading() when you want to stop scanning
``` ```
### Writing to NFC Tags ### Writing to NFC Tags
@ -117,6 +130,196 @@ async function writeUrlToTag() {
} }
``` ```
## iOS Integration
### Overview
iOS devices with NFC hardware (iPhone 7 and later running iOS 11+) support reading NFC tags, but with some important restrictions:
- **Safari browser cannot directly access NFC**: The Web NFC API is not supported in Safari.
- **Native app required**: NFC on iOS requires a native app built with the Core NFC framework.
- **Web apps can access NFC through a bridge**: Web content running in a WebView inside a native app can access NFC via a custom bridge.
### iOS Native Bridge Setup
To use Universal NFC with iOS, you need to:
1. Create a native iOS app with WebView.
2. Implement Core NFC.
3. Create a JavaScript bridge.
#### 1. Native iOS App with NFC Capabilities
First, ensure your app has NFC entitlements:
- Add the NFC entitlement to your app in Xcode.
- Add `NFCReaderUsageDescription` in `Info.plist`.
- Enable the "Near Field Communication Tag Reading" capability.
#### 2. Implement the NFC Bridge in Swift
```swift
import WebKit
import CoreNFC
class NfcBridge: NSObject, NFCNDEFReaderSessionDelegate {
weak var webView: WKWebView?
var nfcSession: NFCNDEFReaderSession?
init(webView: WKWebView) {
self.webView = webView
super.init()
// Register JavaScript interface
let bridgeScript = WKUserScript(
source: "window.nativeNfcBridge = {
isNfcEnabled: function() { return window.webkit.messageHandlers.nfcBridge.postMessage({action: 'isEnabled'}); },
startNfcScan: function(options) { return window.webkit.messageHandlers.nfcBridge.postMessage({action: 'startScan', options: options}); },
stopNfcScan: function() { return window.webkit.messageHandlers.nfcBridge.postMessage({action: 'stopScan'}); },
writeNfcTag: function(data) { return window.webkit.messageHandlers.nfcBridge.postMessage({action: 'writeTag', data: data}); },
openSettings: function() { return window.webkit.messageHandlers.nfcBridge.postMessage({action: 'openSettings'}); }
};",
injectionTime: .atDocumentStart,
forMainFrameOnly: false
)
let contentController = webView.configuration.userContentController
contentController.addUserScript(bridgeScript)
contentController.add(self, name: "nfcBridge")
}
// Handle JavaScript messages
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard let body = message.body as? [String: Any],
let action = body["action"] as? String else {
return
}
switch action {
case "isEnabled":
checkNfcAvailability()
case "startScan":
let options = body["options"] as? String ?? "{}"
startNfcSession(options: options)
case "stopScan":
stopNfcSession()
case "writeTag":
if let data = body["data"] as? String {
writeNfcTag(data: data)
}
case "openSettings":
openSettings()
default:
break
}
}
private func checkNfcAvailability() {
let isAvailable = NFCNDEFReaderSession.readingAvailable
sendToWebView(script: "window.dispatchEvent(new MessageEvent('message', {data: {type: 'nfcStatusChanged', enabled: \(isAvailable)}}));")
}
private func startNfcSession(options: String) {
guard NFCNDEFReaderSession.readingAvailable else {
sendToWebView(script: "console.error('NFC reading not available on this device');")
return
}
nfcSession = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false)
nfcSession?.alertMessage = "Hold your iPhone near an NFC tag"
nfcSession?.begin()
}
private func stopNfcSession() {
nfcSession?.invalidate()
nfcSession = nil
}
private func writeNfcTag(data: String) {
// Implement write logic
}
private func openSettings() {
if let url = URL(string: UIApplication.openSettingsURLString) {
DispatchQueue.main.async {
UIApplication.shared.open(url)
}
}
}
private func sendToWebView(script: String) {
DispatchQueue.main.async {
self.webView?.evaluateJavaScript(script, completionHandler: nil)
}
}
}
```
#### 3. Initialize the Bridge in Your View Controller
```swift
import UIKit
import WebKit
class WebViewController: UIViewController {
var webView: WKWebView!
var nfcBridge: NfcBridge!
override func viewDidLoad() {
super.viewDidLoad()
webView = WKWebView(frame: view.bounds)
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(webView)
nfcBridge = NfcBridge(webView: webView)
if let url = URL(string: "https://your-web-app-url.com") {
webView.load(URLRequest(url: url))
}
}
}
```
### Using the iOS Bridge in Your Web App
The native bridge will automatically be detected by Universal NFC when your web app runs inside the native iOS app's WebView:
```javascript
import { Nfc } from 'universal-nfc';
const nfc = new Nfc();
async function checkNfcSupport() {
const { enabled } = await nfc.isEnabled();
console.log('NFC supported and enabled:', enabled);
if (enabled) {
await nfc.startScanSession();
await nfc.addListener('tagDetected', (tag) => {
console.log('NFC tag detected via iOS bridge:', tag);
});
}
}
```
### Troubleshooting iOS-Specific Issues
#### "NFC reading is not supported in web browsers on iOS"
- This error occurs when trying to use NFC in Safari or a standard WebView.
- **Solution**: Use the native bridge approach with a custom iOS app.
#### "CoreNFC framework missing"
- Make sure you have the proper entitlements in your iOS app.
- Check that your iOS device supports NFC (iPhone 7 and later).
#### "Bridge communication error"
- Check the bridge implementation in your native app.
- Verify message format passed between WebView and native code.
## API Reference ## API Reference
### Core API (Nfc class) ### Core API (Nfc class)
@ -438,7 +641,3 @@ Permissions-Policy: nfc=self
## License ## License
MIT MIT
## Credits
This library is inspired by the API design of [@capawesome-team/capacitor-nfc](https://github.com/capawesome-team/capacitor-plugins/tree/main/packages/nfc), but implements a framework-agnostic solution based on the Web NFC API.

174
ios-bridge.ts Normal file
View File

@ -0,0 +1,174 @@
import { NfcPlugin, IsEnabledResult, TagDetectedEvent } from './definitions.js';
/**
* Interface for native iOS app to implement for WebView communication
*/
interface NativeIosBridge {
isNfcEnabled?: () => Promise<boolean>;
startNfcScan?: (options: string) => Promise<void>;
stopNfcScan?: () => Promise<void>;
writeNfcTag?: (data: string) => Promise<void>;
openSettings?: () => Promise<void>;
}
/**
* NFC implementation that communicates with a native iOS app via a bridge
* Note: This requires custom implementation in a native iOS app
*/
export class IosBridgeNfc implements NfcPlugin {
private bridge: NativeIosBridge;
private listeners: { [key: string]: Array<(...args: any[]) => void> } = {};
private isBridgeAvailable: boolean = false;
constructor() {
// Look for the bridge in the global scope
// The native app needs to inject this object
this.bridge = (window as any).nativeNfcBridge || {};
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('iOS NFC bridge initialized');
} else {
console.warn('iOS NFC bridge not found');
}
}
private handleNativeMessage(event: MessageEvent) {
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 as TagDetectedEvent;
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(): Promise<IsEnabledResult> {
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(): Promise<void> {
if (!this.isBridgeAvailable || !this.bridge.openSettings) {
throw new Error('NFC settings cannot be opened - bridge not available');
}
try {
await this.bridge.openSettings();
} catch (error) {
console.error('Error opening NFC settings through bridge:', error);
throw error;
}
}
async startScanSession(options?: any): Promise<void> {
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(): Promise<void> {
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: any): Promise<void> {
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(): Promise<void> {
throw new Error('makeReadOnly is not implemented in the iOS bridge');
}
async format(): Promise<void> {
throw new Error('format is not implemented in the iOS bridge');
}
async erase(): Promise<void> {
throw new Error('erase is not implemented in the iOS bridge');
}
async share(): Promise<void> {
throw new Error('share is not supported in iOS');
}
async stopSharing(): Promise<void> {
throw new Error('share is not supported in iOS');
}
async addListener(
eventName: 'nfcStatusChanged' | 'tagDetected',
listenerFunc: (data: any) => void,
): Promise<any> {
if (!this.listeners[eventName]) {
this.listeners[eventName] = [];
}
this.listeners[eventName].push(listenerFunc);
return {
remove: async () => {
this.removeListener(eventName, listenerFunc);
},
};
}
private removeListener(eventName: string, listenerFunc: (data: any) => void): void {
if (this.listeners[eventName]) {
this.listeners[eventName] = this.listeners[eventName].filter(
listener => listener !== listenerFunc
);
}
}
async removeAllListeners(): Promise<void> {
this.listeners = {};
}
}

73
ios-detection.ts Normal file
View File

@ -0,0 +1,73 @@
// src/ios-detection.ts
export interface IosSupportInfo {
isIos: boolean;
version: number | null;
supportsNfc: boolean;
requiresNative: boolean;
}
/**
* Provides detailed information about iOS NFC compatibility
*/
export class IosDetection {
/**
* Detects if the current device is running iOS and its NFC capabilities
*/
static getIosSupportInfo(): IosSupportInfo {
const userAgent = navigator.userAgent;
// Detect iOS
const isIos = /iphone|ipad|ipod/i.test(userAgent);
if (!isIos) {
return { isIos: false, version: null, supportsNfc: false, requiresNative: false };
}
// Extract iOS version
const versionMatch = userAgent.match(/OS (\d+)_(\d+)_?(\d+)?/);
const version = versionMatch ?
parseInt(versionMatch[1], 10) + (parseInt(versionMatch[2], 10) / 10) :
null;
// iOS NFC support info:
// - iOS 11+ supports NFC reading but requires a native app
// - No iOS version supports Web NFC API
const supportsNfc = version !== null && version >= 11;
return {
isIos,
version,
supportsNfc,
requiresNative: true // iOS always requires native app for NFC
};
}
/**
* Checks if this device supports NFC in any form (native or web)
*/
static hasNfcHardware(): boolean {
const iosInfo = this.getIosSupportInfo();
if (iosInfo.isIos) {
return iosInfo.supportsNfc;
}
// For Android/other platforms, we check based on the user agent
return /android/i.test(navigator.userAgent);
}
/**
* Provides guidance for enabling NFC on iOS
*/
static getIosNfcGuidance(): string {
const iosInfo = this.getIosSupportInfo();
if (!iosInfo.isIos) {
return '';
}
if (!iosInfo.supportsNfc) {
return 'Your iOS device does not support NFC or is running an iOS version below 11.0.';
}
return 'NFC on iOS requires a native app. The web browser cannot directly access NFC hardware on iOS devices.';
}
}

15
nfc.ts
View File

@ -10,6 +10,8 @@ import {
NfcErrorType, NfcErrorType,
} from "./definitions.js"; } from "./definitions.js";
import { WebNfc } from "./web.js"; import { WebNfc } from "./web.js";
import { IosBridgeNfc } from './ios-bridge.js';
import { IosDetection } from './ios-detection.js';
/** /**
* Main NFC class that provides access to NFC functionality. * Main NFC class that provides access to NFC functionality.
@ -18,15 +20,24 @@ import { WebNfc } from "./web.js";
export class Nfc { export class Nfc {
private implementation: NfcPlugin; private implementation: NfcPlugin;
private listeners: Map<string, Set<Function>> = new Map(); private listeners: Map<string, Set<Function>> = new Map();
private iosInfo: any;
constructor() { constructor() {
// Currently we only have the Web implementation this.iosInfo = IosDetection.getIosSupportInfo();
this.implementation = new WebNfc();
if (this.iosInfo.isIos && typeof (window as any).nativeNfcBridge !== 'undefined') {
console.log('Using iOS Native Bridge for NFC');
this.implementation = new IosBridgeNfc();
} else {
this.implementation = new WebNfc();
}
// Set up status monitoring to track NFC availability // Set up status monitoring to track NFC availability
this.monitorNfcStatus(); this.monitorNfcStatus();
} }
/** /**
* Internal method to monitor NFC status changes * Internal method to monitor NFC status changes
*/ */

105
web.ts
View File

@ -6,8 +6,10 @@ import {
ShareOptions, ShareOptions,
PluginListenerHandle, PluginListenerHandle,
TagDetectedEvent, TagDetectedEvent,
NfcErrorType,
NdefRecord, NdefRecord,
} from "./definitions.js"; } from './definitions.js';
import { IosDetection } from './ios-detection.js';
export class WebNfc implements NfcPlugin { export class WebNfc implements NfcPlugin {
private scanSessionActive = false; private scanSessionActive = false;
@ -15,73 +17,104 @@ export class WebNfc implements NfcPlugin {
private listeners: { [key: string]: Array<(...args: any[]) => void> } = {}; private listeners: { [key: string]: Array<(...args: any[]) => void> } = {};
private ndefReader: any = null; private ndefReader: any = null;
private nfcSupported: boolean = false; private nfcSupported: boolean = false;
private iosInfo: any = null;
constructor() { constructor() {
this.detectNfcSupport(); this.detectNfcSupport();
} }
private detectNfcSupport() { private detectNfcSupport() {
// Check if Web NFC API is available // Check for iOS first
if (typeof window !== "undefined") { this.iosInfo = IosDetection.getIosSupportInfo();
// Primary check for NDEFReader
this.nfcSupported = "NDEFReader" in window; if (this.iosInfo.isIos) {
this.nfcSupported = false;
console.info('iOS device detected:', this.iosInfo);
if (this.iosInfo.supportsNfc) {
console.warn('iOS NFC requires a native app wrapper - web browser access is not supported');
} else {
console.warn('NFC is not supported on this iOS device or iOS version');
}
return;
}
// Check Web NFC API for other platforms (primarily Android)
if (typeof window !== 'undefined') {
this.nfcSupported = 'NDEFReader' in window;
// Log platform info for debugging
const userAgent = navigator.userAgent; const userAgent = navigator.userAgent;
const isHttps = window.location.protocol === "https:"; const isHttps = window.location.protocol === 'https:';
const isPWA = window.matchMedia("(display-mode: standalone)").matches; const isPWA = window.matchMedia('(display-mode: standalone)').matches;
console.info("NFC Support Check:", { console.info('NFC Support Check:', {
supported: this.nfcSupported, supported: this.nfcSupported,
isHttps: isHttps, isHttps: isHttps,
isPWA: isPWA, isPWA: isPWA,
isAndroid: /android/i.test(userAgent), isAndroid: /android/i.test(userAgent),
isIOS: /iphone|ipad|ipod/i.test(userAgent), isChrome: /chrome/i.test(userAgent)
isChrome: /chrome/i.test(userAgent),
}); });
if (!this.nfcSupported) { if (!this.nfcSupported) {
// Provide helpful message about browser compatibility const reason = !isHttps ? 'NFC requires HTTPS' :
const reason = !isHttps !/android/i.test(userAgent) ? 'NFC Web API only supported on Android' :
? "NFC requires HTTPS" !/chrome/i.test(userAgent) ? 'NFC Web API only supported in Chrome-based browsers' :
: !/android/i.test(userAgent) 'This browser does not support the Web NFC API';
? "NFC Web API only supported on Android"
: !/chrome/i.test(userAgent)
? "NFC Web API only supported in Chrome-based browsers"
: "This browser does not support the Web NFC API";
console.warn(`Web NFC not available: ${reason}`); console.warn(`Web NFC not available: ${reason}`);
} }
} else { } else {
this.nfcSupported = false; this.nfcSupported = false;
console.warn("Web NFC not available: Not in browser environment"); console.warn('Web NFC not available: Not in browser environment');
} }
} }
async isEnabled(): Promise<IsEnabledResult> { async isEnabled(): Promise<IsEnabledResult> {
// For iOS, provide accurate info without throwing errors
if (this.iosInfo?.isIos) {
return { enabled: false };
}
return { enabled: this.nfcSupported }; return { enabled: this.nfcSupported };
} }
async openSettings(): Promise<void> { async openSettings(): Promise<void> {
// Special handling for iOS
if (this.iosInfo?.isIos) {
const message = IosDetection.getIosNfcGuidance();
// Use alert() on iOS to show guidance
if (typeof alert === 'function') {
alert(message);
}
console.warn('iOS NFC guidance:', message);
return;
}
if (!this.nfcSupported) { if (!this.nfcSupported) {
throw this.createCompatibilityError(); throw this.createCompatibilityError();
} }
console.warn( console.warn('openSettings: On web, users must enable NFC in device settings manually.');
"openSettings: On web, users must enable NFC in device settings manually."
);
// Provide instructions based on browser detection // Provide instructions based on browser detection
if (/android/i.test(navigator.userAgent)) { if (/android/i.test(navigator.userAgent)) {
alert( alert('Please enable NFC in your device settings: Settings > Connected devices > Connection preferences > NFC');
"Please enable NFC in your device settings: Settings > Connected devices > Connection preferences > NFC"
);
} else { } else {
alert("Please ensure NFC is enabled on your device."); alert('Please ensure NFC is enabled on your device.');
} }
} }
async startScanSession(options?: StartScanSessionOptions): Promise<void> { async startScanSession(options?: StartScanSessionOptions): Promise<void> {
if (this.iosInfo?.isIos) {
throw new Error("NFC reading is not supported in web browsers on iOS. " +
"To use NFC on iOS, you need a native app implementation.");
}
if (!this.nfcSupported) { if (!this.nfcSupported) {
throw this.createCompatibilityError(); throw this.createCompatibilityError();
} }
@ -364,18 +397,10 @@ export class WebNfc implements NfcPlugin {
} }
private createCompatibilityError(): Error { private createCompatibilityError(): Error {
return new Error( if (this.iosInfo?.isIos) {
"Web NFC API is not supported in this browser. NFC Web API requires Chrome 89+ on Android with NFC hardware, running over HTTPS." return new Error("iOS browsers don't support the Web NFC API. To use NFC on iOS, you need a native app implementation.");
); }
}
} return new Error('Web NFC API is not supported in this browser. NFC Web API requires Chrome 89+ on Android with NFC hardware, running over HTTPS.');
import { NFCDefinition } from "./definitions";
export class WebNFC {
// Implement your web NFC functionalities here
read(): NFCDefinition {
// Dummy implementation
return { id: "1", data: "sample data" };
} }
} }