google-services.json for different productFlavors

154,108

Solution 1

Google included support for flavors in version 2.0 of the play services plugin. Since this version of the gradle plugin com.google.gms:google-services:2.0.0-alpha3

you can do this

Step 1: add to gradle

// To auto-generate google map api key of google-services.json
implementation 'com.google.android.gms:play-services-maps:17.0.0'

Step 2: add to AndroidManifest.xml in the application tag

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="@string/google_api_key" />

Step 3: download each flavor JSON file from firebase and add it

app/src/
    flavor1/google-services.json
    flavor2/google-services.json

Version 3.0.0 of the plugin searches for the JSON file in these locations (considering you have a flavor flavor1 and a build type debug):

/app/src/debug/google-services.json
/app/src/debug/flavor1/google-services.json
/app/google-services.json

This worked for me even using flavorDimensions. I have free & paid in one dimension and Mock & Prod in the other dimension. I also have 3 buildTypes: debug, release, and staging. This is how it looks in my project for the FreeProd flavor:

enter image description here

How many google-services.json files will depend on your project's characteristics, but you will need at least one JSON file for every Google project.

If you want more details about what this plugin does with these JSON files, here it is: https://github.com/googlesamples/google-services/issues/54#issuecomment-165824720

Link to the official docs: https://developers.google.com/android/guides/google-services-plugin

Blog post with updated info: https://firebase.googleblog.com/2016/08/organizing-your-firebase-enabled-android-app-builds.html

And go here to check the latest version of this plugin: https://mvnrepository.com/artifact/com.google.gms/google-services?repo=google

Solution 2

UPDATE: The following explanation is for one Android Studio project, with one Firebase Project and different Firebase Apps inside that project. If the aim is to have different JSON files for different Firebase Apps in different Firebase Projects inside the same Android Studio project, (or if you don't know what's the difference) look here..

You need one Firebase App per Android Application ID (usually package name). Is common to have one Application ID per Gradle build variant (This is gonna be likely if you use Gradle build types and Gradle build flavours)


As of Google Services 3.0 and using Firebase it's not necessary to create different files for different flavours. Creating different files for different flavours can be not clear or straightforward in case you have productFlavours and Build types which compose with each other.

In the same file you'll have the all the configurations you need for all your build types and flavours.

In the Firebase console you need to add one app per package name. Imagine that you have 2 flavours (dev and live) and 2 build types (debug and release). Depending on your config but it's likely that you have 4 different package names like:

  • com.stackoverflow.example (live - release)
  • com.stackoverflow.example.dev (live - dev)
  • com.stackoverflow.example.debug (debug - release)
  • com.stackoverflow.example.dev.debug (debug - dev)

You need 4 different Android Apps in the Firebase Console. (On each one you need to add the SHA-1 for debug and live for each computer you are using)

When you download the google-services.json file, actually it doesn't really matter from what app you download it, all of them contain the same info related to all your apps.

Now you need to locate this file in app level (app/).

enter image description here

If you open that file you'll see that if contains all the information for all your package names.

A pain point use to be the plugin. In order to get it working you need to locate the plugin at the bottom of your file. So this line..

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

...needs to be on the bottom of your app build.gradle file.

For most of the said here, it applies to previous versions as well. I've never had different files for different configs, but now with the Firebase console is easier because they provide one single file with everything you need for all you configs.

Solution 3

Wrote a Medium post on this issue.

Had the a similar problem (using BuildTypes instead of Flavors), and fixed it like so.

Take advantage of Gradle's dependency management system. I created two tasks, switchToDebug and switchToRelease. Require that any time assembleRelease is run, that switchToRelease is also run. Same for debug.

def appModuleRootFolder = '.'
def srcDir = 'src'
def googleServicesJson = 'google-services.json'

task switchToDebug(type: Copy) {
    def buildType = 'debug'
    description = 'Switches to DEBUG google-services.json'
    from "${srcDir}/${buildType}"
    include "$googleServicesJson"
    into "$appModuleRootFolder"
}

task switchToRelease(type: Copy) {
    def buildType = 'release'
    description = 'Switches to RELEASE google-services.json'
    from "${srcDir}/${buildType}/"
    include "$googleServicesJson"
    into "$appModuleRootFolder"
}

afterEvaluate {
    processDebugGoogleServices.dependsOn switchToDebug
    processReleaseGoogleServices.dependsOn switchToRelease
}

EDIT: use processDebugFlavorGoogleServices/processReleaseFlavorGoogleServices task to modify it at a per-flavor level.

Solution 4

According to ahmed_khan_89's answer, you can put you "copy code" inside product flavors.

productFlavors {
    staging {
        applicationId = "com.demo.staging"

        println "Using Staging google-service.json"
        copy {
            from 'src/staging/'
            include '*.json'
            into '.'
        }
    }
    production {
        applicationId = "com.demo.production"

        println "Using Production google-service.json"
        copy {
            from 'src/production/'
            include '*.json'
            into '.'
        }
    }
}

Then you don't have to switch settings manually.

Solution 5

Well I am running into the same problem and couldn't get any perfect solution. It's just a workaround. I am wondering how Google didn't think about flavors...? And i hope they will propose soon a better solution.

What I am doing:

I have two flavors, in each one I put the corresponding google-services.json : src/flavor1/google-services.json and src/flavor2/google-services.json .

Then in build gradle I copy the file depending on the flavor to the app/ directory:

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
}

Limitation: you will have to change myFlavor manually in gradle each time you want to run for a different flavor (because it's hardcoded).

I tried many ways to get the current build flavor like afterEvaluate close... couldn't get any better solution until now.

Update, Another solution: one google-services.json for all the flavors:

You can also, have different package names for each flavor and then in the google developer console you don't have to create two different apps for each flavor, but just two different clients in the same app. Then you will have only one google-services.json that contains your both clients. Of course, this depends on how you're implementing the backend of your flavors. If they're not separated then this solution will not help you.

Share:
154,108
gentra
Author by

gentra

I'm a technical guy. My first startup's app, Vocalita, has winned Merit Award in INAICTA 2013, a runner up in Samsung Developer Competition 2013, and second winner in Believe National Research. My technological background is on mobile technology, mostly on Android Development. But I also love doing web development project using Laravel. Or even trying new things such as Node.JS, ReactiveX paradigm, etc. I manage my software development team using Scrum Methodology.

Updated on August 21, 2022

Comments

  • gentra
    gentra over 1 year

    Update: GCM is deprecated, use FCM

    I'm implementing the new Google Cloud Messaging following the guides from the Google Developers page here

    I've successfully run and test it. But my problem now is I have different product flavors with different applicationId/packageName and different Google Cloud Messaging Project Id. The google-services.json have to be put at the /app/google-services.json not the flavors folder.

    Is there any way to make the google-services.json config different for many flavors?