@exxili/capacitor-nfc 0.0.13 → 0.0.14

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.
@@ -1,169 +1,181 @@
1
- import Foundation
2
- import Capacitor
3
- import CoreNFC
4
-
5
- @objc(NFCPlugin)
6
- public class NFCPlugin: CAPPlugin, CAPBridgedPlugin {
7
- public let identifier = "NFCPlugin"
8
- public let jsName = "NFC"
9
- public let pluginMethods: [CAPPluginMethod] = [
10
- CAPPluginMethod(name: "isSupported", returnType: CAPPluginReturnPromise),
11
- CAPPluginMethod(name: "cancelWriteAndroid", returnType: CAPPluginReturnPromise),
12
- CAPPluginMethod(name: "startScan", returnType: CAPPluginReturnPromise),
13
- CAPPluginMethod(name: "cancelScan", returnType: CAPPluginReturnPromise),
14
- CAPPluginMethod(name: "writeNDEF", returnType: CAPPluginReturnPromise)
15
- ]
16
-
17
- private let reader = NFCReader()
18
- private let writer = NFCWriter()
19
-
20
- @objc func isSupported(_ call: CAPPluginCall) {
21
- call.resolve(["supported": NFCNDEFReaderSession.readingAvailable])
22
- }
23
-
24
- @objc func cancelWriteAndroid(_ call: CAPPluginCall) {
25
- call.reject("Function not implemented for iOS")
26
- }
27
-
28
- @objc func startScan(_ call: CAPPluginCall) {
29
- print("startScan called")
30
- if let preferredMode = call.getString("mode") {
31
- reader.setPreferredReaderMode(preferredMode)
32
- } else if call.getBool("forceFull") == true {
33
- reader.setPreferredReaderMode("full")
34
- } else if call.getBool("forceCompat") == true {
35
- reader.setPreferredReaderMode("compat")
36
- } else if call.getBool("forceNDEF") == true {
37
- reader.setPreferredReaderMode("ndef")
38
- }
39
- reader.onNDEFMessageReceived = { messages, tagInfo in
40
- var ndefMessages = [[String: Any]]()
41
-
42
- if messages.isEmpty {
43
- // If no NDEF messages but we have tag info, create a fallback record with the UID
44
- if let tagInfo = tagInfo, let uid = tagInfo["uid"] as? String {
45
- let payloadData = uid.data(using: .utf8)?.base64EncodedString() ?? ""
46
- let records = [[
47
- "type": "ID",
48
- "payload": payloadData
49
- ]]
50
- ndefMessages.append([
51
- "records": records
52
- ])
53
- }
54
- } else {
55
- for message in messages {
56
- var records = [[String: Any]]()
57
- for record in message.records {
58
- let recordType = String(data: record.type, encoding: .utf8) ?? ""
59
- let payloadData = record.payload.base64EncodedString()
60
-
61
- records.append([
62
- "type": recordType,
63
- "payload": payloadData
64
- ])
65
- }
66
- ndefMessages.append([
67
- "records": records
68
- ])
69
- }
70
- }
71
-
72
- var response: [String: Any] = ["messages": ndefMessages]
73
- if let tagInfo = tagInfo {
74
- response["tagInfo"] = tagInfo
75
- }
76
-
77
- self.notifyListeners("nfcTag", data: response)
78
- }
79
-
80
- reader.onError = { error in
81
- if let nfcError = error as? NFCReaderError {
82
- if nfcError.code != .readerSessionInvalidationErrorUserCanceled {
83
- self.notifyListeners("nfcError", data: ["error": nfcError.localizedDescription])
84
- }
85
- }
86
- }
87
-
88
- reader.startScanning()
89
- call.resolve()
90
- }
91
-
92
- @objc func cancelScan(_ call: CAPPluginCall) {
93
- reader.cancelScanning()
94
- call.resolve()
95
- }
96
-
97
- @objc func writeNDEF(_ call: CAPPluginCall) {
98
- print("writeNDEF called")
99
-
100
- guard let recordsData = call.getArray("records") as? [[String: Any]] else {
101
- call.reject("Records are required")
102
- return
103
- }
104
-
105
- var ndefRecords = [NFCNDEFPayload]()
106
- for recordData in recordsData {
107
- guard let type = recordData["type"] as? String,
108
- let payload = recordData["payload"] as? [NSNumber]
109
- else {
110
- print("Skipping record due to missing or invalid record")
111
- continue
112
- }
113
-
114
- guard let payloadArray = payload as [NSNumber]? else {
115
- print("Skipping record due to missing or invalid 'payload' (expected array of numbers)")
116
- continue
117
- }
118
-
119
- var payloadBytes = [UInt8]()
120
- for number in payloadArray {
121
- payloadBytes.append(number.uint8Value)
122
- }
123
- let payloadData = Data(payloadBytes)
124
-
125
- let format: NFCTypeNameFormat
126
- let typeEncoding: String.Encoding
127
- if type == "T" || type == "U" {
128
- format = .nfcWellKnown
129
- typeEncoding = .utf8
130
- } else if type.contains("/") {
131
- format = .media
132
- typeEncoding = .ascii
133
- } else {
134
- format = .nfcExternal
135
- typeEncoding = .utf8
136
- }
137
-
138
- guard let typeData = type.data(using: typeEncoding) else {
139
- print("Skipping record due to unsupported type encoding")
140
- continue
141
- }
142
-
143
- let ndefRecord = NFCNDEFPayload(
144
- format: format,
145
- type: typeData,
146
- identifier: Data(),
147
- payload: payloadData
148
- )
149
- ndefRecords.append(ndefRecord)
150
- }
151
-
152
- let ndefMessage = NFCNDEFMessage(records: ndefRecords)
153
-
154
- writer.onWriteSuccess = {
155
- self.notifyListeners("nfcWriteSuccess", data: ["success": true])
156
- }
157
-
158
- writer.onError = { error in
159
- if let nfcError = error as? NFCReaderError {
160
- if nfcError.code != .readerSessionInvalidationErrorUserCanceled {
161
- self.notifyListeners("nfcError", data: ["error": nfcError.localizedDescription])
162
- }
163
- }
164
- }
165
-
166
- writer.startWriting(message: ndefMessage)
167
- call.resolve()
168
- }
169
- }
1
+ import Foundation
2
+ import Capacitor
3
+ import CoreNFC
4
+
5
+ @objc(NFCPlugin)
6
+ public class NFCPlugin: CAPPlugin, CAPBridgedPlugin {
7
+ public let identifier = "NFCPlugin"
8
+ public let jsName = "NFC"
9
+ public let pluginMethods: [CAPPluginMethod] = [
10
+ CAPPluginMethod(name: "isSupported", returnType: CAPPluginReturnPromise),
11
+ CAPPluginMethod(name: "cancelWriteAndroid", returnType: CAPPluginReturnPromise),
12
+ CAPPluginMethod(name: "startScan", returnType: CAPPluginReturnPromise),
13
+ CAPPluginMethod(name: "cancelScan", returnType: CAPPluginReturnPromise),
14
+ CAPPluginMethod(name: "writeNDEF", returnType: CAPPluginReturnPromise),
15
+ CAPPluginMethod(name: "getStatus", returnType: CAPPluginReturnPromise)
16
+ ]
17
+
18
+ private let reader = NFCReader()
19
+ private let writer = NFCWriter()
20
+
21
+ private func isNfcAvailable() -> Bool {
22
+ NFCNDEFReaderSession.readingAvailable
23
+ }
24
+
25
+ @objc func isSupported(_ call: CAPPluginCall) {
26
+ call.resolve(["supported": isNfcAvailable()])
27
+ }
28
+
29
+ @objc func cancelWriteAndroid(_ call: CAPPluginCall) {
30
+ call.reject("Function not implemented for iOS")
31
+ }
32
+
33
+ @objc func startScan(_ call: CAPPluginCall) {
34
+ print("startScan called")
35
+ if let preferredMode = call.getString("mode") {
36
+ reader.setPreferredReaderMode(preferredMode)
37
+ } else if call.getBool("forceFull") == true {
38
+ reader.setPreferredReaderMode("full")
39
+ } else if call.getBool("forceCompat") == true {
40
+ reader.setPreferredReaderMode("compat")
41
+ } else if call.getBool("forceNDEF") == true {
42
+ reader.setPreferredReaderMode("ndef")
43
+ }
44
+ reader.onNDEFMessageReceived = { messages, tagInfo in
45
+ var ndefMessages = [[String: Any]]()
46
+
47
+ if messages.isEmpty {
48
+ // If no NDEF messages but we have tag info, create a fallback record with the UID
49
+ if let tagInfo = tagInfo, let uid = tagInfo["uid"] as? String {
50
+ let payloadData = uid.data(using: .utf8)?.base64EncodedString() ?? ""
51
+ let records = [[
52
+ "type": "ID",
53
+ "payload": payloadData
54
+ ]]
55
+ ndefMessages.append([
56
+ "records": records
57
+ ])
58
+ }
59
+ } else {
60
+ for message in messages {
61
+ var records = [[String: Any]]()
62
+ for record in message.records {
63
+ let recordType = String(data: record.type, encoding: .utf8) ?? ""
64
+ let payloadData = record.payload.base64EncodedString()
65
+
66
+ records.append([
67
+ "type": recordType,
68
+ "payload": payloadData
69
+ ])
70
+ }
71
+ ndefMessages.append([
72
+ "records": records
73
+ ])
74
+ }
75
+ }
76
+
77
+ var response: [String: Any] = ["messages": ndefMessages]
78
+ if let tagInfo = tagInfo {
79
+ response["tagInfo"] = tagInfo
80
+ }
81
+
82
+ self.notifyListeners("nfcTag", data: response)
83
+ }
84
+
85
+ reader.onError = { error in
86
+ if let nfcError = error as? NFCReaderError {
87
+ if nfcError.code != .readerSessionInvalidationErrorUserCanceled {
88
+ self.notifyListeners("nfcError", data: ["error": nfcError.localizedDescription])
89
+ }
90
+ }
91
+ }
92
+
93
+ reader.startScanning()
94
+ call.resolve()
95
+ }
96
+
97
+ @objc func cancelScan(_ call: CAPPluginCall) {
98
+ reader.cancelScanning()
99
+ call.resolve()
100
+ }
101
+
102
+ @objc func writeNDEF(_ call: CAPPluginCall) {
103
+ print("writeNDEF called")
104
+
105
+ guard let recordsData = call.getArray("records") as? [[String: Any]] else {
106
+ call.reject("Records are required")
107
+ return
108
+ }
109
+
110
+ var ndefRecords = [NFCNDEFPayload]()
111
+ for recordData in recordsData {
112
+ guard let type = recordData["type"] as? String,
113
+ let payload = recordData["payload"] as? [NSNumber]
114
+ else {
115
+ print("Skipping record due to missing or invalid record")
116
+ continue
117
+ }
118
+
119
+ guard let payloadArray = payload as [NSNumber]? else {
120
+ print("Skipping record due to missing or invalid 'payload' (expected array of numbers)")
121
+ continue
122
+ }
123
+
124
+ var payloadBytes = [UInt8]()
125
+ for number in payloadArray {
126
+ payloadBytes.append(number.uint8Value)
127
+ }
128
+ let payloadData = Data(payloadBytes)
129
+
130
+ let format: NFCTypeNameFormat
131
+ let typeEncoding: String.Encoding
132
+ if type == "T" || type == "U" {
133
+ format = .nfcWellKnown
134
+ typeEncoding = .utf8
135
+ } else if type.contains("/") {
136
+ format = .media
137
+ typeEncoding = .ascii
138
+ } else {
139
+ format = .nfcExternal
140
+ typeEncoding = .utf8
141
+ }
142
+
143
+ guard let typeData = type.data(using: typeEncoding) else {
144
+ print("Skipping record due to unsupported type encoding")
145
+ continue
146
+ }
147
+
148
+ let ndefRecord = NFCNDEFPayload(
149
+ format: format,
150
+ type: typeData,
151
+ identifier: Data(),
152
+ payload: payloadData
153
+ )
154
+ ndefRecords.append(ndefRecord)
155
+ }
156
+
157
+ let ndefMessage = NFCNDEFMessage(records: ndefRecords)
158
+
159
+ writer.onWriteSuccess = {
160
+ self.notifyListeners("nfcWriteSuccess", data: ["success": true])
161
+ }
162
+
163
+ writer.onError = { error in
164
+ if let nfcError = error as? NFCReaderError {
165
+ if nfcError.code != .readerSessionInvalidationErrorUserCanceled {
166
+ self.notifyListeners("nfcError", data: ["error": nfcError.localizedDescription])
167
+ }
168
+ }
169
+ }
170
+
171
+ writer.startWriting(message: ndefMessage)
172
+ call.resolve()
173
+ }
174
+
175
+ @objc func getStatus(_ call: CAPPluginCall) {
176
+ let status = isNfcAvailable() ? "ENABLED" : "NOT_SUPPORTED"
177
+ call.resolve([
178
+ "status": status
179
+ ])
180
+ }
181
+ }