7

I have a multi-module multi-flavor android project, the modules are as follows:

  1. core module, which is an android library that holds common stuff, including library dependencies.
  2. authentication module, which is as the name suggests, a module that contains a bunch of UI activities and is responsible for authenticating users. It's also the module that has the launcher activity.
  3. user module, which is another android library module. It is responsible for handling user profile UI, user data, along with Firebase database. But it also has to deal with Firebase authentication to get the Uid as it's used as key in the database.
  4. Other modules that are irrelevant right now

The module core does nothing with respect to Firebase, except just include it as a dependency for other modules. So I have this in my project build.gradle:

dependencies {
    classpath 'com.android.tools.build:gradle:3.2.0'
    classpath 'com.google.gms:google-services:4.1.0'
}

and I also have this in my core build.gradle:

apply plugin: 'com.android.library'
apply plugin: 'com.google.gms.google-services'

android {
    compileSdkVersion 28
    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        otherstuff
    }
    otherStuff
}

dependencies {
    otherStuff
    api 'com.google.android.gms:play-services-base:16.1.0'
    api 'com.google.firebase:firebase-core:16.0.6'
    api 'com.google.firebase:firebase-auth:16.1.0'
    api 'com.google.firebase:firebase-database:16.0.6'
    api 'com.google.firebase:firebase-storage:16.0.5'
    api 'com.hbb20:ccp:2.2.3'
    api 'com.google.android.libraries.places:places:1.0.0'
}

The user module does nothing except import the core library, and use authentication right away. So I have the following in my user build.gradle:

dependencies {
    otherStuff
    implementation project(':core')
}

and then I proceed to use it in my classes like so:

FirebaseAuth auth = FirebaseAuth.getInstance();

boolean isLoggedIn()
{
    assert(auth != null);
    return (auth.getCurrentUser() != null);
}

void uploadUserImpl()
{
    assert(isLoggedIn());
    db.getReference("users").child(auth.getCurrentUser().getUid()).setValue(this);
}

etc

The authentication module is the one that defines the app name, the launcher activity, etc. So, in my mind at least, it's also the one that should have the google-services.json file. So it has it under the authentication folder.

It includes both core and user libraries, so in my authentication build.gradle I have the following:

dependencies {
    otherStuff
    implementation project(':core')
    implementation project(':user')
}

It also proceeds to use Firebase authentication for logging in and signing up users.

Now with the problem:

trying to build the project, I get the following error:

File google-services.json is missing. The Google Services Plugin cannot function without it. 
 Searched Location: 
/work/mewais/CompanyName/ProjectName/core/src/FlavorName/debug/google-services.json
/work/mewais/CompanyName/ProjectName/core/google-services.json

and if I try to copy the google-services.json under core too, I get the following error:

No matching client found for package name 'com.companyname.projectname.core'

the google-services.json file has the app name defined inside it as:

"package_name": "com.companyname.projectname.appname"

which obviously expects the app name and not core.

So how to include Firebase in this setting? I want to keep the firebase dependencies defined inside core because multiple modules will use it. At the same time, authentication is the one that actually defines the appname and is also the one that has the launcher activity in which I start to use Firebase. I also expect user and any other modules to be able to use Firebase after that. It doesn't make sense to me to register all modules with Firebase (not even sure if it's possible since Firebase expects an app not a library?!). So is there anyway to fix this issue?

mewais
  • 1,265
  • 3
  • 25
  • 42

2 Answers2

4

I managed to wrap firebase dependencies into a library module without polluting the main module. Here is what I did:

google-play-services plugin requires the module that includes it to have applicationId and its JSON file(or it won't compile).

If you're sure you don't use special functions that google-play-services plugin provides, you can delete them.

https://developers.google.com/android/guides/google-services-plugin

Then you can follow this article's instructions:

https://medium.com/@samstern_58566/how-to-use-firebase-on-android-without-the-google-services-plugin-93ecc7dc6c4

Update: Another Link

https://firebase.google.com/docs/projects/multiprojects#support_multiple_environments_in_your_android_application

Because this provider is just reading resources with known names, another option is to add the string resources directly to your app instead of using the Google Services gradle plugin.

Dewey Reed
  • 4,353
  • 2
  • 27
  • 41
0

you may put a google-services.json file in flavor accoding to use:-

check this link

android {
 // set build flavor here to get the right gcm configuration.
    //def myFlavor = "flavor1"
    def myFlavor = "flavor2"

    if (myFlavor.equals("flavor1")) {
        println "--> flavor1 copy!"
        copy {
            from 'src/flavor1/'
            include '*.json'
            into '.'
        }
    } else {
        println "--> flavor2 copy!"
        copy {
            from 'src/flavor2/'
            include '*.json'
            into '.'
        }
    }

    // other stuff
    }
Ashwani kumar
  • 164
  • 15
  • The flavor was not the problem. It's the modules that were causing this. Dewey Reed's answer solved it for me. – mewais Feb 02 '19 at 01:58