电容 NFC 插件 (@ exxili/ capcor-nfc)
一个用于在iOS和Android设备上读取并编写NFC标记的Capacitor插件. 此插件允许您 :
- 从 NFC 标记读取 NDEF 信件 .
- 将 NDEF 信件写入 NFC 标签 .
说明: NFC功能只在运行iOS 13.0或更后兼容的iOS设备上可用.
这个项目得到最好的维护。 不保证答复、审查或发布时限
目录
安装
使用 npm 安装插件 :
npm install @exxili/capacitor-nfc
npx cap sync
iOS 设置
要在iOS上使用NFC功能,需要执行一些额外的设置步骤.
1. 启用NFC能力
在 Xcode 中 :
- 打开您的项目( O)
.xcworkspace(原始内容存档于2018-09-21). in Xcode. - 在工程导航中选择您的工程 .
- 选择您的应用目标 .
- 转到 签名能力( C) 选项卡.
- 点击
+ Capability按钮. - 添加 近地通讯标签读取。 。 。 .
高级标签格式 : 如果您需要 ISO 7816, ISO 15693, 或 FeliCa 访问( 读取原始的 UID, 系统代码等) , Apple 在您的提供配置和
Info.plist。插件在缺失时会自动倒回,但要解锁全部功能集,则会添加相关的密钥:<key>com.apple.developer.nfc.readersession.felica.systemcodes</key> <array> <string>12FC</string> <string>0000</string> </array> <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key> <array> <string>D2760000850100</string> <string>D2760000850101</string> <string>D2760001180101</string> <string>00000000000000</string> </array>用标签所需的值替换样本标识符。 咨询 Apple 的 CorenfC 文档以获取完整的权利密钥列表 .
2. 添加使用说明
添加数据 NFCReaderUsageDescription 键 Info.plist 以解释为什么您的应用程序需要访问 NFC .
在你身边 Info.plist 文件(通常位于 ios/App/App/Info.plist,添加:
<key>NFCReaderUsageDescription</key>
<string>This app requires access to NFC to read and write NFC tags.</string>
将描述替换为解释为何您的应用程序需要NFC访问的信息.
Android 设置
在您的 AndroidManifest.xml 文件 :
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
使用量
将插件导入您的代码 :
import { NFC } from '@exxili/capacitor-nfc';
读取 NFC 标记
要读取 NFC 标签, 您需要聆听 nfcTag 事件。 在 iOS 上,您还必须使用 startScan()。 。 。 .
import { NFC, NDEFMessagesTransformable, NFCError } from '@exxili/capacitor-nfc';
// Start NFC scanning (iOS only)
NFC.startScan().catch((error) => {
console.error('Error starting NFC scan:', error);
});
// Listen for NFC tag detection
NFC.onRead((data: NDEFMessagesTransformable) => {
// Text (T) and URI (U) records decoded; others best-effort UTF-8
const asString = data.string();
console.log('First record text payload:', asString.messages[0]?.records[0]?.payload);
// Raw bytes
const asUint8 = data.uint8Array();
console.log('First record raw bytes length:', asUint8.messages[0]?.records[0]?.payload.length);
// Access tag information (UID, tech types, etc.)
const info = asString.tagInfo;
if (info?.fallback) {
console.log('Reader fallback mode:', info.fallbackMode, 'Reason:', info.reason);
} else if (info) {
console.log('Tag UID:', info.uid);
console.log('Tag technologies:', info.techTypes);
console.log('Tag type:', info.type);
if (info.maxSize) {
console.log('Max NDEF size:', info.maxSize);
}
console.log('Is writable:', info.isWritable);
}
});
// Handle NFC errors
NFC.onError((error: NFCError) => {
console.error('NFC Error:', error);
});
写入 NFC 标记
要将 NDEF 信件写入 NFC 标记, 请使用 writeNDEF 方法和倾听 onWrite 事件.
import { NFC, NDEFWriteOptions, NFCError } from '@exxili/capacitor-nfc';
const message: NDEFWriteOptions = {
records: [
{
type: 'T', // Well Known Text record. String payload will be encoded as: [status][lang='en'][UTF-8 text]
payload: 'Hello, NFC!',
},
{
type: 'U', // Well Known URI record. String payload encoded as: [0x00][URI bytes]
payload: 'https://example.com',
},
{
type: 'T',
payload: new Uint8Array([0x01, 0x65, 0x48, 0x69]), // Raw bytes preserved (DO NOT re-format)
},
],
};
// For complete control over binary content, use raw mode:
const rawMessage: NDEFWriteOptions = {
rawMode: true, // Bypasses automatic Text/URI formatting
records: [
{
type: 'T',
payload: 'Hello, NFC!', // Written as UTF-8 bytes without Text record prefix
},
{
type: 'custom',
payload: new Uint8Array([0x01, 0x02, 0x03, 0x04]), // Exact bytes written to tag
},
],
};
// Write NDEF message to NFC tag
NFC.writeNDEF(message)
.then(() => {
console.log('Write initiated');
})
.catch((error) => {
console.error('Error writing to NFC tag:', error);
});
// Listen for write success
NFC.onWrite(() => {
console.log('NDEF message written successfully.');
});
// Handle NFC errors
NFC.onError((error: NFCError) => {
console.error('NFC Error:', error);
});
API 密码
方法
isSupported()
如果扫描设备上支持NFC,则返回.
回返数字 : Promise<{ supported: boolean }>
startScan()
启动 NFC 扫描会话 仅iOS。Android设备总是处于读取模式,因此设置 nfcTag 听者足以处理在Android上读取的标记.
如果扩展的CorenfC应享待遇(ISO 7816,ISO 15693,FeliCa)缺失,iOS实施现在会自动调整. 该插件首先尝试高级标签读取器,以便访问UID/tech信息. 当iOS报告时 Missing required entitlement,插件会降级为兼容模式(仅ISO 14443),必要时会降级为经典的NDEF读取器. 一个合成人 nfcTag 事件以 tagInfo.fallback, (中文(简体) ), tagInfo.fallbackMode,以及 tagInfo.reason 因此,你的UI可以立即作出反应.
您可以明确覆盖模式 :
mode: 'auto'(默认) – 有自动降级和缓存的高级阅读器.mode: 'full'– 迫使高级阅读器重新尝试,重置缓存后退状态.mode: 'compat'– 跳过高级探测器并直接跳入ISO 14443相容读取器.mode: 'ndef'– 绕行标记会话全部恢复到遗留的 NDEF 仅读取器.
遗产布尔斯 forceFull, (中文(简体) ), forceCompat,以及 forceNDEF 映射到上面的选项后向兼容性.
回返数字 : Promise<void>
NFC.startScan({ mode: 'auto' })
.then(() => {
// Scanning started
})
.catch((error) => {
console.error('Error starting NFC scan:', error);
});
cancelScan()
立即取消活动的 iOS CorenfC 阅读器会话( 如果有的话) 。 当您想要提早中止扫描, 而不是等待用户取消或标记检测超时时有用 .
平台注释:
- iOS:积极结束会话. 通话
startScan()回到承诺是安全的. - Android: No-op(Android总是被动地通过前地发送来收听;你一般只是忽略了未来的事件或控制UI状态).
await NFC.cancelScan(); // iOS: ends session; Android: no-op
// Optionally restart
await NFC.startScan();
回返数字 : Promise<void>
writeNDEF(options: NDEFWriteOptions<T extends string | number[] | Uint8Array = string>)
将 NDEF 消息写入 NFC 标签 .
有效载荷可作为字符串提供, Uint8Array,或数组.
自动格式化规则( 协助互通性):
- 案文(
type: 'T'+ 字符串有效载荷:按NFC论坛编码 RTD 文本规格[status][lang=en][UTF-8 text]。 。 。 . - URI (美国)
type: 'U'+字符串有效载荷:编码为[0x00][UTF-8 URI bytes](前缀压缩尚未应用). - 任何其他
type+ 字符串有效载荷:仅UTF-8字节(没有额外设定). Uint8Array或者说number[]有效载荷作为原始字节和书面逐字记录处理(从未更改).
原始模式设置 rawMode: true 以完全绕过自动Well Known Type格式。 所有字符串有效载荷都会被写成UTF-8字节,没有文本 ('T') 或 URI ('U') 前缀,使您完全控制了二进制内容.
如果您需要全手工控制文本或URI记录,则提供原始字节(编号[]/Uint8Array)和插件不会修改它们.
如果你试图写入零记录 承诺拒绝使用 Error("At least one NDEF record is required")。 。 。 .
Android的使用:由于Android在读写NFC标记时没有默认的UI,因此建议您在调用时在应用程序中添加一个UI指标 writeNDEF 并把它删除在 nfcWriteSuccess 收听器调用和 nfcError 听者唤回. 这将防止意外写到用户要读取的标签 .
参数数字 :
options: NDEFWriteOptions<T extends string | number[] | Uint8Array = string>- NDEF要写的信息。 必须有至少一个记录.
回返数字 : Promise<void>
NFC.writeNDEF(options)
.then(() => {
// Write initiated
})
.catch((error) => {
console.error('Error writing NDEF message:', error);
});
cancelWriteAndroid()
取消一个Android NFC写入操作. Android对于NFC标记写入没有本土的UI,因此这种方法允许开发者勾接自定义的UI来取消在建工程扫描.
听众
onRead(listener: (data: NDEFMessagesTransformable) => void)
为 NFC 标签检测事件添加一个收听器。 返回类型 NDEFMessagesTransformable,返回以下提供有效载荷的方法:
string(): 回归NDEFMessages<string>,所有的有效载荷都是弦.base64(): 回归NDEFMessages<string>,所有有效载荷都是从NFC标记读取的基数64编码有效载荷.uint8Array(): 回归NDEFMessages<Uint8Array>,所有有效载荷为Uint8ArraynFC 标签中的字节 .numberArray(): 回归NDEFMessages<number[]>,其中NFC标签中所有有效载荷的字节都作为代表number[]。 。 。 .
参数数字 :
listener: (data: NDEFMessagesTransformable) => void- 检测出NFC标签后调用功能.
回返数字 : () => void 取消订阅功能只删除此收听器 .
const offRead = NFC.onRead((data) => {
const textRecords = data.string(); // Decoded string representation
const base64Records = data.base64(); // Original base64 payloads
const bytesRecords = data.uint8Array(); // Uint8Array payloads
const numArrayRecords = data.numberArray(); // number[] representation
console.log(textRecords);
});
// Later (component unmount / cleanup)
offRead();
提示:每个屏幕/组件一次注册收听器,卸载时总是处理,以避免重复回调.
#### On Error
Adds a listener for NFC error events.
**Parameters**:
- `listener: (error: NFCError) => void` - The function to call when an NFC error occurs.
**Returns**: `() => void` Unsubscribe function.
#### On Error
Adds a listener for NFC error events.
**Parameters**:
- `listener: (error: NFCError) => void` - The function to call when an NFC error occurs.
**Returns**: `() => void` Unsubscribe function.
```typescript
const offError = NFC.onError(err => console.error('NFC Error:', err));
// later
offError();
接口
NDEFWriteOptions
写入 NDEF 信件的选项 .
interface NDEFWriteOptions<T extends string | number[] | Uint8Array = string> {
records: NDEFRecord<T>[];
/**
* When true, bypasses automatic Well Known Type formatting (Text 'T' and URI 'U' prefixes).
* All payloads are written as raw bytes without additional framing.
*/
rawMode?: boolean;
}
NDEFMessagesTransformable
归来 onRead 包括提供有效载荷的下列方法:
string(): 回归NDEFMessages<string>,所有的有效载荷都是弦.base64(): 回归NDEFMessages<string>,所有有效载荷都是从NFC标记读取的基数64编码有效载荷.uint8Array(): 回归NDEFMessages<Uint8Array>,所有有效载荷为Uint8ArraynFC 标签中的字节 .numberArray(): 回归NDEFMessages<number[]>,将NFC标记中的所有有效载荷字节作为number[]。 。 。 .
interface NDEFMessagesTransformable {
base64: () => NDEFMessages<string>; // Original base64 strings
uint8Array: () => NDEFMessages<Uint8Array>; // Raw bytes
string: () => NDEFMessages<string>; // Decoded (T & U handled, others UTF-8 best-effort)
numberArray: () => NDEFMessages<number[]>; // Raw bytes as number[]
}
NDEFMessages
数据来自NFC标签.
interface NDEFMessages {
messages: NDEFMessage[];
tagInfo?: TagInfo;
}
TagInfo
关于被读取的NFC标签的信息.
interface TagInfo {
/**
* The unique identifier of the tag (UID) as a hex string
*/
uid?: string;
/**
* The NFC tag technology types supported
*/
techTypes?: string[];
/**
* The maximum size of NDEF message that can be written to this tag (if applicable)
*/
maxSize?: number;
/**
* Whether the tag is writable
*/
isWritable?: boolean;
/**
* The tag type (e.g., "ISO14443-4", "MifareClassic", etc.)
*/
type?: string;
/**
* Present when the plugin downgraded capabilities for compatibility.
*/
fallback?: boolean;
/**
* Which fallback strategy is in use (`compat` or `ndef`).
*/
fallbackMode?: 'compat' | 'ndef';
/**
* Reason metadata (e.g., `missing-entitlement`).
*/
reason?: string;
}
StartScanOptions
IOS阅读器行为的可选tweaks.
interface StartScanOptions {
mode?: 'auto' | 'full' | 'compat' | 'ndef';
forceFull?: boolean;
forceCompat?: boolean;
forceNDEF?: boolean;
}
NDEFMessage
由一个或多个记录组成的NDEF消息.
interface NDEFMessage {
records: NDEFRecord[];
}
NDEFRecord
NDEF记录. payload 默认是代表数据的字节数组;这就是 NDEFRecord 从 NFC 标签中读取。 您可以选择提供 NDEFRecord 作为字符串 a Uint8Array 临τ.
interface NDEFRecord<T = number[]> {
/**
* The type of the record.
*/
type: string;
/**
* The payload of the record.
*/
payload: T;
}
NFCError
一个NFC错误.
interface NFCError {
/**
* The error message.
*/
error: string;
}
加入一个电容App
要将此插件集成到您的 Capacitor app 中 :
-
安装插件 :
npm install @exxili/capacitor-nfc npx cap sync -
导入代码中的插件 :
import { NFC } from '@exxili/capacitor-nfc'; -
使用在 使用量 节.
示例
以下是一个完整的例子,说明如何在您的应用程序中读取和写入NFC标签:
import { NFC, NDEFWriteOptions, NFCError, NDEFMessagesTransformable } from '@exxili/capacitor-nfc';
// Check if NFC is supported (optional gating logic)
const { supported } = await NFC.isSupported();
if (!supported) {
console.warn('NFC not supported on this device');
}
// Start NFC scanning (needed on iOS only)
NFC.startScan().catch((err) => console.error('Failed to start scan', err));
// Read listener returns a transformable wrapper
const offRead = NFC.onRead((data: NDEFMessagesTransformable) => {
const textView = data.string(); // NDEFMessages<string>
const rawBytesView = data.uint8Array(); // NDEFMessages<Uint8Array>
const firstText = textView.messages[0]?.records[0]?.payload;
const firstLength = rawBytesView.messages[0]?.records[0]?.payload.length;
console.log('First text record:', firstText);
console.log('First record byte length:', firstLength);
});
// Error listener (covers read & write errors)
const offError = NFC.onError((error: NFCError) => console.error('NFC Error:', error));
// Prepare an NDEF message to write (auto-formats Text/URI if payload is string)
const message: NDEFWriteOptions = {
records: [
{ type: 'T', payload: 'Hello, NFC!' },
{ type: 'U', payload: 'https://example.com' },
],
};
await NFC.writeNDEF(message).catch((err) => console.error('Write failed', err));
const offWrite = NFC.onWrite(() => console.log('Write success'));
// Later (cleanup)
offRead();
offError();
offWrite();
许可证
支助:如果你遇到任何问题或有问题,请随意打开一个问题.