Search code examples
androidfirebasecrashlyticsmulti-module

How to add Firebase Crashlytics in kotlin-only module?


I have a multi-module Android project. The Modules are: "app", "core", "auth", "coreAndroid", and various feature modules. I am trying to add Firebase Crashlytics to the "core" module that is kotlin-only, so that I can create a function like:

fun cLog(msg: String?){
     FirebaseCrashlytics.getInstance().log(msg)
}

which will be accessed by all kotlin-only modules (like networking) to log error messages.

I have followed the official documentation but I can get the FirebaseCrashlytics Instance only in Android Modules. The google-services.json file is in the "app" module. I have been trying various solutions from the web for 3 days now but nothing seems to work.

The way that I have structured my gradle files is that I have an android-library-build.gradle and a library-build.gradle file, each of which act as a common ground for for their respective android and kotlin-only modules.

These are my gradle files:

(app) build.gradle.kts

plugins {
    id("com.android.application")
    kotlin("android")
    kotlin("plugin.serialization") version Kotlin.version //"1.6.10"
    kotlin("kapt")
    id ("com.google.firebase.crashlytics")
    id ("com.google.gms.google-services")
}

...

dependencies {
...

    implementation (platform("com.google.firebase:firebase-bom:31.2.0"))
    implementation ("com.google.firebase:firebase-analytics-ktx")
    implementation ("com.google.firebase:firebase-crashlytics-ktx")
}

(project) build.gradle.kts

buildscript {
    val kotlin_version by extra("1.8.0")
    repositories {
        gradlePluginPortal()
        google()
        mavenCentral()
    }

    dependencies {
        ...

        // Dependency for the Google services Gradle plugin
        classpath("com.google.gms:google-services:4.3.15")

        // Dependency for the Crashlytics Gradle plugin
        classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.4")

    }
}

android-library-build.gradle

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'androidx.navigation.safeargs.kotlin'

...

dependencies {
...

    implementation (platform("com.google.firebase:firebase-bom:31.2.0"))
    implementation ("com.google.firebase:firebase-analytics-ktx")
    implementation ("com.google.firebase:firebase-crashlytics-ktx")
}

library-build.gradle

apply plugin: 'java-library'
apply plugin: 'org.jetbrains.kotlin.jvm'


dependencies{

...
    implementation (platform("com.google.firebase:firebase-bom:31.2.0"))
    implementation ("com.google.firebase:firebase-analytics-ktx")
    implementation ("com.google.firebase:firebase-crashlytics-ktx")
}

apply {
    plugin("com.google.firebase.crashlytics")
    plugin("com.google.gms.google-services")
}

(core) build.gradle.kts

apply {
    from("$rootDir/library-build.gradle")
}

plugins {
    kotlin(KotlinPlugins.serialization) version Kotlin.version
}



dependencies {
    ...
}

I have also tried:

  • to implement directly the dependencies and the plugins in the core build.gradle.kts file without success (with the platform implementation, and with the separate dependencies implementation).
  • to copy/paste the google-services.gson file in the core module
  • to use Firebase on Android without the google-services plugin meaning that I copy/pasted the generated strings from app/build/generated/res/google-services/debug/main/values/values.xml to the strings.xml file of app module, and deleted the gson file with the relevant plugins, and still didn't work.

I really can't figure it out. Any help would be deeply appreciated.


Solution

  • After the comments of @CommonsWare, it seems that its not possible to use directly the crashlytics library in a kotlin-only module.

    I have found another way using an Interface in the koltin-only "core" module, and its implementation in the "app" module that has access to the crashlytics libraries.

    Here is a simple example:

    "core" module:

    interface CrashlyticsService {
        fun cLog(message: String?)
    }
    

    "app" module:

    class FirebaseCrashlyticsService : CrashlyticsService {
    
        override fun cLog(message: String?){
            message?.let {
                    FirebaseCrashlytics.getInstance().log(it)
                }
        }
    
    }
    

    And then, wherever I want to use the cLog function in other modules that depend on "core" i just inject it in the constructor of the Class, i.e. :

    class NetworkingServiceImpl(
        private val httpClient: HttpClient,
        private val crashlyticsService: CrashlyticsService
    ) : NetworkingService {
    
    
        override suspend fun downloadVideo(videoUrl: String): ByteArray {
            crashlyticsService.cLog("This is a crash test message")
            return httpClient.get(videoUrl).body()
        }
    
    }