시작하기
-
패키지 설치
Terminal window npm i @capgo/capacitor-nfcTerminal window pnpm add @capgo/capacitor-nfcTerminal window yarn add @capgo/capacitor-nfcTerminal window bun add @capgo/capacitor-nfc -
네이티브 프로젝트와 동기화
Terminal window npx cap syncTerminal window pnpm cap syncTerminal window yarn cap syncTerminal window bunx cap sync
iOS 구성
Section titled “iOS 구성”Info.plist에 NFC 사용 설명을 추가하세요:
<key>NFCReaderUsageDescription</key><string>This app needs NFC access to read and write tags</string>Xcode 프로젝트에서 Near Field Communication Tag Reading 기능을 활성화하세요.
Android 구성
Section titled “Android 구성”AndroidManifest.xml에 NFC 권한을 추가하세요:
<manifest> <uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="false" /></manifest>NFC 태그 스캔 시작
Section titled “NFC 태그 스캔 시작”import { CapacitorNfc } from '@capgo/capacitor-nfc';
await CapacitorNfc.startScanning({ invalidateAfterFirstRead: false, // Keep session open (iOS) alertMessage: 'Hold a tag near the top of your device.',});
const listener = await CapacitorNfc.addListener('nfcEvent', (event) => { console.log('Tag detected:', event.type); console.log('Tag ID:', event.tag?.id); console.log('NDEF message:', event.tag?.ndefMessage);});NFC 태그 읽기
Section titled “NFC 태그 읽기”await CapacitorNfc.addListener('nfcEvent', (event) => { if (event.tag?.ndefMessage) { event.tag.ndefMessage.forEach(record => { console.log('TNF:', record.tnf); console.log('Type:', record.type); console.log('Payload:', record.payload);
// Decode text record if (record.tnf === 1 && record.type[0] === 0x54) { // Text record const langLen = record.payload[0] & 0x3f; const text = new TextDecoder().decode( new Uint8Array(record.payload.slice(langLen + 1)) ); console.log('Text:', text); } }); }});NFC 태그에 쓰기
Section titled “NFC 태그에 쓰기”// Prepare a text recordconst encoder = new TextEncoder();const langBytes = Array.from(encoder.encode('en'));const textBytes = Array.from(encoder.encode('Hello NFC'));const payload = [langBytes.length & 0x3f, ...langBytes, ...textBytes];
await CapacitorNfc.write({ allowFormat: true, records: [ { tnf: 0x01, // TNF Well-known type: [0x54], // 'T' for Text id: [], payload, }, ],});
console.log('Tag written successfully');NFC 태그에 URL 쓰기
Section titled “NFC 태그에 URL 쓰기”const url = 'https://capgo.app';const urlBytes = Array.from(new TextEncoder().encode(url));
await CapacitorNfc.write({ allowFormat: true, records: [ { tnf: 0x01, // TNF Well-known type: [0x55], // 'U' for URI id: [], payload: [0x01, ...urlBytes], // 0x01 = https:// }, ],});NFC 태그 지우기
Section titled “NFC 태그 지우기”await CapacitorNfc.erase();console.log('Tag erased');태그를 읽기 전용으로 만들기
Section titled “태그를 읽기 전용으로 만들기”await CapacitorNfc.makeReadOnly();console.log('Tag is now read-only');await listener.remove();await CapacitorNfc.stopScanning();NFC 상태 확인
Section titled “NFC 상태 확인”const { status } = await CapacitorNfc.getStatus();console.log('NFC status:', status);// Possible values: 'NFC_OK', 'NO_NFC', 'NFC_DISABLED', 'NDEF_PUSH_DISABLED'
if (status === 'NFC_DISABLED') { // Open system settings await CapacitorNfc.showSettings();}Android Beam (P2P 공유)
Section titled “Android Beam (P2P 공유)”// Share data via Android Beamconst message = { records: [ { tnf: 0x01, type: [0x54], // Text id: [], payload: [/* text record payload */], }, ],};
await CapacitorNfc.share(message);
// Later, stop sharingawait CapacitorNfc.unshare();API 참조
Section titled “API 참조”startScanning(options?)
Section titled “startScanning(options?)”NFC 태그 수신 대기를 시작합니다.
interface StartScanningOptions { invalidateAfterFirstRead?: boolean; // iOS only, defaults to true alertMessage?: string; // iOS only androidReaderModeFlags?: number; // Android only}
await CapacitorNfc.startScanning(options);stopScanning()
Section titled “stopScanning()”NFC 스캔 세션을 중지합니다.
await CapacitorNfc.stopScanning();write(options)
Section titled “write(options)”마지막으로 발견된 태그에 NDEF 레코드를 씁니다.
interface WriteTagOptions { records: NdefRecord[]; allowFormat?: boolean; // Defaults to true}
interface NdefRecord { tnf: number; // Type Name Format type: number[]; // Record type id: number[]; // Record ID payload: number[]; // Record payload}
await CapacitorNfc.write(options);erase()
Section titled “erase()”마지막으로 발견된 태그를 지웁니다.
await CapacitorNfc.erase();makeReadOnly()
Section titled “makeReadOnly()”마지막으로 발견된 태그를 읽기 전용으로 만듭니다 (영구적).
await CapacitorNfc.makeReadOnly();share(options)
Section titled “share(options)”Android Beam을 통해 NDEF 메시지를 공유합니다 (Android 전용).
await CapacitorNfc.share({ records: [...] });unshare()
Section titled “unshare()”공유를 중지합니다 (Android 전용).
await CapacitorNfc.unshare();getStatus()
Section titled “getStatus()”현재 NFC 어댑터 상태를 가져옵니다.
const { status } = await CapacitorNfc.getStatus();// Returns: 'NFC_OK' | 'NO_NFC' | 'NFC_DISABLED' | 'NDEF_PUSH_DISABLED'showSettings()
Section titled “showSettings()”시스템 NFC 설정을 엽니다.
await CapacitorNfc.showSettings();nfcEvent
Section titled “nfcEvent”NFC 태그가 발견되었을 때 발생합니다.
interface NfcEvent { type: 'tag' | 'ndef' | 'ndef-mime' | 'ndef-formattable'; tag?: NfcTag;}
interface NfcTag { id: number[]; techTypes: string[]; type: string | null; maxSize: number | null; isWritable: boolean | null; canMakeReadOnly: boolean | null; ndefMessage: NdefRecord[] | null;}nfcStateChange
Section titled “nfcStateChange”NFC 어댑터 가용성이 변경되었을 때 발생합니다 (Android 전용).
interface NfcStateChangeEvent { status: NfcStatus; enabled: boolean;}완전한 예제
Section titled “완전한 예제”import { CapacitorNfc } from '@capgo/capacitor-nfc';
export class NfcService { private listener: any;
async startReading() { // Check NFC status const { status } = await CapacitorNfc.getStatus();
if (status === 'NO_NFC') { throw new Error('NFC not available on this device'); }
if (status === 'NFC_DISABLED') { await CapacitorNfc.showSettings(); return; }
// Start scanning await CapacitorNfc.startScanning({ invalidateAfterFirstRead: false, alertMessage: 'Ready to scan NFC tags', });
// Listen for tags this.listener = await CapacitorNfc.addListener('nfcEvent', (event) => { this.handleNfcEvent(event); }); }
private handleNfcEvent(event: any) { console.log('NFC Event:', event.type);
if (event.tag?.ndefMessage) { event.tag.ndefMessage.forEach(record => { this.processRecord(record); }); } }
private processRecord(record: any) { // Process text records if (record.tnf === 1 && record.type[0] === 0x54) { const langLen = record.payload[0] & 0x3f; const text = new TextDecoder().decode( new Uint8Array(record.payload.slice(langLen + 1)) ); console.log('Text:', text); }
// Process URI records if (record.tnf === 1 && record.type[0] === 0x55) { const uriCode = record.payload[0]; const uri = new TextDecoder().decode( new Uint8Array(record.payload.slice(1)) ); console.log('URI:', uri); } }
async writeText(text: string) { const encoder = new TextEncoder(); const langBytes = Array.from(encoder.encode('en')); const textBytes = Array.from(encoder.encode(text)); const payload = [langBytes.length & 0x3f, ...langBytes, ...textBytes];
await CapacitorNfc.write({ allowFormat: true, records: [ { tnf: 0x01, type: [0x54], id: [], payload, }, ], }); }
async stopReading() { if (this.listener) { await this.listener.remove(); } await CapacitorNfc.stopScanning(); }}NDEF 레코드 유형
Section titled “NDEF 레코드 유형”TNF (Type Name Format)
Section titled “TNF (Type Name Format)”0x00: Empty0x01: Well-known (e.g., Text, URI)0x02: MIME media type0x03: Absolute URI0x04: External type0x05: Unknown0x06: Unchanged0x07: Reserved
일반적인 레코드 유형
Section titled “일반적인 레코드 유형”- Text:
type: [0x54](‘T’) - URI:
type: [0x55](‘U’) - Smart Poster:
type: [0x53, 0x70](‘Sp’)
URI 접두사
Section titled “URI 접두사”0x00: (no prefix)0x01:https://0x02:https://0x03:http://0x04:https://www.
- NFC 상태 확인: NFC가 사용 가능하고 활성화되어 있는지 항상 확인
- 권한 처리: NFC 권한을 적절히 요청
- 스캔 중지: 배터리를 절약하기 위해 작업 완료 후 항상 스캔 중지
- 오류 처리: NFC 작업을 try-catch 블록으로 감싸기
- 기기에서 테스트: NFC 기능은 시뮬레이터/에뮬레이터에서 작동하지 않음
플랫폼 참고사항
Section titled “플랫폼 참고사항”- iOS 11.0+ 필요
- Core NFC 프레임워크 사용
- 백그라운드 태그 읽기 지원 (iOS 13+)
- NDEF 형식 태그 읽기로 제한
- 백그라운드에서 태그 쓰기 불가
- Info.plist에 NFCReaderUsageDescription 필요
Android
Section titled “Android”- Android 4.4 (API 19)+ 필요
- Android NFC API 사용
- 포그라운드 및 백그라운드 태그 읽기 모두 지원
- 태그에 쓰기 가능
- NFC가 있는 기기에서 Android Beam (P2P) 지원
- AndroidManifest.xml에 NFC 권한 필요
- 웹 플랫폼에서 지원되지 않음