@capgo/capacitor-nfc 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CapgoCapacitorNfc.podspec +17 -0
- package/LICENSE +21 -0
- package/Package.swift +28 -0
- package/README.md +385 -0
- package/android/build.gradle +57 -0
- package/android/src/main/AndroidManifest.xml +9 -0
- package/android/src/main/java/app/capgo/nfc/CapacitorNfcPlugin.java +535 -0
- package/android/src/main/java/app/capgo/nfc/NfcJsonConverter.java +135 -0
- package/dist/docs.json +499 -0
- package/dist/esm/definitions.d.ts +184 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +22 -0
- package/dist/esm/web.js +40 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +54 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +57 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/NfcPlugin/NfcPlugin.swift +407 -0
- package/ios/Tests/NfcPluginTests/NfcPluginTests.swift +10 -0
- package/package.json +87 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { registerPlugin } from '@capacitor/core';
|
|
2
|
+
const CapacitorNfc = registerPlugin('CapacitorNfc', {
|
|
3
|
+
web: () => import('./web').then((m) => new m.CapacitorNfcWeb()),
|
|
4
|
+
});
|
|
5
|
+
export * from './definitions';
|
|
6
|
+
export { CapacitorNfc };
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,YAAY,GAAG,cAAc,CAAqB,cAAc,EAAE;IACtE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;CAChE,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { CapacitorNfcPlugin } from './definitions';\n\nconst CapacitorNfc = registerPlugin<CapacitorNfcPlugin>('CapacitorNfc', {\n web: () => import('./web').then((m) => new m.CapacitorNfcWeb()),\n});\n\nexport * from './definitions';\nexport { CapacitorNfc };\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
import type { CapacitorNfcPlugin, NfcStateChangeEvent, NfcEvent, ShareTagOptions, StartScanningOptions, WriteTagOptions, PluginListenerHandle } from './definitions';
|
|
3
|
+
export declare class CapacitorNfcWeb extends WebPlugin implements CapacitorNfcPlugin {
|
|
4
|
+
private unsupported;
|
|
5
|
+
startScanning(_options?: StartScanningOptions): Promise<void>;
|
|
6
|
+
stopScanning(): Promise<void>;
|
|
7
|
+
write(_options: WriteTagOptions): Promise<void>;
|
|
8
|
+
erase(): Promise<void>;
|
|
9
|
+
makeReadOnly(): Promise<void>;
|
|
10
|
+
share(_options: ShareTagOptions): Promise<void>;
|
|
11
|
+
unshare(): Promise<void>;
|
|
12
|
+
getStatus(): Promise<{
|
|
13
|
+
status: 'NO_NFC';
|
|
14
|
+
}>;
|
|
15
|
+
showSettings(): Promise<void>;
|
|
16
|
+
getPluginVersion(): Promise<{
|
|
17
|
+
version: string;
|
|
18
|
+
}>;
|
|
19
|
+
addListener(eventName: 'nfcEvent', listenerFunc: (event: NfcEvent) => void): Promise<PluginListenerHandle>;
|
|
20
|
+
addListener(eventName: 'tagDiscovered' | 'ndefDiscovered' | 'ndefMimeDiscovered' | 'ndefFormatableDiscovered', listenerFunc: (event: NfcEvent) => void): Promise<PluginListenerHandle>;
|
|
21
|
+
addListener(eventName: 'nfcStateChange', listenerFunc: (event: NfcStateChangeEvent) => void): Promise<PluginListenerHandle>;
|
|
22
|
+
}
|
package/dist/esm/web.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
export class CapacitorNfcWeb extends WebPlugin {
|
|
3
|
+
unsupported(method) {
|
|
4
|
+
throw this.unimplemented(`CapacitorNfc.${method} is not available in a browser environment.`);
|
|
5
|
+
}
|
|
6
|
+
async startScanning(_options) {
|
|
7
|
+
this.unsupported('startScanning');
|
|
8
|
+
}
|
|
9
|
+
async stopScanning() {
|
|
10
|
+
this.unsupported('stopScanning');
|
|
11
|
+
}
|
|
12
|
+
async write(_options) {
|
|
13
|
+
this.unsupported('write');
|
|
14
|
+
}
|
|
15
|
+
async erase() {
|
|
16
|
+
this.unsupported('erase');
|
|
17
|
+
}
|
|
18
|
+
async makeReadOnly() {
|
|
19
|
+
this.unsupported('makeReadOnly');
|
|
20
|
+
}
|
|
21
|
+
async share(_options) {
|
|
22
|
+
this.unsupported('share');
|
|
23
|
+
}
|
|
24
|
+
async unshare() {
|
|
25
|
+
this.unsupported('unshare');
|
|
26
|
+
}
|
|
27
|
+
async getStatus() {
|
|
28
|
+
return { status: 'NO_NFC' };
|
|
29
|
+
}
|
|
30
|
+
async showSettings() {
|
|
31
|
+
this.unsupported('showSettings');
|
|
32
|
+
}
|
|
33
|
+
async getPluginVersion() {
|
|
34
|
+
return { version: '0.0.0-web' };
|
|
35
|
+
}
|
|
36
|
+
async addListener(eventName, _listenerFunc) {
|
|
37
|
+
this.unsupported(`addListener(${eventName})`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAY5C,MAAM,OAAO,eAAgB,SAAQ,SAAS;IACpC,WAAW,CAAC,MAAc;QAChC,MAAM,IAAI,CAAC,aAAa,CAAC,gBAAgB,MAAM,6CAA6C,CAAC,CAAC;IAChG,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAA+B;QACjD,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAyB;QACnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAyB;QACnC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAClC,CAAC;IAcD,KAAK,CAAC,WAAW,CAAC,SAAiB,EAAE,aAAuC;QAC1E,IAAI,CAAC,WAAW,CAAC,eAAe,SAAS,GAAG,CAAC,CAAC;IAChD,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type {\n CapacitorNfcPlugin,\n NfcStateChangeEvent,\n NfcEvent,\n ShareTagOptions,\n StartScanningOptions,\n WriteTagOptions,\n PluginListenerHandle,\n} from './definitions';\n\nexport class CapacitorNfcWeb extends WebPlugin implements CapacitorNfcPlugin {\n private unsupported(method: string): never {\n throw this.unimplemented(`CapacitorNfc.${method} is not available in a browser environment.`);\n }\n\n async startScanning(_options?: StartScanningOptions): Promise<void> {\n this.unsupported('startScanning');\n }\n\n async stopScanning(): Promise<void> {\n this.unsupported('stopScanning');\n }\n\n async write(_options: WriteTagOptions): Promise<void> {\n this.unsupported('write');\n }\n\n async erase(): Promise<void> {\n this.unsupported('erase');\n }\n\n async makeReadOnly(): Promise<void> {\n this.unsupported('makeReadOnly');\n }\n\n async share(_options: ShareTagOptions): Promise<void> {\n this.unsupported('share');\n }\n\n async unshare(): Promise<void> {\n this.unsupported('unshare');\n }\n\n async getStatus(): Promise<{ status: 'NO_NFC' }> {\n return { status: 'NO_NFC' };\n }\n\n async showSettings(): Promise<void> {\n this.unsupported('showSettings');\n }\n\n async getPluginVersion(): Promise<{ version: string }> {\n return { version: '0.0.0-web' };\n }\n\n addListener(\n eventName: 'nfcEvent',\n listenerFunc: (event: NfcEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'tagDiscovered' | 'ndefDiscovered' | 'ndefMimeDiscovered' | 'ndefFormatableDiscovered',\n listenerFunc: (event: NfcEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'nfcStateChange',\n listenerFunc: (event: NfcStateChangeEvent) => void,\n ): Promise<PluginListenerHandle>;\n async addListener(eventName: string, _listenerFunc: (..._args: any[]) => any): Promise<PluginListenerHandle> {\n this.unsupported(`addListener(${eventName})`);\n }\n}\n"]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@capacitor/core');
|
|
4
|
+
|
|
5
|
+
const CapacitorNfc = core.registerPlugin('CapacitorNfc', {
|
|
6
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapacitorNfcWeb()),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
class CapacitorNfcWeb extends core.WebPlugin {
|
|
10
|
+
unsupported(method) {
|
|
11
|
+
throw this.unimplemented(`CapacitorNfc.${method} is not available in a browser environment.`);
|
|
12
|
+
}
|
|
13
|
+
async startScanning(_options) {
|
|
14
|
+
this.unsupported('startScanning');
|
|
15
|
+
}
|
|
16
|
+
async stopScanning() {
|
|
17
|
+
this.unsupported('stopScanning');
|
|
18
|
+
}
|
|
19
|
+
async write(_options) {
|
|
20
|
+
this.unsupported('write');
|
|
21
|
+
}
|
|
22
|
+
async erase() {
|
|
23
|
+
this.unsupported('erase');
|
|
24
|
+
}
|
|
25
|
+
async makeReadOnly() {
|
|
26
|
+
this.unsupported('makeReadOnly');
|
|
27
|
+
}
|
|
28
|
+
async share(_options) {
|
|
29
|
+
this.unsupported('share');
|
|
30
|
+
}
|
|
31
|
+
async unshare() {
|
|
32
|
+
this.unsupported('unshare');
|
|
33
|
+
}
|
|
34
|
+
async getStatus() {
|
|
35
|
+
return { status: 'NO_NFC' };
|
|
36
|
+
}
|
|
37
|
+
async showSettings() {
|
|
38
|
+
this.unsupported('showSettings');
|
|
39
|
+
}
|
|
40
|
+
async getPluginVersion() {
|
|
41
|
+
return { version: '0.0.0-web' };
|
|
42
|
+
}
|
|
43
|
+
async addListener(eventName, _listenerFunc) {
|
|
44
|
+
this.unsupported(`addListener(${eventName})`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
49
|
+
__proto__: null,
|
|
50
|
+
CapacitorNfcWeb: CapacitorNfcWeb
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
exports.CapacitorNfc = CapacitorNfc;
|
|
54
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst CapacitorNfc = registerPlugin('CapacitorNfc', {\n web: () => import('./web').then((m) => new m.CapacitorNfcWeb()),\n});\nexport * from './definitions';\nexport { CapacitorNfc };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class CapacitorNfcWeb extends WebPlugin {\n unsupported(method) {\n throw this.unimplemented(`CapacitorNfc.${method} is not available in a browser environment.`);\n }\n async startScanning(_options) {\n this.unsupported('startScanning');\n }\n async stopScanning() {\n this.unsupported('stopScanning');\n }\n async write(_options) {\n this.unsupported('write');\n }\n async erase() {\n this.unsupported('erase');\n }\n async makeReadOnly() {\n this.unsupported('makeReadOnly');\n }\n async share(_options) {\n this.unsupported('share');\n }\n async unshare() {\n this.unsupported('unshare');\n }\n async getStatus() {\n return { status: 'NO_NFC' };\n }\n async showSettings() {\n this.unsupported('showSettings');\n }\n async getPluginVersion() {\n return { version: '0.0.0-web' };\n }\n async addListener(eventName, _listenerFunc) {\n this.unsupported(`addListener(${eventName})`);\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,YAAY,GAAGA,mBAAc,CAAC,cAAc,EAAE;AACpD,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;AACnE,CAAC;;ACFM,MAAM,eAAe,SAASC,cAAS,CAAC;AAC/C,IAAI,WAAW,CAAC,MAAM,EAAE;AACxB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,CAAC,aAAa,EAAE,MAAM,CAAC,2CAA2C,CAAC,CAAC;AACrG,IAAI;AACJ,IAAI,MAAM,aAAa,CAAC,QAAQ,EAAE;AAClC,QAAQ,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC;AACzC,IAAI;AACJ,IAAI,MAAM,YAAY,GAAG;AACzB,QAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;AACxC,IAAI;AACJ,IAAI,MAAM,KAAK,CAAC,QAAQ,EAAE;AAC1B,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;AACjC,IAAI;AACJ,IAAI,MAAM,KAAK,GAAG;AAClB,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;AACjC,IAAI;AACJ,IAAI,MAAM,YAAY,GAAG;AACzB,QAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;AACxC,IAAI;AACJ,IAAI,MAAM,KAAK,CAAC,QAAQ,EAAE;AAC1B,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;AACjC,IAAI;AACJ,IAAI,MAAM,OAAO,GAAG;AACpB,QAAQ,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC;AACnC,IAAI;AACJ,IAAI,MAAM,SAAS,GAAG;AACtB,QAAQ,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE;AACnC,IAAI;AACJ,IAAI,MAAM,YAAY,GAAG;AACzB,QAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;AACxC,IAAI;AACJ,IAAI,MAAM,gBAAgB,GAAG;AAC7B,QAAQ,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE;AACvC,IAAI;AACJ,IAAI,MAAM,WAAW,CAAC,SAAS,EAAE,aAAa,EAAE;AAChD,QAAQ,IAAI,CAAC,WAAW,CAAC,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;AACrD,IAAI;AACJ;;;;;;;;;"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
var capacitorCapacitorNfc = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const CapacitorNfc = core.registerPlugin('CapacitorNfc', {
|
|
5
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapacitorNfcWeb()),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
class CapacitorNfcWeb extends core.WebPlugin {
|
|
9
|
+
unsupported(method) {
|
|
10
|
+
throw this.unimplemented(`CapacitorNfc.${method} is not available in a browser environment.`);
|
|
11
|
+
}
|
|
12
|
+
async startScanning(_options) {
|
|
13
|
+
this.unsupported('startScanning');
|
|
14
|
+
}
|
|
15
|
+
async stopScanning() {
|
|
16
|
+
this.unsupported('stopScanning');
|
|
17
|
+
}
|
|
18
|
+
async write(_options) {
|
|
19
|
+
this.unsupported('write');
|
|
20
|
+
}
|
|
21
|
+
async erase() {
|
|
22
|
+
this.unsupported('erase');
|
|
23
|
+
}
|
|
24
|
+
async makeReadOnly() {
|
|
25
|
+
this.unsupported('makeReadOnly');
|
|
26
|
+
}
|
|
27
|
+
async share(_options) {
|
|
28
|
+
this.unsupported('share');
|
|
29
|
+
}
|
|
30
|
+
async unshare() {
|
|
31
|
+
this.unsupported('unshare');
|
|
32
|
+
}
|
|
33
|
+
async getStatus() {
|
|
34
|
+
return { status: 'NO_NFC' };
|
|
35
|
+
}
|
|
36
|
+
async showSettings() {
|
|
37
|
+
this.unsupported('showSettings');
|
|
38
|
+
}
|
|
39
|
+
async getPluginVersion() {
|
|
40
|
+
return { version: '0.0.0-web' };
|
|
41
|
+
}
|
|
42
|
+
async addListener(eventName, _listenerFunc) {
|
|
43
|
+
this.unsupported(`addListener(${eventName})`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
48
|
+
__proto__: null,
|
|
49
|
+
CapacitorNfcWeb: CapacitorNfcWeb
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
exports.CapacitorNfc = CapacitorNfc;
|
|
53
|
+
|
|
54
|
+
return exports;
|
|
55
|
+
|
|
56
|
+
})({}, capacitorExports);
|
|
57
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst CapacitorNfc = registerPlugin('CapacitorNfc', {\n web: () => import('./web').then((m) => new m.CapacitorNfcWeb()),\n});\nexport * from './definitions';\nexport { CapacitorNfc };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class CapacitorNfcWeb extends WebPlugin {\n unsupported(method) {\n throw this.unimplemented(`CapacitorNfc.${method} is not available in a browser environment.`);\n }\n async startScanning(_options) {\n this.unsupported('startScanning');\n }\n async stopScanning() {\n this.unsupported('stopScanning');\n }\n async write(_options) {\n this.unsupported('write');\n }\n async erase() {\n this.unsupported('erase');\n }\n async makeReadOnly() {\n this.unsupported('makeReadOnly');\n }\n async share(_options) {\n this.unsupported('share');\n }\n async unshare() {\n this.unsupported('unshare');\n }\n async getStatus() {\n return { status: 'NO_NFC' };\n }\n async showSettings() {\n this.unsupported('showSettings');\n }\n async getPluginVersion() {\n return { version: '0.0.0-web' };\n }\n async addListener(eventName, _listenerFunc) {\n this.unsupported(`addListener(${eventName})`);\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,YAAY,GAAGA,mBAAc,CAAC,cAAc,EAAE;IACpD,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;IACnE,CAAC;;ICFM,MAAM,eAAe,SAASC,cAAS,CAAC;IAC/C,IAAI,WAAW,CAAC,MAAM,EAAE;IACxB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,CAAC,aAAa,EAAE,MAAM,CAAC,2CAA2C,CAAC,CAAC;IACrG,IAAI;IACJ,IAAI,MAAM,aAAa,CAAC,QAAQ,EAAE;IAClC,QAAQ,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC;IACzC,IAAI;IACJ,IAAI,MAAM,YAAY,GAAG;IACzB,QAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;IACxC,IAAI;IACJ,IAAI,MAAM,KAAK,CAAC,QAAQ,EAAE;IAC1B,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;IACjC,IAAI;IACJ,IAAI,MAAM,KAAK,GAAG;IAClB,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;IACjC,IAAI;IACJ,IAAI,MAAM,YAAY,GAAG;IACzB,QAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;IACxC,IAAI;IACJ,IAAI,MAAM,KAAK,CAAC,QAAQ,EAAE;IAC1B,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;IACjC,IAAI;IACJ,IAAI,MAAM,OAAO,GAAG;IACpB,QAAQ,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC;IACnC,IAAI;IACJ,IAAI,MAAM,SAAS,GAAG;IACtB,QAAQ,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE;IACnC,IAAI;IACJ,IAAI,MAAM,YAAY,GAAG;IACzB,QAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;IACxC,IAAI;IACJ,IAAI,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE;IACvC,IAAI;IACJ,IAAI,MAAM,WAAW,CAAC,SAAS,EAAE,aAAa,EAAE;IAChD,QAAQ,IAAI,CAAC,WAAW,CAAC,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACrD,IAAI;IACJ;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import Capacitor
|
|
2
|
+
import CoreNFC
|
|
3
|
+
import UIKit
|
|
4
|
+
|
|
5
|
+
@objc(NfcPlugin)
|
|
6
|
+
public class NfcPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
7
|
+
private let pluginVersion = "0.0.1"
|
|
8
|
+
|
|
9
|
+
public let identifier = "NfcPlugin"
|
|
10
|
+
public let jsName = "CapacitorNfc"
|
|
11
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
12
|
+
CAPPluginMethod(name: "startScanning", returnType: CAPPluginReturnPromise),
|
|
13
|
+
CAPPluginMethod(name: "stopScanning", returnType: CAPPluginReturnPromise),
|
|
14
|
+
CAPPluginMethod(name: "write", returnType: CAPPluginReturnPromise),
|
|
15
|
+
CAPPluginMethod(name: "erase", returnType: CAPPluginReturnPromise),
|
|
16
|
+
CAPPluginMethod(name: "makeReadOnly", returnType: CAPPluginReturnPromise),
|
|
17
|
+
CAPPluginMethod(name: "share", returnType: CAPPluginReturnPromise),
|
|
18
|
+
CAPPluginMethod(name: "unshare", returnType: CAPPluginReturnPromise),
|
|
19
|
+
CAPPluginMethod(name: "getStatus", returnType: CAPPluginReturnPromise),
|
|
20
|
+
CAPPluginMethod(name: "showSettings", returnType: CAPPluginReturnPromise),
|
|
21
|
+
CAPPluginMethod(name: "getPluginVersion", returnType: CAPPluginReturnPromise)
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
private var readerSession: NFCNDEFReaderSession?
|
|
25
|
+
private let sessionQueue = DispatchQueue(label: "app.capgo.nfc.session")
|
|
26
|
+
private var currentTag: NFCNDEFTag?
|
|
27
|
+
private var invalidateAfterFirstRead = true
|
|
28
|
+
|
|
29
|
+
@objc public func startScanning(_ call: CAPPluginCall) {
|
|
30
|
+
#if targetEnvironment(simulator)
|
|
31
|
+
call.reject("NFC is not available on the simulator.", "NO_NFC")
|
|
32
|
+
return
|
|
33
|
+
#else
|
|
34
|
+
guard NFCNDEFReaderSession.readingAvailable else {
|
|
35
|
+
call.reject("NFC is not available on this device.", "NO_NFC")
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
invalidateAfterFirstRead = call.getBool("invalidateAfterFirstRead", true)
|
|
40
|
+
let alertMessage = call.getString("alertMessage")
|
|
41
|
+
|
|
42
|
+
DispatchQueue.main.async {
|
|
43
|
+
self.readerSession?.invalidate()
|
|
44
|
+
self.readerSession = NFCNDEFReaderSession(delegate: self, queue: self.sessionQueue, invalidateAfterFirstRead: self.invalidateAfterFirstRead)
|
|
45
|
+
if let alertMessage, !alertMessage.isEmpty {
|
|
46
|
+
self.readerSession?.alertMessage = alertMessage
|
|
47
|
+
}
|
|
48
|
+
self.readerSession?.begin()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
call.resolve()
|
|
52
|
+
#endif
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@objc public func stopScanning(_ call: CAPPluginCall) {
|
|
56
|
+
DispatchQueue.main.async {
|
|
57
|
+
self.readerSession?.invalidate()
|
|
58
|
+
self.readerSession = nil
|
|
59
|
+
self.currentTag = nil
|
|
60
|
+
}
|
|
61
|
+
call.resolve()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@objc public func write(_ call: CAPPluginCall) {
|
|
65
|
+
guard let session = readerSession, let tag = currentTag else {
|
|
66
|
+
call.reject("No active NFC session or tag. Call startScanning and present a tag before writing.")
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
guard let rawRecords = call.getArray("records") as? [[String: Any]] else {
|
|
71
|
+
call.reject("records is required and must be an array.")
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
do {
|
|
76
|
+
let message = try buildMessage(from: rawRecords)
|
|
77
|
+
performWrite(message: message, on: tag, session: session, call: call)
|
|
78
|
+
} catch {
|
|
79
|
+
call.reject("Invalid NDEF records payload.", nil, error)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@objc public func erase(_ call: CAPPluginCall) {
|
|
84
|
+
guard let session = readerSession, let tag = currentTag else {
|
|
85
|
+
call.reject("No active NFC session or tag. Call startScanning and present a tag before erasing.")
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let emptyRecord = NFCNDEFPayload(format: .empty, type: Data(), identifier: Data(), payload: Data())
|
|
90
|
+
let message = NFCNDEFMessage(records: [emptyRecord])
|
|
91
|
+
performWrite(message: message, on: tag, session: session, call: call)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@objc public func makeReadOnly(_ call: CAPPluginCall) {
|
|
95
|
+
call.reject("Making tags read only is not supported on iOS.", "UNSUPPORTED")
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@objc public func share(_ call: CAPPluginCall) {
|
|
99
|
+
call.reject("Peer-to-peer NFC sharing is not available on iOS.", "UNSUPPORTED")
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@objc public func unshare(_ call: CAPPluginCall) {
|
|
103
|
+
call.reject("Peer-to-peer NFC sharing is not available on iOS.", "UNSUPPORTED")
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@objc public func getStatus(_ call: CAPPluginCall) {
|
|
107
|
+
let status = NFCNDEFReaderSession.readingAvailable ? "NFC_OK" : "NO_NFC"
|
|
108
|
+
call.resolve([
|
|
109
|
+
"status": status
|
|
110
|
+
])
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@objc public func showSettings(_ call: CAPPluginCall) {
|
|
114
|
+
guard let url = URL(string: UIApplication.openSettingsURLString) else {
|
|
115
|
+
call.reject("Unable to open application settings.")
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
DispatchQueue.main.async {
|
|
120
|
+
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
|
121
|
+
}
|
|
122
|
+
call.resolve()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@objc public func getPluginVersion(_ call: CAPPluginCall) {
|
|
126
|
+
call.resolve([
|
|
127
|
+
"version": pluginVersion
|
|
128
|
+
])
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private func performWrite(message: NFCNDEFMessage, on tag: NFCNDEFTag, session: NFCNDEFReaderSession, call: CAPPluginCall) {
|
|
132
|
+
session.connect(to: tag) { [weak self] error in
|
|
133
|
+
guard let self else {
|
|
134
|
+
DispatchQueue.main.async { call.reject("Session is no longer available.") }
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if let error {
|
|
139
|
+
DispatchQueue.main.async {
|
|
140
|
+
call.reject("Failed to connect to tag.", nil, error)
|
|
141
|
+
}
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
tag.queryNDEFStatus { status, capacity, statusError in
|
|
146
|
+
if let statusError {
|
|
147
|
+
DispatchQueue.main.async {
|
|
148
|
+
call.reject("Failed to query tag status.", nil, statusError)
|
|
149
|
+
}
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
switch status {
|
|
154
|
+
case .readWrite:
|
|
155
|
+
if capacity < message.length {
|
|
156
|
+
DispatchQueue.main.async {
|
|
157
|
+
call.reject("Tag capacity is insufficient for the provided message.")
|
|
158
|
+
}
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
tag.writeNDEF(message) { writeError in
|
|
162
|
+
DispatchQueue.main.async {
|
|
163
|
+
if let writeError {
|
|
164
|
+
call.reject("Failed to write NDEF message.", nil, writeError)
|
|
165
|
+
} else {
|
|
166
|
+
call.resolve()
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
case .readOnly:
|
|
171
|
+
DispatchQueue.main.async {
|
|
172
|
+
call.reject("Tag is read only.")
|
|
173
|
+
}
|
|
174
|
+
case .notSupported:
|
|
175
|
+
DispatchQueue.main.async {
|
|
176
|
+
call.reject("Tag does not support NDEF.")
|
|
177
|
+
}
|
|
178
|
+
@unknown default:
|
|
179
|
+
DispatchQueue.main.async {
|
|
180
|
+
call.reject("Unknown tag status.")
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private func buildMessage(from records: [[String: Any]]) throws -> NFCNDEFMessage {
|
|
188
|
+
if records.isEmpty {
|
|
189
|
+
throw NfcPluginError.invalidPayload
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
let payloads = try records.map { record -> NFCNDEFPayload in
|
|
193
|
+
guard let tnfValue = record["tnf"] as? NSNumber,
|
|
194
|
+
let typeArray = record["type"],
|
|
195
|
+
let idArray = record["id"],
|
|
196
|
+
let payloadArray = record["payload"] else {
|
|
197
|
+
throw NfcPluginError.invalidPayload
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
let payload = NFCNDEFPayload(
|
|
201
|
+
format: NFCTypeNameFormat(rawValue: UInt8(truncating: tnfValue)) ?? .unknown,
|
|
202
|
+
type: data(from: typeArray),
|
|
203
|
+
identifier: data(from: idArray),
|
|
204
|
+
payload: data(from: payloadArray)
|
|
205
|
+
)
|
|
206
|
+
return payload
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return NFCNDEFMessage(records: payloads)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private func data(from any: Any) -> Data {
|
|
213
|
+
guard let numbers = any as? [NSNumber] else {
|
|
214
|
+
return Data()
|
|
215
|
+
}
|
|
216
|
+
var bytes = [UInt8]()
|
|
217
|
+
bytes.reserveCapacity(numbers.count)
|
|
218
|
+
numbers.forEach { number in
|
|
219
|
+
bytes.append(number.uint8Value)
|
|
220
|
+
}
|
|
221
|
+
return Data(bytes)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private func array(from data: Data?) -> [NSNumber]? {
|
|
225
|
+
guard let data else {
|
|
226
|
+
return nil
|
|
227
|
+
}
|
|
228
|
+
return data.map { NSNumber(value: $0) }
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private func notify(event: [String: Any]) {
|
|
232
|
+
DispatchQueue.main.async {
|
|
233
|
+
self.notifyListeners("nfcEvent", data: event, retainUntilConsumed: true)
|
|
234
|
+
guard let type = event["type"] as? String else {
|
|
235
|
+
return
|
|
236
|
+
}
|
|
237
|
+
switch type {
|
|
238
|
+
case "ndef":
|
|
239
|
+
self.notifyListeners("ndefDiscovered", data: event, retainUntilConsumed: true)
|
|
240
|
+
default:
|
|
241
|
+
self.notifyListeners("tagDiscovered", data: event, retainUntilConsumed: true)
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private func buildEvent(tag: NFCNDEFTag, status: NFCNDEFStatus, capacity: Int, message: NFCNDEFMessage?) -> [String: Any] {
|
|
247
|
+
var tagInfo: [String: Any] = [:]
|
|
248
|
+
if let identifierData = extractIdentifier(from: tag) {
|
|
249
|
+
tagInfo["id"] = array(from: identifierData)
|
|
250
|
+
}
|
|
251
|
+
tagInfo["techTypes"] = detectTechTypes(for: tag)
|
|
252
|
+
tagInfo["isWritable"] = status == .readWrite
|
|
253
|
+
tagInfo["maxSize"] = capacity
|
|
254
|
+
tagInfo["type"] = translateType(for: tag)
|
|
255
|
+
|
|
256
|
+
if let message {
|
|
257
|
+
tagInfo["ndefMessage"] = message.records.map { record in
|
|
258
|
+
[
|
|
259
|
+
"tnf": NSNumber(value: record.typeNameFormat.rawValue),
|
|
260
|
+
"type": array(from: record.type),
|
|
261
|
+
"id": array(from: record.identifier),
|
|
262
|
+
"payload": array(from: record.payload)
|
|
263
|
+
].compactMapValues { $0 }
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return [
|
|
268
|
+
"type": "ndef",
|
|
269
|
+
"tag": tagInfo
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private func extractIdentifier(from tag: NFCNDEFTag) -> Data? {
|
|
274
|
+
if let miFare = tag as? NFCMiFareTag {
|
|
275
|
+
return miFare.identifier
|
|
276
|
+
}
|
|
277
|
+
if #available(iOS 13.3, *), let iso7816 = tag as? NFCISO7816Tag {
|
|
278
|
+
return iso7816.identifier
|
|
279
|
+
}
|
|
280
|
+
if let iso15693 = tag as? NFCISO15693Tag {
|
|
281
|
+
return iso15693.identifier
|
|
282
|
+
}
|
|
283
|
+
if let feliCa = tag as? NFCFeliCaTag {
|
|
284
|
+
return Data(feliCa.currentIDm)
|
|
285
|
+
}
|
|
286
|
+
return nil
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
private func detectTechTypes(for tag: NFCNDEFTag) -> [String] {
|
|
290
|
+
var types: [String] = []
|
|
291
|
+
if tag is NFCMiFareTag {
|
|
292
|
+
types.append("NFCMiFareTag")
|
|
293
|
+
}
|
|
294
|
+
if tag is NFCISO7816Tag {
|
|
295
|
+
types.append("NFCISO7816Tag")
|
|
296
|
+
}
|
|
297
|
+
if tag is NFCISO15693Tag {
|
|
298
|
+
types.append("NFCISO15693Tag")
|
|
299
|
+
}
|
|
300
|
+
if tag is NFCFeliCaTag {
|
|
301
|
+
types.append("NFCFeliCaTag")
|
|
302
|
+
}
|
|
303
|
+
return types
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private func translateType(for tag: NFCNDEFTag) -> String? {
|
|
307
|
+
if let miFare = tag as? NFCMiFareTag {
|
|
308
|
+
switch miFare.mifareFamily {
|
|
309
|
+
case .plus:
|
|
310
|
+
return "MIFARE Plus"
|
|
311
|
+
case .ultralight:
|
|
312
|
+
return "MIFARE Ultralight"
|
|
313
|
+
case .desfire:
|
|
314
|
+
return "MIFARE DESFire"
|
|
315
|
+
case .unknown:
|
|
316
|
+
return "MIFARE"
|
|
317
|
+
@unknown default:
|
|
318
|
+
return "MIFARE"
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if tag is NFCISO7816Tag {
|
|
322
|
+
return "ISO 7816"
|
|
323
|
+
}
|
|
324
|
+
if tag is NFCISO15693Tag {
|
|
325
|
+
return "ISO 15693"
|
|
326
|
+
}
|
|
327
|
+
if tag is NFCFeliCaTag {
|
|
328
|
+
return "FeliCa"
|
|
329
|
+
}
|
|
330
|
+
return nil
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
extension NfcPlugin: NFCNDEFReaderSessionDelegate {
|
|
335
|
+
public func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
|
|
336
|
+
currentTag = nil
|
|
337
|
+
if (error as NSError).code != NFCReaderError.readerSessionInvalidationErrorFirstNDEFTagRead.rawValue {
|
|
338
|
+
DispatchQueue.main.async {
|
|
339
|
+
let payload: [String: Any] = [
|
|
340
|
+
"status": NFCNDEFReaderSession.readingAvailable ? "NFC_OK" : "NO_NFC",
|
|
341
|
+
"enabled": NFCNDEFReaderSession.readingAvailable
|
|
342
|
+
]
|
|
343
|
+
self.notifyListeners("nfcStateChange", data: payload, retainUntilConsumed: true)
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
readerSession = nil
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
public func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag]) {
|
|
350
|
+
guard let tag = tags.first else {
|
|
351
|
+
return
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
session.connect(to: tag) { [weak self] error in
|
|
355
|
+
guard let self else {
|
|
356
|
+
return
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if let error {
|
|
360
|
+
session.invalidate(errorMessage: "Failed to connect to the tag: \(error.localizedDescription)")
|
|
361
|
+
return
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
tag.queryNDEFStatus { status, capacity, statusError in
|
|
365
|
+
if let statusError {
|
|
366
|
+
session.invalidate(errorMessage: "Failed to read tag status: \(statusError.localizedDescription)")
|
|
367
|
+
return
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
tag.readNDEF { message, readError in
|
|
371
|
+
if let readError {
|
|
372
|
+
session.invalidate(errorMessage: "Failed to read NDEF message: \(readError.localizedDescription)")
|
|
373
|
+
return
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
self.currentTag = tag
|
|
377
|
+
let event = self.buildEvent(tag: tag, status: status, capacity: capacity, message: message)
|
|
378
|
+
self.notify(event: event)
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
public func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
|
|
385
|
+
guard !messages.isEmpty else {
|
|
386
|
+
return
|
|
387
|
+
}
|
|
388
|
+
let event: [String: Any] = [
|
|
389
|
+
"type": "ndef",
|
|
390
|
+
"tag": [
|
|
391
|
+
"ndefMessage": messages.first?.records.map { record in
|
|
392
|
+
[
|
|
393
|
+
"tnf": NSNumber(value: record.typeNameFormat.rawValue),
|
|
394
|
+
"type": array(from: record.type) ?? [],
|
|
395
|
+
"id": array(from: record.identifier) ?? [],
|
|
396
|
+
"payload": array(from: record.payload) ?? []
|
|
397
|
+
]
|
|
398
|
+
} ?? []
|
|
399
|
+
]
|
|
400
|
+
]
|
|
401
|
+
notify(event: event)
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
enum NfcPluginError: Error {
|
|
406
|
+
case invalidPayload
|
|
407
|
+
}
|