From da12e3e5ab28cb289b38de5675cf259b2980a8be Mon Sep 17 00:00:00 2001 From: cschlaefke Date: Mon, 20 Jul 2026 16:47:05 +0200 Subject: [PATCH] iOS-Push aktiviert: APNs/Entitlements + Doku MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Push Notifications & Background Mode (remote-notification) als iOS-Capability ergänzt (Runner.entitlements, Info.plist, project.pbxproj) - Apple Developer Account freigeschaltet, APNs-Schlüssel in Firebase hinterlegt - Doku: firebase-einrichtung.md Schritt 6 auf "erledigt" + Stolperfalle "Personal Team versteckt Push-Capability" festgehalten - Handoff: V1 nun auch iOS vollständig, iOS-Push aus Offen-Liste entfernt Co-Authored-By: Claude Opus 4.8 --- docs/firebase-einrichtung.md | 4 +++- docs/handoff.md | 8 ++++---- ios/Runner.xcodeproj/project.pbxproj | 10 +++++++--- ios/Runner/Info.plist | 12 ++++++++---- ios/Runner/Runner.entitlements | 8 ++++++++ 5 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 ios/Runner/Runner.entitlements diff --git a/docs/firebase-einrichtung.md b/docs/firebase-einrichtung.md index 7d278fb..3c740ef 100644 --- a/docs/firebase-einrichtung.md +++ b/docs/firebase-einrichtung.md @@ -133,7 +133,7 @@ Die Keys liegen damit im **Google Secret Manager** — verschlüsselt, nur die C **Android:** funktioniert sofort — beim ersten App-Start nach diesem Update fragt die App die Benachrichtigungs-Berechtigung ab, fertig. -**iOS braucht den Apple Developer Account** (Push ist auf iOS ohne bezahlten Account nicht möglich). Sobald er freigeschaltet ist: +**iOS braucht den Apple Developer Account** (Push ist auf iOS ohne bezahlten Account nicht möglich). ✅ **Erledigt am 2026-07-20** — iOS-Push ist eingerichtet und läuft auf dem echten Gerät. So wurde es gemacht: 1. **APNs-Schlüssel erzeugen:** → *Certificates, Identifiers & Profiles* → **Keys** → „+" → Namen vergeben, **Apple Push Notifications service (APNs)** ankreuzen → Continue → Register → **.p8-Datei herunterladen** (nur einmal möglich!) und die **Key ID** notieren; die **Team ID** steht oben rechts im Account. 2. **In Firebase hinterlegen:** Firebase Console → Projekteinstellungen (Zahnrad) → **Cloud Messaging** → Abschnitt „Apple-App-Konfiguration" → APNs-Authentifizierungsschlüssel **hochladen** (.p8 + Key ID + Team ID). @@ -141,6 +141,8 @@ Die Keys liegen damit im **Google Secret Manager** — verschlüsselt, nur die C Danach einmal neu bauen (`flutter run`) — die Erinnerungen landen dann auch auf dem iPhone-Sperrbildschirm. +> **Stolperfalle (teuer erkauft):** „Push Notifications" fehlte in Xcode unter „+ Capability", obwohl „Background Modes" da war. Ursache: Es war noch das alte **kostenlose „Personal Team"** als Signing-Team gewählt — Gratis-Teams dürfen kein Push, deshalb blendet Xcode den Eintrag komplett aus. Fix: In *Xcode → Settings → Accounts* die Apple-ID mit der bezahlten Mitgliedschaft hinzufügen und in *Signing & Capabilities* das Team **ohne** den Zusatz `(Personal Team)` wählen. Danach erscheint „Push Notifications" in der Liste. + ## Schritt 7 und folgende (kommen mit den nächsten Blöcken) - **Google-/Apple-Login** — zusätzlich zu E-Mail/Passwort (Apple-Login braucht ebenfalls den Developer Account). diff --git a/docs/handoff.md b/docs/handoff.md index 89b9ed5..073b35f 100644 --- a/docs/handoff.md +++ b/docs/handoff.md @@ -17,7 +17,7 @@ Private Flutter-App (iOS+Android) zur Pflanzenpflege für Haushalt + Pflanzen-Si ## Verifizierter Stand -- **V1 komplett** und auf Android Ende-zu-Ende getestet: Foto → Erkennung → vorbefülltes Profil; Tages-Checkliste; Sammel-Push kam im regulären Scheduler-Lauf auf dem Sperrbildschirm an. iOS-App läuft ebenfalls (Login, Pflanzen, Fotos) — **nur iOS-Push fehlt** (braucht Apple Developer Account, Beantragung scheiterte bisher an Apples Webseite; Schritte stehen in `docs/firebase-einrichtung.md` Schritt 6). +- **V1 komplett** und auf Android + iOS Ende-zu-Ende getestet: Foto → Erkennung → vorbefülltes Profil; Tages-Checkliste; Sammel-Push kam im regulären Scheduler-Lauf auf dem Sperrbildschirm an. **iOS-Push seit 2026-07-20 eingerichtet und laufend** (Apple Developer Account freigeschaltet, APNs-Schlüssel in Firebase, Push-/Background-Capability in Xcode — Details + Stolperfalle „Personal Team" in `docs/firebase-einrichtung.md` Schritt 6). - **V2 implementiert, deployt und vom Nutzer erfolgreich getestet** (Einladungscodes member/sitter, `joinHousehold`-Function, Rules-Enforcement für Sitter, „bestätigt von"-Anzeige). - **V2.1 Multi-Haushalt implementiert und getestet**: Nutzer bleiben Mitglied aller Haushalte (`memberUids` ist Quelle der Wahrheit, `users.householdId` nur noch aktiver Zeiger), `sendDailyReminders` sammelt Aufgaben aus allen Haushalten. - **V2.2 implementiert, deployt und vom Nutzer vollständig getestet und bestätigt**: Besitzer-Konzept (`ownerUid`, Alt-Haushalte: memberUids[0]), Besitzer-Anzeige, Haushalt umbenennen (Rules: Clients dürfen nur noch `name` ändern), Haushalts-Wechsler im Drawer, Tages-Checkliste gruppiert Aufgaben aus allen Haushalten, Functions `leaveHousehold`/`removeMember` (biegen den aktiven Zeiger des Betroffenen um, legen notfalls frischen Haushalt an). Zwei Nachbesserungen aus dem Live-Test, beide behoben und bestätigt: @@ -26,11 +26,11 @@ Private Flutter-App (iOS+Android) zur Pflanzenpflege für Haushalt + Pflanzen-Si ## Offen / Nächstes -**Offener Faden aus der letzten Session:** Der Nutzer wollte nach der V2.2-Bestätigung weitermachen, hat auf Rückfrage nach dem nächsten Punkt aber bewusst „Etwas anderes" gewählt statt einer der unten stehenden Optionen — die Session endete, bevor er sagen konnte, worum es geht. **Nächster Schritt: direkt fragen, was das Anliegen ist, nicht von einem der Kandidaten unten ausgehen.** +**Zuletzt erledigt (2026-07-20):** iOS-Push eingerichtet — Apple Developer Account war frisch freigeschaltet, APNs-Schlüssel/Firebase/Xcode-Capability durchgezogen, Nutzer bestätigt „läuft jetzt". Damit ist V1 auch auf iOS vollständig. -Bekannte Kandidaten, falls der Nutzer nach Optionen fragt: +Bekannte Kandidaten für den nächsten Schritt: -1. iOS-Push, sobald Apple Developer Account existiert. +1. **Apple-Login** — braucht denselben (jetzt vorhandenen) Developer Account, wäre logischer Anschluss an iOS-Push (siehe `docs/firebase-einrichtung.md` Schritt 7). 2. **V3:** Krankheits-Diagnose per Foto, Stellplatz-Bewertung (Standort-Analyse pro Stellplatz + Eignungs-Sterne pro Pflanze — Zwei-Ebenen-Konzept siehe Memory), Umtopf-Erinnerungen. 3. **Backlog:** Button „KI-Zweitmeinung" bei unbefriedigendem PlantNet-Ergebnis; Push-Anzeige auch bei App im Vordergrund; App Check vor App-Store-Release; Englisch (`app_en.arb`). diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 7a7bb21..d18b904 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -69,6 +69,7 @@ 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B91F40C029091C1C3E88A3C3 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D85240B0300E69D300945466 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -102,7 +103,6 @@ 041675BB1A44D5A4222F7755 /* Pods-RunnerTests.release.xcconfig */, 27AD176722468C79F044AE02 /* Pods-RunnerTests.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -151,6 +151,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + D85240B0300E69D300945466 /* Runner.entitlements */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, @@ -248,7 +249,7 @@ ); mainGroup = 97C146E51CF9000F007C117D; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; @@ -466,6 +467,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = KSX6GJY9C5; ENABLE_BITCODE = NO; @@ -649,6 +651,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = KSX6GJY9C5; ENABLE_BITCODE = NO; @@ -672,6 +675,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = KSX6GJY9C5; ENABLE_BITCODE = NO; @@ -724,7 +728,7 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 857cc35..e89e550 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -2,10 +2,6 @@ - NSCameraUsageDescription - LeafItToMe nutzt die Kamera, um Pflanzen zu fotografieren und automatisch zu erkennen. - NSPhotoLibraryUsageDescription - LeafItToMe greift auf deine Fotos zu, um vorhandene Pflanzenbilder auszuwählen. CADisableMinimumFrameDurationOnPhone CFBundleDevelopmentRegion @@ -30,6 +26,10 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS + NSCameraUsageDescription + LeafItToMe nutzt die Kamera, um Pflanzen zu fotografieren und automatisch zu erkennen. + NSPhotoLibraryUsageDescription + LeafItToMe greift auf deine Fotos zu, um vorhandene Pflanzenbilder auszuwählen. UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -53,6 +53,10 @@ UIApplicationSupportsIndirectInputEvents + UIBackgroundModes + + remote-notification + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements new file mode 100644 index 0000000..903def2 --- /dev/null +++ b/ios/Runner/Runner.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + +