From 696ed2f4521f9993a2cca61aeb7897fd7ae2004c Mon Sep 17 00:00:00 2001 From: Marcello Date: Fri, 3 Apr 2026 10:11:37 +0200 Subject: [PATCH 1/4] Refactor package name from `eu.project.sayitagain` to `eu.project.sia` - Rename base package directory and update package declarations in `MainActivity.kt`, `SaveFileContract.kt`, and `ApplicationClass.kt`. - Update `namespace` and `applicationId` in `app/build.gradle.kts` to reflect the new package name. --- app/build.gradle.kts | 4 ++-- .../java/eu/project/{sayitagain => sia}/ApplicationClass.kt | 2 +- .../main/java/eu/project/{sayitagain => sia}/MainActivity.kt | 2 +- .../java/eu/project/{sayitagain => sia}/SaveFileContract.kt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename app/src/main/java/eu/project/{sayitagain => sia}/ApplicationClass.kt (92%) rename app/src/main/java/eu/project/{sayitagain => sia}/MainActivity.kt (98%) rename app/src/main/java/eu/project/{sayitagain => sia}/SaveFileContract.kt (96%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index af91f3a..bcc8e4f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -7,11 +7,11 @@ plugins { } android { - namespace = "eu.project.sayitagain" + namespace = "eu.project.sia" compileSdk = 36 defaultConfig { - applicationId = "eu.project.sayitagain" + applicationId = "eu.project.sia" minSdk = 26 targetSdk = 34 versionCode = 1 diff --git a/app/src/main/java/eu/project/sayitagain/ApplicationClass.kt b/app/src/main/java/eu/project/sia/ApplicationClass.kt similarity index 92% rename from app/src/main/java/eu/project/sayitagain/ApplicationClass.kt rename to app/src/main/java/eu/project/sia/ApplicationClass.kt index f2babc5..d1a5b4a 100644 --- a/app/src/main/java/eu/project/sayitagain/ApplicationClass.kt +++ b/app/src/main/java/eu/project/sia/ApplicationClass.kt @@ -1,4 +1,4 @@ -package eu.project.sayitagain +package eu.project.sia import android.app.Application import dagger.hilt.android.HiltAndroidApp diff --git a/app/src/main/java/eu/project/sayitagain/MainActivity.kt b/app/src/main/java/eu/project/sia/MainActivity.kt similarity index 98% rename from app/src/main/java/eu/project/sayitagain/MainActivity.kt rename to app/src/main/java/eu/project/sia/MainActivity.kt index afa1c66..5a20023 100644 --- a/app/src/main/java/eu/project/sayitagain/MainActivity.kt +++ b/app/src/main/java/eu/project/sia/MainActivity.kt @@ -1,4 +1,4 @@ -package eu.project.sayitagain +package eu.project.sia import android.net.Uri import android.os.Bundle diff --git a/app/src/main/java/eu/project/sayitagain/SaveFileContract.kt b/app/src/main/java/eu/project/sia/SaveFileContract.kt similarity index 96% rename from app/src/main/java/eu/project/sayitagain/SaveFileContract.kt rename to app/src/main/java/eu/project/sia/SaveFileContract.kt index 7814b28..2ab68aa 100644 --- a/app/src/main/java/eu/project/sayitagain/SaveFileContract.kt +++ b/app/src/main/java/eu/project/sia/SaveFileContract.kt @@ -1,4 +1,4 @@ -package eu.project.sayitagain +package eu.project.sia import android.app.Activity import android.content.Context From 540d83a8ecef578ed07cfd7f97dbb50df8faf12a Mon Sep 17 00:00:00 2001 From: Marcello Date: Fri, 3 Apr 2026 11:19:20 +0200 Subject: [PATCH 2/4] Add Firebase and Crashlytics dependencies - Add `google-services` and `firebase-crashlytics` plugins to the root and app-level `build.gradle.kts` files. - Include Firebase BOM, Crashlytics, and Analytics dependencies in the `app` and `common` modules. - Define versions and library aliases for `firebase-bom` (34.11.0), `google-services` (4.4.4), and `firebase-crashlytics` (3.0.6) in `libs.versions.toml`. --- app/build.gradle.kts | 9 +++++++++ build.gradle.kts | 2 ++ common/build.gradle.kts | 7 +++++++ gradle/libs.versions.toml | 10 +++++++++- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index bcc8e4f..e3b30c8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,6 +4,8 @@ plugins { alias(libs.plugins.compose.compiler) alias(libs.plugins.google.devtools.ksp) alias(libs.plugins.hilt.android) + alias(libs.plugins.google.services) + alias(libs.plugins.firebase.crashlytics) } android { @@ -70,6 +72,13 @@ dependencies { // Splash screen implementation(libs.androidx.core.splashscreen) +// Firebase + implementation(platform(libs.firebase.bom)) + +// Crashlytics + implementation(libs.firebase.crashlytics) + implementation(libs.firebase.analytics) + implementation(project(":common")) implementation(project(":scaffold")) implementation(project(":localData")) diff --git a/build.gradle.kts b/build.gradle.kts index dd6d3f5..c9be53f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,4 +6,6 @@ plugins { alias(libs.plugins.compose.compiler) apply false alias(libs.plugins.google.devtools.ksp) apply false alias(libs.plugins.hilt.android) apply false + alias(libs.plugins.google.services) apply false + alias(libs.plugins.firebase.crashlytics) apply false } \ No newline at end of file diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 23e3515..54d8cc6 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -54,5 +54,12 @@ dependencies { // Serialization implementation(libs.kotlinx.serialization.json) + // Firebase + implementation(platform(libs.firebase.bom)) + + // Crashlytics + implementation(libs.firebase.crashlytics) + implementation(libs.firebase.analytics) + implementation(libs.navigation.compose) } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dfc26b2..2f8256c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,12 +1,15 @@ [versions] converterGsonVersion = "3.0.0" coreSplashscreenVersion = "1.2.0" +firebaseBomVersion = "34.11.0" hiltNavigationComposeVersion = "1.2.0" activityComposeVersion = "1.10.1" composeBom = "2026.03.00" coreKtx = "1.16.0" hiltAndroidCompilerVersion = "2.56.2" hiltAndroidVersion = "2.56.2" +googleServices = "4.4.4" +firebaseCrashlytics = "3.0.6" junit = "4.13.2" junitVersion = "1.2.1" espressoCore = "3.6.1" @@ -55,6 +58,9 @@ androidx-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } androidx-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" } androidx-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" } converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGsonVersion" } +firebase-analytics = { module = "com.google.firebase:firebase-analytics" } +firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBomVersion" } +firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics" } hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroidVersion" } hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroidCompilerVersion" } junit = { module = "junit:junit", version.ref = "junit" } @@ -83,4 +89,6 @@ kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", versi android-application = { id = "com.android.application", version.ref = "agpVersion" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlinVersion" } google-devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } -hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hiltAndroidVersion" } \ No newline at end of file +hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hiltAndroidVersion" } +google-services = { id = "com.google.gms.google-services", version.ref = "googleServices" } +firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebaseCrashlytics" } From a52ca2da7cf0da1a75fdc8248aaceb764d9378ed Mon Sep 17 00:00:00 2001 From: Marcello Date: Fri, 3 Apr 2026 11:19:37 +0200 Subject: [PATCH 3/4] Implement Crashlytics abstraction and Hilt module - Create `CrashlyticsManager` interface to abstract crash reporting operations, including breadcrumbs, non-fatal exceptions, and user context. - Implement `CrashlyticsManagerImpl` using the Firebase Crashlytics SDK. - Add `CrashlyticsManagerModule` to provide `CrashlyticsManager` as a singleton via Dagger/Hilt. --- .../common/crashlytics/CrashlyticsManager.kt | 23 +++++++++++++++++++ .../crashlytics/CrashlyticsManagerImpl.kt | 22 ++++++++++++++++++ .../crashlytics/CrashlyticsManagerModule.kt | 17 ++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 common/src/main/java/eu/project/common/crashlytics/CrashlyticsManager.kt create mode 100644 common/src/main/java/eu/project/common/crashlytics/CrashlyticsManagerImpl.kt create mode 100644 common/src/main/java/eu/project/common/crashlytics/CrashlyticsManagerModule.kt diff --git a/common/src/main/java/eu/project/common/crashlytics/CrashlyticsManager.kt b/common/src/main/java/eu/project/common/crashlytics/CrashlyticsManager.kt new file mode 100644 index 0000000..3b7f208 --- /dev/null +++ b/common/src/main/java/eu/project/common/crashlytics/CrashlyticsManager.kt @@ -0,0 +1,23 @@ +package eu.project.common.crashlytics + +/** + * Abstraction over the crash reporting SDK. + */ +interface CrashlyticsManager { + + /** + * Appends a message to the in-memory breadcrumb buffer. + */ + fun logBreadcrumb(message: String) + + /** + * Records a non-fatal exception and flushes the breadcrumb buffer + * into the report. + */ + fun recordException(throwable: Throwable, extras: Map = emptyMap()) + + /** + * Associates subsequent reports with a specific user. + */ + fun setUserContext(userId: String, email: String) +} \ No newline at end of file diff --git a/common/src/main/java/eu/project/common/crashlytics/CrashlyticsManagerImpl.kt b/common/src/main/java/eu/project/common/crashlytics/CrashlyticsManagerImpl.kt new file mode 100644 index 0000000..0bc03b2 --- /dev/null +++ b/common/src/main/java/eu/project/common/crashlytics/CrashlyticsManagerImpl.kt @@ -0,0 +1,22 @@ +package eu.project.common.crashlytics + +import com.google.firebase.crashlytics.FirebaseCrashlytics +import jakarta.inject.Inject + +class CrashlyticsManagerImpl @Inject constructor(): CrashlyticsManager { + + private val crashlytics = FirebaseCrashlytics.getInstance() + + override fun logBreadcrumb(message: String) { + crashlytics.log(message) + } + + override fun recordException(throwable: Throwable, extras: Map) { + extras.forEach { (k, v) -> crashlytics.setCustomKey(k, v) } + crashlytics.recordException(throwable) + } + + override fun setUserContext(userId: String, email: String) { + crashlytics.setUserId(userId) + } +} \ No newline at end of file diff --git a/common/src/main/java/eu/project/common/crashlytics/CrashlyticsManagerModule.kt b/common/src/main/java/eu/project/common/crashlytics/CrashlyticsManagerModule.kt new file mode 100644 index 0000000..4b4c3de --- /dev/null +++ b/common/src/main/java/eu/project/common/crashlytics/CrashlyticsManagerModule.kt @@ -0,0 +1,17 @@ +package eu.project.common.crashlytics + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +class CrashlyticsManagerModule { + + @Provides + @Singleton + fun provideCrashlyticsManager(): CrashlyticsManager = + CrashlyticsManagerImpl() +} \ No newline at end of file From 5a6c383f128344b669b5338d89b18e31f11a6e8e Mon Sep 17 00:00:00 2001 From: Marcello Date: Fri, 3 Apr 2026 12:12:17 +0200 Subject: [PATCH 4/4] Add step to write google-services.json in CI workflow - Create `app/google-services.json` using the `GOOGLE_SERVICES_JSON` secret during the CI process. --- .github/workflows/CI.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 69c5927..41123a1 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -17,6 +17,9 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + - name: Write google-services.json + run: echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > app/google-services.json + - name: Set up JDK 17 uses: actions/setup-java@v4 with: