Search code examples
androidfirebasefirebase-authenticationandroid-library

How to configure an Android library that uses Firebase to authenticate users to use google-services.json from an app that uses it?


I'm trying to implement an Android library that uses Firebase authentication to authenticate users. It consists of one class that looks like this:

class FirebaseRepository {

    fun signInWithUsernameAndPassword(username: String, password: String): Task<AuthResult> {
        return Firebase.auth
            .signInWithEmailAndPassword(username, password)
    }

}

I'm using this library in my app as follows:

fun signInWithUsernameAndPassword() {
    FirebaseRepository().signInWithUsernameAndPassword("bobapp@gmail.com", "bobapp")
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d("exampleapp", "signInWithEmail:success")
            } else {
                Log.w("exampleapp", "signInWithEmail:failure", task.exception)
            }
        }
}

When building the app I'm getting an error that google-services.json could not be found for auth library. I would not like to register my library in Firebase as a separate app, but instead I would like to use google-services.json file from the app. How can I do that?

Edit:

Here's the app's build.gradle file:

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'com.google.gms.google-services'
}

android {
    namespace 'com.example.exampleapp'
    compileSdk 33

    defaultConfig {
        applicationId "com.example.exampleapp"
        minSdk 24
        targetSdk 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary true
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        compose true
    }
    composeOptions {
        kotlinCompilerExtensionVersion '1.4.4'
    }
    packagingOptions {
        resources {
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
        }
    }
}

dependencies {

    implementation project(path: ':auth')
    implementation 'androidx.core:core-ktx:1.10.0'
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
    implementation 'androidx.activity:activity-compose:1.7.1'
    implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
    implementation 'androidx.compose.material3:material3:1.1.0-rc01'
    implementation 'androidx.core:core-ktx:1.10.0'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
    debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
    debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"

    implementation platform('com.google.firebase:firebase-bom:31.3.0')
    implementation 'com.google.firebase:firebase-analytics-ktx'

}

Here's the library's build.gradle file:

plugins {
    id 'com.android.library'
    id 'org.jetbrains.kotlin.android'
    id 'com.google.gms.google-services'
}

android {
    namespace 'com.example.auth'
    compileSdk 33

    defaultConfig {
        minSdk 24
        targetSdk 33

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.10.0'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.9.0'
    implementation project(path: ':apimanager')
    implementation 'androidx.core:core-ktx:1.10.0'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

    implementation platform('com.google.firebase:firebase-bom:32.0.0')
    implementation 'com.google.firebase:firebase-auth-ktx'
    implementation 'com.google.android.gms:play-services-auth:20.5.0'

}

Structure of the project is:

android/
  app/
  auth/

The error message that I'm getting when building the project:

Execution failed for task ':auth:processDebugGoogleServices'.
> No matching client found for package name 'com.example.auth'

But I've managed to find the solution:

  1. In build.gradle file of auth I need to change the namespace to be com.example.exampleapp.
  2. Add the google-services.json from the app into the auth.

Still is there some better way to solve this problem without the need to change the auth library every time it is used in a different app?


Solution

  • You can only apply Firebase configuration to the main app module of your app. You can't apply it to library modules.

    You should:

    • Remove the com.google.gms.google-services plugin from your library
    • Remove the google-services.json file from your library

    You can leave the Firebase dependencies, since they are required to compile your library, regardless of what the app module needs itself.

    Your library should absolutely not access any Firebase APIs until the after app module has fully initialized Firebase.