From 4390949c7ea9e41a881fcfcea84449de8de992f1 Mon Sep 17 00:00:00 2001 From: cschlaefke Date: Sat, 18 Jul 2026 22:44:24 +0200 Subject: [PATCH] Firebase angebunden: Projekt leaf-it-to-me-app, App-Registrierung iOS/Android, Initialisierung beim Start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - flutterfire configure: firebase_options.dart, google-services.json, GoogleService-Info.plist - firebase_core eingebunden, Firebase.initializeApp in main.dart - Doku firebase-einrichtung.md auf aktuellen Stand gebracht - Verifiziert: flutter analyze/test grün, Android-Debug-Build erfolgreich Co-Authored-By: Claude Fable 5 --- android/app/build.gradle.kts | 3 ++ android/app/google-services.json | 29 ++++++++++++ android/settings.gradle.kts | 3 ++ docs/firebase-einrichtung.md | 9 +++- firebase.json | 1 + ios/Runner.xcodeproj/project.pbxproj | 4 ++ ios/Runner/GoogleService-Info.plist | 30 ++++++++++++ lib/firebase_options.dart | 68 ++++++++++++++++++++++++++++ lib/main.dart | 5 ++ pubspec.lock | 24 ++++++++++ pubspec.yaml | 1 + 11 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 android/app/google-services.json create mode 100644 firebase.json create mode 100644 ios/Runner/GoogleService-Info.plist create mode 100644 lib/firebase_options.dart diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 95c2e20..031726b 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,5 +1,8 @@ plugins { id("com.android.application") + // START: FlutterFire Configuration + id("com.google.gms.google-services") + // END: FlutterFire Configuration id("kotlin-android") // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. id("dev.flutter.flutter-gradle-plugin") diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..7662f48 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "724282636354", + "project_id": "leaf-it-to-me-app", + "storage_bucket": "leaf-it-to-me-app.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:724282636354:android:db0671eaf1218c414195db", + "android_client_info": { + "package_name": "dev.leafittome.app" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyBl591_B4-LJ2k_D-kSBJx_PILYOevnkHg" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index ca7fe06..174f408 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -20,6 +20,9 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" id("com.android.application") version "8.11.1" apply false + // START: FlutterFire Configuration + id("com.google.gms.google-services") version("4.3.15") apply false + // END: FlutterFire Configuration id("org.jetbrains.kotlin.android") version "2.2.20" apply false } diff --git a/docs/firebase-einrichtung.md b/docs/firebase-einrichtung.md index 6c3cb98..f48e642 100644 --- a/docs/firebase-einrichtung.md +++ b/docs/firebase-einrichtung.md @@ -2,7 +2,7 @@ Firebase ist Googles „Backend als Dienst": Es liefert uns Login (**Auth**), Datenbank mit Echtzeit-Sync (**Firestore**), Foto-Speicher (**Storage**), serverseitigen Code (**Cloud Functions**) und Push-Nachrichten (**FCM**) — ohne dass wir einen eigenen Server betreiben. -> **Stand:** Vorbereitung. Die App läuft aktuell noch mit Demo-Daten ohne Firebase. Dieses Dokument wird mit jedem Firebase-Baustein erweitert und führt dich durch alles, was du selbst (mit deinem Google-Konto) tun musst. +> **Stand:** Schritt 1–3 sind erledigt (18.07.2026): Projekt `leaf-it-to-me-app` existiert, die iOS- und Android-App sind registriert, `lib/firebase_options.dart` ist erzeugt und Firebase wird beim App-Start initialisiert. Die App-Daten (Pflanzen etc.) laufen noch über Demo-Daten — Firestore folgt im nächsten Block. Dieses Dokument wird mit jedem Baustein erweitert. ## Was wofür? (Überblick) @@ -52,6 +52,13 @@ flutterfire configure `flutterfire configure` erzeugt `lib/firebase_options.dart` — darin stehen die Projekt-Kennungen (keine Geheimnisse, darf ins Git). Die eigentlichen API-Keys (Anthropic, PlantNet) leben **nur** in der Cloud-Functions-Umgebung, niemals in der App. +**Was dabei konkret passiert ist (zum Nachvollziehen):** + +- In der Firebase Console tauchen unter *Projekteinstellungen → Meine Apps* jetzt zwei Apps auf (iOS und Android, jeweils `dev.leafittome.app`). +- `android/app/google-services.json` und `ios/Runner/GoogleService-Info.plist` sind die plattformspezifischen Verbindungsdateien; `firebase.json` merkt sich die Zuordnung fürs CLI. +- In den Android-Gradle-Dateien wurde das `google-services`-Plugin eingetragen (verarbeitet die JSON-Datei beim Build). +- `lib/main.dart` ruft beim Start `Firebase.initializeApp(...)` auf — ab jetzt können wir nach und nach Auth, Firestore, Storage und FCM andocken. + ## Schritt 4 und folgende (kommen mit den nächsten Blöcken) - **Firestore-Datenmodell + Sicherheitsregeln** — wer darf was lesen/schreiben (Haushalts-Mitgliedschaft), Doku folgt beim Firestore-Block. diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..5067faa --- /dev/null +++ b/firebase.json @@ -0,0 +1 @@ +{"flutter":{"platforms":{"android":{"default":{"projectId":"leaf-it-to-me-app","appId":"1:724282636354:android:db0671eaf1218c414195db","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"leaf-it-to-me-app","appId":"1:724282636354:ios:7c2855f20b2ba5ba4195db","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"leaf-it-to-me-app","configurations":{"android":"1:724282636354:android:db0671eaf1218c414195db","ios":"1:724282636354:ios:7c2855f20b2ba5ba4195db"}}}}}} \ No newline at end of file diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 088f616..7ad9bff 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 1AE0D843A80013A3DE955CB5 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5A01F7941722D9D24C51BCF1 /* GoogleService-Info.plist */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; @@ -45,6 +46,7 @@ 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 5A01F7941722D9D24C51BCF1 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -94,6 +96,7 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + 5A01F7941722D9D24C51BCF1 /* GoogleService-Info.plist */, ); sourceTree = ""; }; @@ -216,6 +219,7 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + 1AE0D843A80013A3DE955CB5 /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..9879748 --- /dev/null +++ b/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,30 @@ + + + + + API_KEY + AIzaSyBpDElvx9ahyDnBerwL9iQrbuebDtCHRFA + GCM_SENDER_ID + 724282636354 + PLIST_VERSION + 1 + BUNDLE_ID + dev.leafittome.app + PROJECT_ID + leaf-it-to-me-app + STORAGE_BUCKET + leaf-it-to-me-app.firebasestorage.app + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:724282636354:ios:7c2855f20b2ba5ba4195db + + \ No newline at end of file diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart new file mode 100644 index 0000000..a8398f9 --- /dev/null +++ b/lib/firebase_options.dart @@ -0,0 +1,68 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: type=lint +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for web - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return android; + case TargetPlatform.iOS: + return ios; + case TargetPlatform.macOS: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for macos - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.windows: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for windows - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyBl591_B4-LJ2k_D-kSBJx_PILYOevnkHg', + appId: '1:724282636354:android:db0671eaf1218c414195db', + messagingSenderId: '724282636354', + projectId: 'leaf-it-to-me-app', + storageBucket: 'leaf-it-to-me-app.firebasestorage.app', + ); + + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyBpDElvx9ahyDnBerwL9iQrbuebDtCHRFA', + appId: '1:724282636354:ios:7c2855f20b2ba5ba4195db', + messagingSenderId: '724282636354', + projectId: 'leaf-it-to-me-app', + storageBucket: 'leaf-it-to-me-app.firebasestorage.app', + iosBundleId: 'dev.leafittome.app', + ); +} diff --git a/lib/main.dart b/lib/main.dart index 10010e4..e6c4900 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,17 @@ +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'app.dart'; import 'core/settings/settings_provider.dart'; +import 'firebase_options.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); final prefs = await SharedPreferences.getInstance(); runApp( ProviderScope( diff --git a/pubspec.lock b/pubspec.lock index 862ee83..70cbf8c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -129,6 +129,30 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "6f22d1c62e0c20976f02cd842c7b7cd3c0f561cc2052586411871045c08860c9" + url: "https://pub.dev" + source: hosted + version: "4.12.1" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: f74d1d6fabccf7743b0144c2ed363d81049e258e22428ebb6fb0faec2fa7d938 + url: "https://pub.dev" + source: hosted + version: "8.0.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: ddab99d709b8c27dd47576eb05a1e719e07a2aa45c009a49ae92ac4d2a8ca555 + url: "https://pub.dev" + source: hosted + version: "3.9.1" fixnum: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a2ac678..d2fcddd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,6 +40,7 @@ dependencies: go_router: ^17.3.0 shared_preferences: ^2.5.5 intl: any + firebase_core: ^4.12.1 dev_dependencies: flutter_test: