From fca640e98c1e8be0219a52aa668a703b7dd415f1 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 11 Aug 2023 14:03:35 +0200 Subject: [PATCH 01/10] ADD stubs for Crash logging --- README.MD | 2 + .../kotlin/nl/q42/template/MainApplication.kt | 8 ++++ .../template/logging/CrashlyticsAntilog.kt | 47 +++++++++++++++++++ .../navigation/viewmodel/RouteNavigator.kt | 4 +- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt diff --git a/README.MD b/README.MD index 2c265e2..4d2d27e 100644 --- a/README.MD +++ b/README.MD @@ -24,6 +24,8 @@ Only basic features that almost all projects use, were added in this template: 1. Run `python ./scripts/rename-project.py` or `python3 ./scripts/rename-project.py` from the project root, to change the project name and the package names. The script will ask for your new project name and update all references. +1. Some stubs have been added, which require eg. a Firebase project to be configured before they + can be used. Crashlytics, for example. Search the project for TODO comments to find them. ## Contributing diff --git a/app/src/main/kotlin/nl/q42/template/MainApplication.kt b/app/src/main/kotlin/nl/q42/template/MainApplication.kt index 591d885..23a96c6 100644 --- a/app/src/main/kotlin/nl/q42/template/MainApplication.kt +++ b/app/src/main/kotlin/nl/q42/template/MainApplication.kt @@ -4,6 +4,7 @@ import android.app.Application import dagger.hilt.android.HiltAndroidApp import io.github.aakira.napier.DebugAntilog import io.github.aakira.napier.Napier +import nl.q42.template.logging.CrashlyticsAntilog @HiltAndroidApp class MainApplication : Application() { @@ -13,6 +14,13 @@ class MainApplication : Application() { if (BuildConfig.DEBUG) { Napier.base(DebugAntilog()) + Napier.d { "TODO Disabling crashlytics for a debug build" } + // TODO FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(false) + + } else { + Napier.d { "TODO Enabling crashlytics for non-debug build" } + // TODO FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true) + Napier.base(CrashlyticsAntilog()) } } } diff --git a/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt new file mode 100644 index 0000000..a8384c4 --- /dev/null +++ b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt @@ -0,0 +1,47 @@ +package nl.q42.template.logging + +import io.github.aakira.napier.Antilog +import io.github.aakira.napier.DebugAntilog +import io.github.aakira.napier.LogLevel +import io.github.aakira.napier.Napier + +/** A value suitable for Crashlytics */ +private const val MAX_CHARS_IN_LOG = 1200 + +class CrashlyticsAntilog : Antilog() { + + private val logcatAntilog = DebugAntilog() + + override fun performLog( + priority: LogLevel, + tag: String?, + throwable: Throwable?, + message: String? + ) { + // also send to logcat + logcatAntilog.log(priority, tag, throwable, message) + + val limitedMessage = message?.take(MAX_CHARS_IN_LOG) // to avoid OutOfMemoryError's + + // TODO Add crashlytics to your project with this guide https://firebase.google.com/docs/crashlytics/get-started?platform=android + // and then remove this line and uncomment the others + Napier.d { "REPLACE_ME no crash logging handler installed. ${ limitedMessage ?: ""}" } + +// if ((priority == LogLevel.INFO || priority == LogLevel.DEBUG || priority == LogLevel.WARNING) && limitedMessage != null) { +// val errorMessage = throwable?.let { +// " with error: ${throwable}: ${throwable.message}".take(MAX_CHARS_IN_LOG) +// } ?: "" +// Firebase.crashlytics.log(limitedMessage + errorMessage) +// } +// +// if (priority < LogLevel.ERROR) { +// Firebase.crashlytics.log("recordException with message: $limitedMessage") +// Firebase.crashlytics.recordException(throwable ?: Exception(message)) +// } +// +// +// throwable?.let { +// FirebaseCrashlytics.getInstance().recordException(it) +// } + } +} diff --git a/core/navigation/src/main/kotlin/nl/q42/template/navigation/viewmodel/RouteNavigator.kt b/core/navigation/src/main/kotlin/nl/q42/template/navigation/viewmodel/RouteNavigator.kt index 57dc419..6f44bc5 100644 --- a/core/navigation/src/main/kotlin/nl/q42/template/navigation/viewmodel/RouteNavigator.kt +++ b/core/navigation/src/main/kotlin/nl/q42/template/navigation/viewmodel/RouteNavigator.kt @@ -2,6 +2,7 @@ package nl.q42.template.navigation.viewmodel import androidx.annotation.VisibleForTesting import com.ramcosta.composedestinations.spec.Direction +import io.github.aakira.napier.Napier import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -43,6 +44,7 @@ class MyRouteNavigator : RouteNavigator { @VisibleForTesting fun navigate(state: NavigationState) { + Napier.i { state.toString() } navigationState.value = state } -} \ No newline at end of file +} From 82d9737c4a6a05807c5c7983ad7c93f7d60d7b1d Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 1 Dec 2023 16:07:31 +0100 Subject: [PATCH 02/10] ADD Actual Crashlytics implementation --- .idea/gradle.xml | 3 +- .idea/migrations.xml | 10 ++++++ README.MD | 10 ++++-- app/build.gradle | 6 ++++ app/google-services.json | 29 +++++++++++++++ .../kotlin/nl/q42/template/MainApplication.kt | 8 ++--- .../template/logging/CrashlyticsAntilog.kt | 35 ++++++++----------- build.gradle | 2 ++ .../presentation/home/HomeViewModel.kt | 5 +++ gradle/libs.versions.toml | 8 +++++ 10 files changed, 86 insertions(+), 30 deletions(-) create mode 100644 .idea/migrations.xml create mode 100644 app/google-services.json diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 68d1124..a66ecf0 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,8 +4,6 @@ diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/README.MD b/README.MD index 4d2d27e..2cf39dc 100644 --- a/README.MD +++ b/README.MD @@ -24,8 +24,10 @@ Only basic features that almost all projects use, were added in this template: 1. Run `python ./scripts/rename-project.py` or `python3 ./scripts/rename-project.py` from the project root, to change the project name and the package names. The script will ask for your new project name and update all references. -1. Some stubs have been added, which require eg. a Firebase project to be configured before they - can be used. Crashlytics, for example. Search the project for TODO comments to find them. +1. Replace google-services.json with your own Firebase config file. + The template Firebase project can be found here: [Firebase project](https://console.firebase.google.com/u/0/project/template-android-799ab/overview) + Google Services currently in use: + - Crashlytics ## Contributing @@ -220,6 +222,10 @@ not included yet. We use Napier because it's usage is close to Timber/Tolbaaken, but Napier supports KMM. +We use Craslytics for crash reporting. Note that Google Analytics is added to enable more insight such as breadcrumbs and +crash-free percentage. If you don't want to use Google Analytics, you can remove it by simply removing the dependency. + + ### Image loading We did not include an image loading library is this template, because not every app might need it, diff --git a/app/build.gradle b/app/build.gradle index 4d9ccee..1cf4f56 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,5 +1,7 @@ plugins { id "com.android.application" + alias libs.plugins.googleServices + alias libs.plugins.firebaseCrashlyticsPlugin } apply from: "$rootDir/build.module.feature-and-app.gradle" @@ -48,4 +50,8 @@ dependencies { implementation(project(":data:user")) // needed for di implementation(project(":core:network")) // needed for di implementation(libs.composeDestinations) + + api platform(libs.firebaseBoM) + implementation(libs.firebaseCrashlytics) + implementation(libs.firebaseAnalytics) // additional metrics for craslytics https://firebase.google.com/docs/crashlytics/get-started?platform=android#before-you-begin } diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 0000000..867e981 --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "1076113435843", + "project_id": "template-android-799ab", + "storage_bucket": "template-android-799ab.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:1076113435843:android:e2916720b9c98936dc8676", + "android_client_info": { + "package_name": "nl.q42.template" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyDzfsJ_ycKoyci--w_M2hHwvsjk8-zKmzA" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/src/main/kotlin/nl/q42/template/MainApplication.kt b/app/src/main/kotlin/nl/q42/template/MainApplication.kt index 23a96c6..1eb1d5a 100644 --- a/app/src/main/kotlin/nl/q42/template/MainApplication.kt +++ b/app/src/main/kotlin/nl/q42/template/MainApplication.kt @@ -1,6 +1,7 @@ package nl.q42.template import android.app.Application +import com.google.firebase.crashlytics.FirebaseCrashlytics import dagger.hilt.android.HiltAndroidApp import io.github.aakira.napier.DebugAntilog import io.github.aakira.napier.Napier @@ -13,13 +14,10 @@ class MainApplication : Application() { super.onCreate() if (BuildConfig.DEBUG) { + FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(false) Napier.base(DebugAntilog()) - Napier.d { "TODO Disabling crashlytics for a debug build" } - // TODO FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(false) - } else { - Napier.d { "TODO Enabling crashlytics for non-debug build" } - // TODO FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true) + FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true) Napier.base(CrashlyticsAntilog()) } } diff --git a/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt index a8384c4..a896ea5 100644 --- a/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt +++ b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt @@ -1,9 +1,10 @@ package nl.q42.template.logging +import com.google.firebase.crashlytics.ktx.crashlytics +import com.google.firebase.ktx.Firebase import io.github.aakira.napier.Antilog import io.github.aakira.napier.DebugAntilog import io.github.aakira.napier.LogLevel -import io.github.aakira.napier.Napier /** A value suitable for Crashlytics */ private const val MAX_CHARS_IN_LOG = 1200 @@ -23,25 +24,17 @@ class CrashlyticsAntilog : Antilog() { val limitedMessage = message?.take(MAX_CHARS_IN_LOG) // to avoid OutOfMemoryError's - // TODO Add crashlytics to your project with this guide https://firebase.google.com/docs/crashlytics/get-started?platform=android - // and then remove this line and uncomment the others - Napier.d { "REPLACE_ME no crash logging handler installed. ${ limitedMessage ?: ""}" } - -// if ((priority == LogLevel.INFO || priority == LogLevel.DEBUG || priority == LogLevel.WARNING) && limitedMessage != null) { -// val errorMessage = throwable?.let { -// " with error: ${throwable}: ${throwable.message}".take(MAX_CHARS_IN_LOG) -// } ?: "" -// Firebase.crashlytics.log(limitedMessage + errorMessage) -// } -// -// if (priority < LogLevel.ERROR) { -// Firebase.crashlytics.log("recordException with message: $limitedMessage") -// Firebase.crashlytics.recordException(throwable ?: Exception(message)) -// } -// -// -// throwable?.let { -// FirebaseCrashlytics.getInstance().recordException(it) -// } + + if ((priority == LogLevel.INFO || priority == LogLevel.DEBUG || priority == LogLevel.WARNING) && limitedMessage != null) { + val errorMessage = throwable?.let { + " with error: ${throwable}: ${throwable.message}".take(MAX_CHARS_IN_LOG) + } ?: "" + Firebase.crashlytics.log(limitedMessage + errorMessage) + } + + if (priority == LogLevel.ERROR) { + Firebase.crashlytics.log("recordException with message: $limitedMessage") + Firebase.crashlytics.recordException(throwable ?: Exception(message)) + } } } diff --git a/build.gradle b/build.gradle index 10a2858..59cdf25 100644 --- a/build.gradle +++ b/build.gradle @@ -12,4 +12,6 @@ plugins { // sets class paths only (because of 'apply false') alias libs.plugins.jetbrainsKotlinAndroid apply false alias libs.plugins.hilt apply false alias libs.plugins.ksp apply false + alias libs.plugins.googleServices apply false + alias libs.plugins.firebaseCrashlyticsPlugin apply false } diff --git a/feature/home/src/main/kotlin/nl/q42/template/presentation/home/HomeViewModel.kt b/feature/home/src/main/kotlin/nl/q42/template/presentation/home/HomeViewModel.kt index 4608d5b..7865628 100644 --- a/feature/home/src/main/kotlin/nl/q42/template/presentation/home/HomeViewModel.kt +++ b/feature/home/src/main/kotlin/nl/q42/template/presentation/home/HomeViewModel.kt @@ -3,6 +3,7 @@ package nl.q42.template.presentation.home import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import io.github.aakira.napier.Napier import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update @@ -12,6 +13,7 @@ import nl.q42.template.domain.user.usecase.GetUserUseCase import nl.q42.template.navigation.AppGraphRoutes import nl.q42.template.navigation.viewmodel.RouteNavigator import nl.q42.template.ui.home.destinations.HomeSecondScreenDestination +import java.lang.RuntimeException import javax.inject.Inject @HiltViewModel @@ -48,6 +50,9 @@ class HomeViewModel @Inject constructor( } fun onOpenSecondScreenClicked() { + Napier.e(RuntimeException("Open Second Screen tapped. This will be shown as the non-fatal title")) { + "Open Second Screen Tapped. This will be shown in the Crashlytics breadcrumbs" + } navigateTo(HomeSecondScreenDestination(title = "Hello world!")) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d02cbba..197564d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,6 +5,9 @@ kotlinCompilerExtensionVersion = "1.4.4" jvmTarget = "17" kotlin = "1.8.10" gradlePlugin = "8.0.0-rc01" +googleServices = "4.4.0" +crashlyticsPlugin = "2.9.9" +firebaseBOM = "32.6.0" manesVersions = "0.44.0" littleRobotsCatalogUpdates = "0.7.0" hilt = "2.45" @@ -41,6 +44,9 @@ composeUITooling = { module = "androidx.compose.ui:ui-tooling" } composeUIToolingPreview = { module = "androidx.compose.ui:ui-tooling-preview" } composeMaterial3 = { module = "androidx.compose.material3:material3" } composePlatform = { module = "androidx.compose:compose-bom", version.ref = "composePlatform" } +firebaseBoM = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBOM" } +firebaseCrashlytics = { module = "com.google.firebase:firebase-crashlytics-ktx" } +firebaseAnalytics = { module = "com.google.firebase:firebase-analytics-ktx" } activityCompose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" } hiltNavigationCompose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" } composeLifecycle = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "composeLifecycle" } @@ -54,3 +60,5 @@ manesVersions = { id = "com-github-ben-manes-versions", version.ref = "manesVers littleRobotsCatalogUpdates = { id = "nl.littlerobots.version-catalog-update", version.ref = "littleRobotsCatalogUpdates" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +googleServices = { id = "com.google.gms.google-services", version.ref = "googleServices" } +firebaseCrashlyticsPlugin = { id = "com.google.firebase.crashlytics", version.ref = "crashlyticsPlugin" } From 104c87ecc629f514ea59460b022a8326e1eadfc8 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 1 Dec 2023 16:12:02 +0100 Subject: [PATCH 03/10] ADD Warning to replace google-services.json --- .../main/kotlin/nl/q42/template/ui/home/HomeContent.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/feature/home/src/main/kotlin/nl/q42/template/ui/home/HomeContent.kt b/feature/home/src/main/kotlin/nl/q42/template/ui/home/HomeContent.kt index 0d3aba9..c0340be 100644 --- a/feature/home/src/main/kotlin/nl/q42/template/ui/home/HomeContent.kt +++ b/feature/home/src/main/kotlin/nl/q42/template/ui/home/HomeContent.kt @@ -2,12 +2,15 @@ package nl.q42.template.ui.home import androidx.compose.foundation.layout.Arrangement.Center import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import nl.q42.template.presentation.home.HomeViewState import nl.q42.template.ui.theme.PreviewAppTheme import nl.q42.template.ui.theme.PreviewLightDark @@ -47,6 +50,10 @@ internal fun HomeContent( Button(onClick = onOpenOnboardingClicked) { Text("Open onboarding") } + + Spacer(modifier = Modifier.height(32.dp)) + + Text(text = "NOTE: when cloning this template, set up your own Firebase project and replace google-services.json") } } @@ -80,4 +87,4 @@ private fun HomeContentDataPreview() { PreviewAppTheme { HomeContent(HomeViewState.Data("preview@preview.com"), {}, {}, {}) } -} \ No newline at end of file +} From b49a9793ad7bdb43de36e72473d9e8b8ddbb3dc0 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 15 Dec 2023 14:59:15 +0100 Subject: [PATCH 04/10] ADD dev app to google-services.json --- app/google-services.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/app/google-services.json b/app/google-services.json index 867e981..30130e7 100644 --- a/app/google-services.json +++ b/app/google-services.json @@ -23,6 +23,25 @@ "other_platform_oauth_client": [] } } + }, + { + "client_info": { + "mobilesdk_app_id": "1:1076113435843:android:72065788817f0133dc8676", + "android_client_info": { + "package_name": "nl.q42.template.dev" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyDzfsJ_ycKoyci--w_M2hHwvsjk8-zKmzA" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } } ], "configuration_version": "1" From bfa838200ba4c5c6583a27c792ed5743f9156148 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 15 Dec 2023 16:11:48 +0100 Subject: [PATCH 05/10] CHANGE FirebaseBOm to 32.7.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 216f801..ea1cbaf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ kotlin = "1.9.21" gradlePlugin = "8.2.0" googleServices = "4.4.0" crashlyticsPlugin = "2.9.9" -firebaseBOM = "32.6.0" +firebaseBOM = "32.7.0" manesVersions = "0.44.0" littleRobotsCatalogUpdates = "0.8.1" hilt = "2.49" From 94716584703936a0d9bc8f4c8e218338d1327a1b Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 15 Dec 2023 17:06:56 +0100 Subject: [PATCH 06/10] REMOVE Google Analytics dependency because it might not be GDPR compliant This allows reverse proxies like Charles to inspect and manipulate traffic in development builds --- .idea/git_toolbox_prj.xml | 15 +++++++++++++++ README.MD | 6 ++++-- app/build.gradle | 1 - gradle/libs.versions.toml | 1 - 4 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 .idea/git_toolbox_prj.xml diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/README.MD b/README.MD index bf476aa..a3aa318 100644 --- a/README.MD +++ b/README.MD @@ -247,8 +247,10 @@ not included yet. We use Napier because it's usage is close to Timber/Tolbaaken, but Napier supports KMM. -We use Craslytics for crash reporting. Note that Google Analytics is added to enable more insight such as breadcrumbs and -crash-free percentage. If you don't want to use Google Analytics, you can remove it by simply removing the dependency. +We use Crashlytics for crash reporting. Note that Google Analytics is not added. Google [recommends] +(https://firebase.google.com/docs/crashlytics/get-started?platform=android#before-you-begin) +to enable it for more insight such as breadcrumbs and crash-free percentage. +If you don't want to use Google Analytics, you can remove it by simply removing the dependency. ### Image loading diff --git a/app/build.gradle b/app/build.gradle index 9e9e429..0007773 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -68,5 +68,4 @@ dependencies { api platform(libs.firebaseBoM) implementation(libs.firebaseCrashlytics) - implementation(libs.firebaseAnalytics) // additional metrics for craslytics https://firebase.google.com/docs/crashlytics/get-started?platform=android#before-you-begin } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ea1cbaf..161ae95 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,6 @@ composeMaterial3 = { module = "androidx.compose.material3:material3" } composePlatform = { module = "androidx.compose:compose-bom", version.ref = "composePlatform" } firebaseBoM = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBOM" } firebaseCrashlytics = { module = "com.google.firebase:firebase-crashlytics-ktx" } -firebaseAnalytics = { module = "com.google.firebase:firebase-analytics-ktx" } activityCompose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" } hiltNavigationCompose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" } composeLifecycle = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "composeLifecycle" } From f126cf17da12eefaeaa0b20932cd0d2e6fd7e6e5 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 23 Feb 2024 16:57:56 +0100 Subject: [PATCH 07/10] CHANGE don't send DEBUG or VERBOSE messages to logcat for release builds crash-logging --- .../q42/template/logging/CrashlyticsAntilog.kt | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt index a896ea5..eb3b424 100644 --- a/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt +++ b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt @@ -5,10 +5,17 @@ import com.google.firebase.ktx.Firebase import io.github.aakira.napier.Antilog import io.github.aakira.napier.DebugAntilog import io.github.aakira.napier.LogLevel +import nl.q42.template.BuildConfig -/** A value suitable for Crashlytics */ +/** A value suitable for Crashlytics + * This value is used to truncate the user-defined message and the exception message + * In theory, the message sent to Crashlytics could therefore be 2x this value + */ private const val MAX_CHARS_IN_LOG = 1200 +/** A Crashlytics logger. The name Antilog might be an unfortunate choice by the Napier library; + * this is not a stub + */ class CrashlyticsAntilog : Antilog() { private val logcatAntilog = DebugAntilog() @@ -19,12 +26,13 @@ class CrashlyticsAntilog : Antilog() { throwable: Throwable?, message: String? ) { - // also send to logcat - logcatAntilog.log(priority, tag, throwable, message) + if (BuildConfig.DEBUG || priority > LogLevel.DEBUG) { + // also send to logcat + logcatAntilog.log(priority, tag, throwable, message) + } val limitedMessage = message?.take(MAX_CHARS_IN_LOG) // to avoid OutOfMemoryError's - if ((priority == LogLevel.INFO || priority == LogLevel.DEBUG || priority == LogLevel.WARNING) && limitedMessage != null) { val errorMessage = throwable?.let { " with error: ${throwable}: ${throwable.message}".take(MAX_CHARS_IN_LOG) From 8d2b25f62a3e14657a6323f4074cd3f6d0d7c5a2 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 23 Feb 2024 17:08:52 +0100 Subject: [PATCH 08/10] PR feedback 2 crash-logging --- .../nl/q42/template/logging/CrashlyticsAntilog.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt index eb3b424..f9301eb 100644 --- a/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt +++ b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt @@ -26,21 +26,22 @@ class CrashlyticsAntilog : Antilog() { throwable: Throwable?, message: String? ) { + if (message == null && throwable == null) return + if (BuildConfig.DEBUG || priority > LogLevel.DEBUG) { // also send to logcat logcatAntilog.log(priority, tag, throwable, message) } - val limitedMessage = message?.take(MAX_CHARS_IN_LOG) // to avoid OutOfMemoryError's + val limitedMessage = message?.take(MAX_CHARS_IN_LOG) ?: "(no message)" // to avoid OutOfMemoryError's - if ((priority == LogLevel.INFO || priority == LogLevel.DEBUG || priority == LogLevel.WARNING) && limitedMessage != null) { + if (priority < LogLevel.ERROR) { + // at least one of message or throwable is not null val errorMessage = throwable?.let { " with error: ${throwable}: ${throwable.message}".take(MAX_CHARS_IN_LOG) } ?: "" Firebase.crashlytics.log(limitedMessage + errorMessage) - } - - if (priority == LogLevel.ERROR) { + } else { Firebase.crashlytics.log("recordException with message: $limitedMessage") Firebase.crashlytics.recordException(throwable ?: Exception(message)) } From 9deb4561b04376b82d25db31fd137421e0971416 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Thu, 7 Mar 2024 10:09:00 +0100 Subject: [PATCH 09/10] RENAME CrashlyticsAntilog to CrashlyticsLogger crash-logging --- app/src/main/kotlin/nl/q42/template/MainApplication.kt | 4 ++-- .../logging/{CrashlyticsAntilog.kt => CrashlyticsLogger.kt} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename app/src/main/kotlin/nl/q42/template/logging/{CrashlyticsAntilog.kt => CrashlyticsLogger.kt} (97%) diff --git a/app/src/main/kotlin/nl/q42/template/MainApplication.kt b/app/src/main/kotlin/nl/q42/template/MainApplication.kt index e0c308b..c2005c8 100644 --- a/app/src/main/kotlin/nl/q42/template/MainApplication.kt +++ b/app/src/main/kotlin/nl/q42/template/MainApplication.kt @@ -6,7 +6,7 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics import dagger.hilt.android.HiltAndroidApp import io.github.aakira.napier.DebugAntilog import io.github.aakira.napier.Napier -import nl.q42.template.logging.CrashlyticsAntilog +import nl.q42.template.logging.CrashlyticsLogger @HiltAndroidApp class MainApplication : Application() { @@ -28,7 +28,7 @@ class MainApplication : Application() { ) } else { FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true) - Napier.base(CrashlyticsAntilog()) + Napier.base(CrashlyticsLogger()) } } } diff --git a/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsLogger.kt similarity index 97% rename from app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt rename to app/src/main/kotlin/nl/q42/template/logging/CrashlyticsLogger.kt index f9301eb..efc0fc6 100644 --- a/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsAntilog.kt +++ b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsLogger.kt @@ -16,7 +16,7 @@ private const val MAX_CHARS_IN_LOG = 1200 /** A Crashlytics logger. The name Antilog might be an unfortunate choice by the Napier library; * this is not a stub */ -class CrashlyticsAntilog : Antilog() { +class CrashlyticsLogger : Antilog() { private val logcatAntilog = DebugAntilog() From 191ba61cfe6785fcb8204dec07bf3b0ba189ac20 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 5 Apr 2024 16:20:35 +0200 Subject: [PATCH 10/10] RENAME logcatAntilog to logcatLogger crash-logging --- .../main/kotlin/nl/q42/template/logging/CrashlyticsLogger.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsLogger.kt b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsLogger.kt index efc0fc6..4e24de5 100644 --- a/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsLogger.kt +++ b/app/src/main/kotlin/nl/q42/template/logging/CrashlyticsLogger.kt @@ -18,7 +18,7 @@ private const val MAX_CHARS_IN_LOG = 1200 */ class CrashlyticsLogger : Antilog() { - private val logcatAntilog = DebugAntilog() + private val logcatLogger = DebugAntilog() override fun performLog( priority: LogLevel, @@ -30,7 +30,7 @@ class CrashlyticsLogger : Antilog() { if (BuildConfig.DEBUG || priority > LogLevel.DEBUG) { // also send to logcat - logcatAntilog.log(priority, tag, throwable, message) + logcatLogger.log(priority, tag, throwable, message) } val limitedMessage = message?.take(MAX_CHARS_IN_LOG) ?: "(no message)" // to avoid OutOfMemoryError's