diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle index 04f9ed8..445ea48 100644 --- a/android/app/capacitor.build.gradle +++ b/android/app/capacitor.build.gradle @@ -18,6 +18,7 @@ dependencies { implementation project(':capacitor-splash-screen') implementation project(':capacitor-status-bar') implementation project(':capawesome-team-capacitor-file-opener') + implementation project(':capawesome-team-capacitor-nfc') } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index cefeda9..955d1a4 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -36,7 +36,11 @@ - - + + + + + + diff --git a/android/app/src/main/assets/capacitor.plugins.json b/android/app/src/main/assets/capacitor.plugins.json index fbd92fd..1652d03 100644 --- a/android/app/src/main/assets/capacitor.plugins.json +++ b/android/app/src/main/assets/capacitor.plugins.json @@ -34,5 +34,9 @@ { "pkg": "@capawesome-team/capacitor-file-opener", "classpath": "io.capawesome.capacitorjs.plugins.fileopener.FileOpenerPlugin" + }, + { + "pkg": "@capawesome-team/capacitor-nfc", + "classpath": "io.capawesome.capacitorjs.plugins.nfc.NfcPlugin" } ] diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle index 32fc96b..f36cbe6 100644 --- a/android/capacitor.settings.gradle +++ b/android/capacitor.settings.gradle @@ -28,3 +28,6 @@ project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacit include ':capawesome-team-capacitor-file-opener' project(':capawesome-team-capacitor-file-opener').projectDir = new File('../node_modules/@capawesome-team/capacitor-file-opener/android') + +include ':capawesome-team-capacitor-nfc' +project(':capawesome-team-capacitor-nfc').projectDir = new File('../node_modules/@capawesome-team/capacitor-nfc/android') diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index 4fc39f4..23cb17f 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ 504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = ""; }; + 7C07B6D22B91FB6C00652B63 /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = ""; }; AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; }; AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = ""; }; FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = ""; }; @@ -73,6 +74,7 @@ 504EC3061FED79650016851F /* App */ = { isa = PBXGroup; children = ( + 7C07B6D22B91FB6C00652B63 /* App.entitlements */, 50379B222058CBB4000EE86E /* capacitor.config.json */, 504EC3071FED79650016851F /* AppDelegate.swift */, 504EC30B1FED79650016851F /* Main.storyboard */, @@ -128,7 +130,7 @@ 504EC3031FED79650016851F = { CreatedOnToolsVersion = 9.2; LastSwiftMigration = 1100; - ProvisioningStyle = Manual; + ProvisioningStyle = Automatic; }; }; }; @@ -345,19 +347,17 @@ baseConfigurationReference = FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = App/App.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = U73Q28Z596; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = U73Q28Z596; INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = de.dhbw.vs.standortapp; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match Development de.dhbw.vs.standortapp"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development de.dhbw.vs.standortapp"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -369,18 +369,16 @@ baseConfigurationReference = AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = App/App.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = U73Q28Z596; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = U73Q28Z596; INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = de.dhbw.vs.standortapp; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match AppStore de.dhbw.vs.standortapp"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore de.dhbw.vs.standortapp"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/ios/App/App/App.entitlements b/ios/App/App/App.entitlements new file mode 100644 index 0000000..2bb4dee --- /dev/null +++ b/ios/App/App/App.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.developer.nfc.readersession.formats + + TAG + + + diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist index 3b4bd9b..64eaa4f 100644 --- a/ios/App/App/Info.plist +++ b/ios/App/App/Info.plist @@ -16,9 +16,9 @@ $(PRODUCT_NAME) CFBundlePackageType APPL - CFBundleShortVersionString + CFBundleShortVersionString 5.0.0 - CFBundleVersion + CFBundleVersion 5.0.0 LSRequiresIPhoneOS @@ -45,5 +45,11 @@ UIViewControllerBasedStatusBarAppearance + NFCReaderUsageDescription + The app enables the reading and writing of various NFC tags. + com.apple.developer.nfc.readersession.iso7816.select-identifiers + + D2760000850100 + diff --git a/ios/App/App/capacitor.config.json b/ios/App/App/capacitor.config.json index 870b170..22aa4aa 100644 --- a/ios/App/App/capacitor.config.json +++ b/ios/App/App/capacitor.config.json @@ -5,7 +5,8 @@ "webDir": "www", "npmClient": "npm", "server": { - "iosScheme": "ionic" + "iosScheme": "ionic", + "url": "http://192.168.2.112:8100" }, "cordova": { "preferences": { diff --git a/ios/App/Podfile b/ios/App/Podfile index bee61ff..fb82035 100644 --- a/ios/App/Podfile +++ b/ios/App/Podfile @@ -20,6 +20,7 @@ def capacitor_pods pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen' pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar' pod 'CapawesomeTeamCapacitorFileOpener', :path => '../../node_modules/@capawesome-team/capacitor-file-opener' + pod 'CapawesomeTeamCapacitorNfc', :path => '../../node_modules/@capawesome-team/capacitor-nfc' pod 'CordovaPlugins', :path => '../capacitor-cordova-ios-plugins' end diff --git a/ios/App/Podfile.lock b/ios/App/Podfile.lock index 855c957..8cf7e61 100644 --- a/ios/App/Podfile.lock +++ b/ios/App/Podfile.lock @@ -20,6 +20,8 @@ PODS: - Capacitor - CapawesomeTeamCapacitorFileOpener (5.0.4): - Capacitor + - CapawesomeTeamCapacitorNfc (5.1.0-dev.7d38c01.1709239536): + - Capacitor - CordovaPlugins (5.6.0): - CapacitorCordova @@ -35,6 +37,7 @@ DEPENDENCIES: - "CapacitorSplashScreen (from `../../node_modules/@capacitor/splash-screen`)" - "CapacitorStatusBar (from `../../node_modules/@capacitor/status-bar`)" - "CapawesomeTeamCapacitorFileOpener (from `../../node_modules/@capawesome-team/capacitor-file-opener`)" + - "CapawesomeTeamCapacitorNfc (from `../../node_modules/@capawesome-team/capacitor-nfc`)" - CordovaPlugins (from `../capacitor-cordova-ios-plugins`) EXTERNAL SOURCES: @@ -60,6 +63,8 @@ EXTERNAL SOURCES: :path: "../../node_modules/@capacitor/status-bar" CapawesomeTeamCapacitorFileOpener: :path: "../../node_modules/@capawesome-team/capacitor-file-opener" + CapawesomeTeamCapacitorNfc: + :path: "../../node_modules/@capawesome-team/capacitor-nfc" CordovaPlugins: :path: "../capacitor-cordova-ios-plugins" @@ -75,8 +80,9 @@ SPEC CHECKSUMS: CapacitorSplashScreen: dd3de3f3644710fa2a697cfb91ec262eece4d242 CapacitorStatusBar: f390fbb49b82ffb754ea4b3cf71dc8b048baf3e7 CapawesomeTeamCapacitorFileOpener: a635d36c142c95018855c21c102da07eb88a4e1e + CapawesomeTeamCapacitorNfc: 62f7b56f556612e050d95a1be2d459c55b02eaa3 CordovaPlugins: 51a49218c1b6e2ae7d7f40efa9159eb978ddc888 -PODFILE CHECKSUM: 26c4df6714124140b8e56789f2c8fd87c2fef304 +PODFILE CHECKSUM: baa07d86309c338c813d17409138037a1834285f -COCOAPODS: 1.14.3 +COCOAPODS: 1.15.2 diff --git a/src/app/core/services/capacitor/capacitor-nfc/capacitor-nfc.service.ts b/src/app/core/services/capacitor/capacitor-nfc/capacitor-nfc.service.ts index 0fc18e2..0aa0a43 100644 --- a/src/app/core/services/capacitor/capacitor-nfc/capacitor-nfc.service.ts +++ b/src/app/core/services/capacitor/capacitor-nfc/capacitor-nfc.service.ts @@ -83,12 +83,18 @@ export class CapacitorNfcService { return Nfc.transceive(options); } - public connect(options: ConnectOptions): Promise { - return Nfc.connect(options); + public async connect(options: ConnectOptions): Promise { + const isAndroid = Capacitor.getPlatform() === 'android'; + if (isAndroid) { + await Nfc.connect(options); + } } public async close(): Promise { - await Nfc.close(); + const isAndroid = Capacitor.getPlatform() === 'android'; + if (isAndroid) { + await Nfc.close(); + } } public async openSettings(): Promise { diff --git a/src/app/core/services/nfc/nfc/nfc.service.ts b/src/app/core/services/nfc/nfc/nfc.service.ts index fc31140..c4b304d 100644 --- a/src/app/core/services/nfc/nfc/nfc.service.ts +++ b/src/app/core/services/nfc/nfc/nfc.service.ts @@ -30,64 +30,24 @@ export class NfcService { } public async stopScanSession(): Promise { - const isSupported = await this.isSupported(); - if (!isSupported) { - return; - } - const isEnabled = await this.isEnabled(); - if (!isEnabled) { - return; - } await this.capacitorNfcService.stopScanSession(); } public async write(message: NdefMessage): Promise { - const isSupported = await this.isSupported(); - if (!isSupported) { - throw this.createNotSupportedError(); - } - const isEnabled = await this.isEnabled(); - if (!isEnabled) { - throw this.createNotEnabledError(); - } await this.capacitorNfcService.write({ message, }); } public async erase(): Promise { - const isSupported = await this.isSupported(); - if (!isSupported) { - throw this.createNotSupportedError(); - } - const isEnabled = await this.isEnabled(); - if (!isEnabled) { - throw this.createNotEnabledError(); - } await this.capacitorNfcService.erase(); } public async format(): Promise { - const isSupported = await this.isSupported(); - if (!isSupported) { - throw this.createNotSupportedError(); - } - const isEnabled = await this.isEnabled(); - if (!isEnabled) { - throw this.createNotEnabledError(); - } await this.capacitorNfcService.format(); } public async transceive(techType: NfcTagTechType, data: number[]): Promise { - const isSupported = await this.isSupported(); - if (!isSupported) { - throw this.createNotSupportedError(); - } - const isEnabled = await this.isEnabled(); - if (!isEnabled) { - throw this.createNotEnabledError(); - } const { response } = await this.capacitorNfcService.transceive({ techType, data, @@ -96,28 +56,12 @@ export class NfcService { } public async connect(techType: NfcTagTechType): Promise { - const isSupported = await this.isSupported(); - if (!isSupported) { - throw this.createNotSupportedError(); - } - const isEnabled = await this.isEnabled(); - if (!isEnabled) { - throw this.createNotEnabledError(); - } await this.capacitorNfcService.connect({ techType, }); } public async close(): Promise { - const isSupported = await this.isSupported(); - if (!isSupported) { - return; - } - const isEnabled = await this.isEnabled(); - if (!isEnabled) { - return; - } await this.capacitorNfcService.close(); } diff --git a/src/app/modules/canteen/components/canteen-card-balance-modal/canteen-card-balance-modal.component.html b/src/app/modules/canteen/components/canteen-card-balance-modal/canteen-card-balance-modal.component.html index 156990b..4d72d5f 100644 --- a/src/app/modules/canteen/components/canteen-card-balance-modal/canteen-card-balance-modal.component.html +++ b/src/app/modules/canteen/components/canteen-card-balance-modal/canteen-card-balance-modal.component.html @@ -1,6 +1,6 @@ - Wohnungsmarkt + Kartenguthaben @@ -12,10 +12,10 @@ - Guthaben + Kartenguthaben - @if (balance()) { + @if (balance() !== undefined) { Dein aktuelles Guthaben betrÃĪgt:

{{ balance() | currency: "EUR" : "symbol" : "1.2-2" : "de" }}

diff --git a/src/app/modules/canteen/components/canteen-card-balance-modal/canteen-card-balance-modal.component.ts b/src/app/modules/canteen/components/canteen-card-balance-modal/canteen-card-balance-modal.component.ts index 74b9121..c8575cc 100644 --- a/src/app/modules/canteen/components/canteen-card-balance-modal/canteen-card-balance-modal.component.ts +++ b/src/app/modules/canteen/components/canteen-card-balance-modal/canteen-card-balance-modal.component.ts @@ -43,6 +43,7 @@ export class CanteenCardBalanceModalComponent { public async startScanSession(): Promise { this.isScanSessionActive.set(true); + this.balance.set(undefined); try { await this.nfcService.startScanSession(); } catch (error) { @@ -74,7 +75,8 @@ export class CanteenCardBalanceModalComponent { // 4. Parse the balance const balance = this.convertBytesToBalance(response); this.balance.set(balance); - // 5. Stop the scan session + // 5. Close the connection + await this.nfcService.close(); } finally { await this.stopScanSession(); } @@ -88,6 +90,7 @@ export class CanteenCardBalanceModalComponent { trimmedBytes.reverse(); const hex = this.nfcHelperService.convertBytesToHex(trimmedBytes); const balance = this.nfcHelperService.convertHexToNumber(hex); + console.log({ bytes, trimmedBytes, hex, balance }); return balance; } @@ -116,9 +119,6 @@ export class CanteenCardBalanceModalComponent { this.isScanSessionActive.set(false); void this.activeWriterAlert?.dismiss(); this.cancelSubject.next(undefined); - await this.nfcService.close().catch(() => { - // Ignore errors - }); await this.nfcService.stopScanSession(); } } diff --git a/src/app/modules/canteen/components/canteen-menu-popover/canteen-menu-popover.component.html b/src/app/modules/canteen/components/canteen-menu-popover/canteen-menu-popover.component.html index a13d707..01e320d 100644 --- a/src/app/modules/canteen/components/canteen-menu-popover/canteen-menu-popover.component.html +++ b/src/app/modules/canteen/components/canteen-menu-popover/canteen-menu-popover.component.html @@ -1,5 +1,5 @@ - Guthaben auslesen + Kartenguthaben diff --git a/src/app/modules/canteen/components/canteen-menu-popover/canteen-menu-popover.component.ts b/src/app/modules/canteen/components/canteen-menu-popover/canteen-menu-popover.component.ts index 8e62f1c..4b6688c 100644 --- a/src/app/modules/canteen/components/canteen-menu-popover/canteen-menu-popover.component.ts +++ b/src/app/modules/canteen/components/canteen-menu-popover/canteen-menu-popover.component.ts @@ -15,5 +15,6 @@ export class CanteenMenuPopoverComponent { await this.dialogService.showModal({ component: CanteenCardBalanceModalComponent, }); + await this.dialogService.dismissPopover(); } }