google-services.json for different productFlavors
Asked Answered
Z

29

576

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?

Zeniazenith answered 11/6, 2015 at 5:23 Comment(6)
For Maven, we've implemented something similar using maven profiles and separate property files for every profileOvariotomy
if you just want you use the sender_id then generate key without any package name from google console.Drisko
The line apply plugin: 'com.google.gms.google-services' in gradle file seems to put gcm strings into app/build/generated/res/google-services/debug/values/values.xml...Barmaid
The best answer I've found for this is on this questionMauer
Be sure to read this: firebase.googleblog.com/2016/08/… It covers every possibility and tradeoffs.Punjabi
Answer ive found so far, https://mcmap.net/q/66140/-changing-the-searched-location-for-google-services-json-using-complex-flavour-treeCookgeneral
E
600

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

Eosinophil answered 18/12, 2015 at 21:42 Comment(21)
Works like a charm. This answer should be upvoted to reach the top as most developers will soon be using google-services > 2.0.0-alpha3.Herthahertz
Make sure to edit the .json file and add the flavor identified to the "package_name" field.Monet
where to put "com.google.gms:google-services:2.0.0-alpha3"?Ferrous
see here: #30527869Eosinophil
do you update just just the client_info or all the elements where package_name appears?Walkerwalkietalkie
This isn't working for me for some reason - I get a gradle build error- File google-services.json is missing from module root folder. The Google Services Plugin cannot function without it. so I'm going to resort to copying the flavor file into the root folder every time via a build script.Zloty
Worked like a charm, thank god for this. google-services.json and this whole new way of using their apis seems like a step backwards. Don't know how this is supposed to be easier.Cupriferous
googl-services.json is an abomination... how is managing some crazy json file easier than just plugging in an API key and sender ID? Please google stop the nonsenseBessiebessy
@Zloty I have he same message, did you managed to solve the problem ?Juncture
@RenaudFavier yes I did solve it by adding a build config field in the app build.gradle file as documented by the answer below https://mcmap.net/q/65007/-google-services-json-for-different-productflavors by divonas.Zloty
The newest version of the configuration file generator puts multiple properties in the same config file, only needing one at the app level again, instead of separate ones at the flavor level. You just need to make sure both configurations are generated under the same "App Name" field.Ergosterol
@runfaj, i have done according to you but i am getting error Error:Execution failed for task ':app:processClientDebugGoogleServices'. > No matching client found for package name 'cl.dropcp.client.debug'Rudnick
As of Android Studio 3.1.4, using /app/src/flavor1/google-services.json no longer works. The files must be located in /app/src/flavor1/debug/google-services.json and /app/src/flavor1/release/google-services.json.Lona
As of Oct 4 '19, this DOES still work, but a slight alteration is needed. Based on the documentation here: firebase.google.com/docs/projects/…: 1. Remove the references to the google-services plugin from the build.gradle files. 2. Use the following tool to convert your google-services.json to xml format and then store that xml file in a res>values folder for any flavors that need firebase. firebase.google.com/docs/projects/…Albuminous
Now is possible to use string resources instead of google-services.json https://mcmap.net/q/65007/-google-services-json-for-different-productflavorsSamekh
Now the plugin search the json file for these locations: /app/src/flavor1/google-services.json /app/src/debug/google-services.json /app/src/flavor1Debug/google-services.json /app/src/flavor1/debug/google-services.json /app/src/debug/flavor1/google-services.json /app/google-services.json PS: gradle version is 3.5+Spancel
It looks that it works only if a product flavor name uses all lowercase symbols and its corresponding Source Set too, and it also matches directory name (no 'setRoot' overrides). Only then those directories are included in a search list!Tattoo
@AntonBreusov Do you think that behavior might have changed? I'm here because a configuration that worked 30 days ago doesn't anymore. My flavor name is camelCase.Soinski
@HélèneMartin I don't know. Previously I used PascalCase names for flavor names, so it never worked for me at all, I used "copy file to project root" technique described in other answers. Until recently I decided to fix a project and renamed to "all lowercase". So, you may try it as an experiment. If plugin fails lookup o a file it prints all paths that it tried. Your flavor directories must be there. So,you can try to remove all "google-services.json" files and check what directories it's searching.Tattoo
Thanks for the ideas, @AntonBreusov. It turns out my issue was caused by github.com/google/play-services-plugins/issues/163 and I was able to revert google-services to 4.3.3 to get the desired behavior.Soinski
this worked for me, although I had to add copy { from 'src/flavor1/src' include '.json' into '.' } copy { from 'src/flavor2/src' include '.json' into '.' }Cropland
S
100

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.

Surname answered 20/7, 2016 at 10:48 Comment(9)
I generate mine from developers.google.com/mobile/add and there is only one opportunity to put in one package name. Where is the Firebase place to set this up, or what does a google-services.json file look like with multiple flavorsSerous
@Serous I've update the answer adding some links. You can check out the Firebase documentation and you can generate the JSON file in the Firebase console as described in the answer.Surname
This is a really good answer and it should be the only right answer for this question.Weigh
I discovered this myself when I ran into the very same problem, just as you described it above. I came here to submit an answer for posterity only to find you have already done it. With version 3.0.0, this is certainly the best answer.Tonguelash
I've the exact problem and thank you for great answer! Now, I have question. What If I want to have two Firebase Projects, one for live and one for other build types/flavor. Where should I put two google-services.json files ?Pulverable
This may help too: medium.com/@Miqubel/…Shultz
Can have google-services.json per Build variant not flavor?Playbook
Note that this only works if all your flavors are within the same firebase project. If using multiple projects (I tend to keep dev and stage in one firebase project and prod in a separate dedicated prod projet in a different google account), you need the solution outlined by Yair Kukielka. Actually the plugin appears to support a variety of paths - during build you'll get a hint about where the plugin went looking for the google-services.json file: "Could not find google-services.json while looking in [src/prod/debug, src/debug/prod, src/prod, src/debug, src/prodDebug]"Oneself
Pity I can only upvote once. And a big -1 to Google for the Firebase Console UI that implies that google-services.json is app-specific.Gipps
J
49

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.

Juristic answered 18/8, 2015 at 22:33 Comment(13)
But this works for buildTypes, not for flavors as posted by the OPOmophagia
@Omophagia if you are using a flavor - I am guessing that you can hook into processDebugFlavorGoogleServices task instead.Juristic
I think you should change it in your answer, as the question was about flavors, not buildTypes. I think you could also leave this answer as second optionOmophagia
Could you put a complete example? Shouldn't it include processReleaseFlavorGoogleServices?Omophagia
@Omophagia the logic is basically the same for either a flavor or buildType. you should be able to figure it outJuristic
I don't understand. Did you create two versions of you google-services.json file??Hanafee
@Hanafee yes, two versionsJuristic
Thanks - this came in handy setting up a copy of the json file stored in a non-standard location and copying it into the right place at build time.Phillips
This is very handy. But in after evaluate i have to many processes. Can put any filter for example if process contains Debug then run task?Playbook
Useful way to hardcode the behaviour. Using the existing paths as in the accepted answer is easier though.Taille
In build why gradle can not recognize processes? and says "Could not get unknown property process..."Playbook
To get all in one file - you have to create the apps under one project at the firebase.Delores
This approach can be dangerous and cause wrong values going to wrong build products if you build multiple build variants at once!Tattoo
K
23

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.

Koniology answered 14/8, 2015 at 7:33 Comment(4)
@Juristic but the question is for flavors, not for build typesOmophagia
this is not as good of a solution as medium.com/@ZakTaccardi/…Juristic
Doesn't work. This runs both copy commands regardless of build flavor, so the production json is always in the app directory.Rogue
It does work for flavors. No need to manually switch variables in build.gradle.Soyuz
K
17

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.

Keishakeisling answered 8/8, 2015 at 15:27 Comment(4)
you mean that if the backends are separated, then this will not work for you, I believeJuristic
all depends on how your definition of the flavors in both sides; client and server. In my case, different package names, different server urls and different databases. So the server will send the notification to the user in the corresponding database. User A has token 1 for flavor1 and token2 for flavor2. If you have different database entries then you will not have any problem.Keishakeisling
I tried creating tasks which copy and then invoking them on a particular debug process or release process and to think this worked .Wish this ws posted earlierMelodeemelodeon
Using one google-services.json for both release and debug worked for me, as mentioned in your update. I think this is the simplest solution if you're only trying to split your debug build, like I am. For reference, you can generate the file here: developers.google.com/mobile/add?platform=androidAlb
J
16

1.) What does google-services.json really do?

Follow this : https://mcmap.net/q/66142/-what-does-google-services-json-really-do

2.) How does google-services.json file affects your android studio project?

Follow this : https://mcmap.net/q/66142/-what-does-google-services-json-really-do

just in short for second url, if you add google-services.json in your project there must be a auto-generated google-services folder for debug variant in this path

app/build/generated/res/google-services/debug/values/values.xml

3.) What to do, to make it done?

add google-services dependency in project_level build.gradle, you can also use version 3.0.0 if you are using app_compact library.

// Top-level build.gradle file
classpath 'com.google.gms:google-services:2.1.2'

now in app_level build.gradle you have to add at the bottom.

// app-level build.gradle file
apply plugin: 'com.google.gms.google-services'

Note: Adding this line at the bottom of the gradle file is really important. Otherwise Gradle builds won't give you any errors, but it won't just work properly.

4.) Where to put google-service.json file in your structure.

case 1.) if you have no build_flavor just put it in inside /app/google-service.json folder.

case 2.) if you have multiple build_flavor and you have different-different google_services.json files put inside app/src/build_flavor/google-service.json.

case 3.) if you have multiple build_flavor and you have single google_services.json file put inside app/google-service.json.

Joettejoey answered 1/10, 2016 at 2:47 Comment(1)
For me it's about adding that Gradle line // app-level build.gradle file apply plugin: 'com.google.gms.google-services' to the very end of the Gradle file which worked.Putamen
C
15

I'm using the google-services.json file, created from here: https://developers.google.com/mobile/add?platform=android&cntapi=gcm&cnturl=https:%2F%2Fdevelopers.google.com%2Fcloud-messaging%2Fandroid%2Fclient&cntlbl=Continue%20Adding%20GCM%20Support&%3Fconfigured%3Dtrue

In the JSON-structure there is a JSON-array called clients. If you have multiple flavors, just add the different properties here.

{
  "project_info": {
    "project_id": "PRODJECT-ID",
    "project_number": "PROJECT-NUMBER",
    "name": "APPLICATION-NAME"
  },
  "client": [
    {
      "client_info": {
        "mobilesdk_app_id": "1:PROJECT-NUMBER:android:HASH-FOR-FLAVOR1",
        "client_id": "android:PACKAGE-NAME-1",
        "client_type": 1,
        "android_client_info": {
          "package_name": "PACKAGE-NAME-1"
        }
      },
      "oauth_client": [],
      "api_key": [],
      "services": {
        "analytics_service": {
          "status": 1
        },
        "cloud_messaging_service": {
          "status": 2,
          "apns_config": []
        },
        "appinvite_service": {
          "status": 1,
          "other_platform_oauth_client": []
        },
        "google_signin_service": {
          "status": 1
        },
        "ads_service": {
          "status": 1
        }
      }
    },
    {
      "client_info": {
        "mobilesdk_app_id": "1:PROJECT-NUMBER:android:HASH-FOR-FLAVOR2",
        "client_id": "android:PACKAGE-NAME-2",
        "client_type": 1,
        "android_client_info": {
          "package_name": "PACKAGE-NAME-2"
        }
      },
      "oauth_client": [],
      "api_key": [],
      "services": {
        "analytics_service": {
          "status": 1
        },
        "cloud_messaging_service": {
          "status": 2,
          "apns_config": []
        },
        "appinvite_service": {
          "status": 1,
          "other_platform_oauth_client": []
        },
        "google_signin_service": {
          "status": 1
        },
        "ads_service": {
          "status": 1
        }
      }
    }
  ],
  "client_info": [],
  "ARTIFACT_VERSION": "1"
}

In my project I'm using the same project-id and when I'm adding the second package-name in the above url, google provides me with a file containing multiple clients in the json-data.

Chretien answered 21/1, 2016 at 14:54 Comment(2)
This doesn't work if you're using multiple projectsChrestomathy
How to get the hash for my flavor ?Shir
F
8

google-services.json file is unnecessary to receive notifications. Just add a variable for each flavour in your build.gradle file:

buildConfigField "String", "GCM_SENDER_ID", "\"111111111111\""

Use this variable BuildConfig.GCM_SENDER_ID instead of getString(R.string.gcm_defaultSenderId) while registering:

instanceID.getToken(BuildConfig.GCM_SENDER_ID, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
Frowst answered 10/11, 2015 at 14:33 Comment(0)
D
8
  1. remove the existing google-services.json from your project.
  2. Build > Clean Project
  3. compile and run your app
  4. look at the error message that comes up to figure out where you can put your google-services.json..mine looked like this
    File google-services.json is missing. The Google Services Plugin cannot function without it. 
     Searched Location: 
    C:\Users\username\Desktop\HelloWorld\app\src\devSuffixYes_EnvQaApistaging_\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\debug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\devSuffixYes_EnvQaApistaging_Debug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\devDebug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\devSuffixYes_EnvQaApistaging_\debug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\debug\devSuffixYes_EnvQaApistaging_\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\debug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffixDebug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\debug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_Debug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_\debug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_\env\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_\envDebug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_\env\debug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_\env\qa\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_\env\qaDebug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_\env\qa\debug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_\env\qa\apistaging_\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_\env\qa\apistaging_Debug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\src\dev\suffix\yes_\env\qa\apistaging_\debug\google-services.json
    C:\Users\username\Desktop\HelloWorld\app\google-services.json
    

NOTE: it also cares about the order of the declaratios in the flavorDimensions. mine was flavorDimensions "dev_suffix", "environment"

Dead answered 27/10, 2020 at 21:29 Comment(1)
It looks that it works only if flavor has all lowercase name and it's corresponding Source Set too, and it also matches directory name (no 'setRoot' overrides). Only then those directories are included in a search list!Tattoo
S
7

I know, you doubt about google-services.json file should be put in the root app folder, yes? I will break down the myth — not necessarily. You can put google-services.json file to the flavor folder too. Like this:

enter image description here

Selfsown answered 2/7, 2021 at 19:41 Comment(0)
A
6

Firebase now supports multiple application ids with one google-services.json file.

This blog post describes it in detail.

You'll create one parent project in Firebase that you'll use for all of your variants. You then create separate Android applications in Firebase under that project for each application id that you have.

When you created all of your variants, you can download a google-services.json that supports all of your applications ids. When it's relevant to see the data separately (i.e. Crash Reporting) you can toggle that with a dropdown.

Andry answered 24/10, 2016 at 19:19 Comment(1)
Damn 5 years later and I still almost did one of the other solutions because this is at the bottom. THIS IS THE BEST SOLUTIONGrueling
S
6

According to Firebase docs you can also use string resources instead of google-services.json.

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. You can do this by:

  • Removing the google-services plugin from your root build.gradle
  • Deleting the google-services.json from your project
  • Adding the string resources directly
  • Deleting apply plugin: 'com.google.gms.google-services' from your app build.gradle

Example strings.xml:

<string name="google_client_id">XXXXXXXXX.apps.googleusercontent.com</string>
<string name="default_web_client_id">XXXX-XXXXXX.apps.googleusercontent.com</string>
<string name="gcm_defaultSenderId">XXXXXX</string>
<string name="google_api_key">AIzaXXXXXX</string>
<string name="google_app_id">1:XXXXXX:android:XXXXX</string>
<string name="google_crash_reporting_api_key">AIzaXXXXXXX</string>
<string name="project_id">XXXXXXX</string>
Samekh answered 16/10, 2019 at 7:29 Comment(2)
I had difficulty matching which key's value in the google-services.json file matches the appropriate string equivalent but then I found this which helped: developers.google.com/android/guides/… Posted in case someone else has the same issue.Antipersonnel
To add to the comment above, you can simply copy the generated values file app/build/generated/res/google-services/{build_type}/values/values.xml (see the reference above) into your res folder.Daisie
W
5

We have a different package name for debug builds (*.debug) so I wanted something that works based on flavor and buildType, without having to write anything flavor-related in the pattern of processDebugFlavorGoogleServices.

I created a folder named "google-services" in each flavor, containing both the debug version and the release version of the json file :

enter image description here

In the buildTypes section of your gradle file, add this :

    applicationVariants.all { variant ->
            def buildTypeName = variant.buildType.name
            def flavorName = variant.productFlavors[0].name;

            def googleServicesJson = 'google-services.json'
            def originalPath = "src/$flavorName/google-services/$buildTypeName/$googleServicesJson"
            def destPath = "."

            copy {
                if (flavorName.equals(getCurrentFlavor()) && buildTypeName.equals(getCurrentBuildType())) {
                    println originalPath
                    from originalPath
                    println destPath
                    into destPath
                }
            }
    }

It will copy the right json file at the root of your app module automatically when you'll switch build variant.

Add the two methods called to get the current flavor and current build type at the root of your build.gradle

def getCurrentFlavor() {
    Gradle gradle = getGradle()
    String  tskReqStr = gradle.getStartParameter().getTaskRequests().toString()

    Pattern pattern;

    if( tskReqStr.contains( "assemble" ) )
        pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
    else
        pattern = Pattern.compile("generate(\\w+)(Release|Debug)")

    Matcher matcher = pattern.matcher( tskReqStr )

    if( matcher.find() ) {
        println matcher.group(1).toLowerCase()
        return matcher.group(1).toLowerCase()
    }
    else
    {
        println "NO MATCH FOUND"
        return "";
    }
}

def getCurrentBuildType() {
    Gradle gradle = getGradle()
    String  tskReqStr = gradle.getStartParameter().getTaskRequests().toString()

        if (tskReqStr.contains("Release")) {
            println "getCurrentBuildType release"
            return "release"
        }
        else if (tskReqStr.contains("Debug")) {
            println "getCurrentBuildType debug"
            return "debug"
        }

    println "NO MATCH FOUND"
    return "";
}

That's it, you don't have to worry about removing/adding/modifying flavors from your gradle file, and it get the debug or the release google-services.json automatically.

Wickiup answered 2/2, 2016 at 17:10 Comment(0)
M
4

No need for any additional gradle scripting.

Google started adding different package name in the name of 'android_client_info'. It looks like below in google-services.json

"android_client_info": {
      "package_name": "com.android.app.companion.dev"
    }

so, following steps are enough to have different google-services.json selection.

  1. Have 2 flavours
  2. Add a new dev flavour's package to google analystics configuration page and download google-services.json.
  3. Notice in the new configuration file, both of your flavour's package ids are there
  4. Prepare any of your flavour build.

That is it!..

Meritorious answered 27/10, 2015 at 10:35 Comment(2)
I'm not sure what 2) and 3) refer to exactly. I cannot find anywhere in analytics.google.com where I can add packagenames, besides linking play store. The only place I have found to download json is from here developers.google.com/mobile/add and that does not permit adding multiple packagenames. Will it work just manually adding packagenames to android_client_info?Hyozo
@Hyozo You can add multiple package names to the same project and then download the file. Check here: github.com/googlesamples/google-services/issues/54Boldfaced
H
4

So if you want to programmatically copy google-services.json file from all your variants into your root folder. When you switch to a specific variant here's a solution for you

android {
  applicationVariants.all { variant ->
    copy {
        println "Switches to $variant google-services.json"
        from "src/$variant"
        include "google-services.json"
        into "."
    }
  }
}

There's a caveat to this approach that is you need to have google-service.json file in each of your variants folder here's an example. variant image

Hallelujah answered 13/8, 2019 at 15:42 Comment(0)
O
3

Based on @ZakTaccardi's answer, and assuming you don't want a single project for both flavors, add this to the end of your build.gradle file:

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

task switchToStaging(type: Copy) {
    outputs.upToDateWhen { false }
    def flavor = 'staging'
    description = "Switches to $flavor $googleServicesJson"
    delete "$appModuleRootFolder/$googleServicesJson"
    from "${srcDir}/$flavor/"
    include "$googleServicesJson"
    into "$appModuleRootFolder"
}

task switchToProduction(type: Copy) {
    outputs.upToDateWhen { false }
    def flavor = 'production'
    description = "Switches to $flavor $googleServicesJson"
    from "${srcDir}/$flavor/"
    include "$googleServicesJson"
    into "$appModuleRootFolder"
}

afterEvaluate {
    processStagingDebugGoogleServices.dependsOn switchToStaging
    processStagingReleaseGoogleServices.dependsOn switchToStaging
    processProductionDebugGoogleServices.dependsOn switchToProduction
    processProductionReleaseGoogleServices.dependsOn switchToProduction
}

You need to have the files src/staging/google-services.json and src/production/google-services.json. Replace the flavor names for the ones you use.

Omophagia answered 7/9, 2015 at 13:57 Comment(0)
Z
3

I have found that the google-services plugin is quite useless for projects that want to add GCM. It only generates the following file which simply adds your project ID as a string resource:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Your API key would be on the following line -->
    <string name="gcm_defaultSenderId">111111111111</string>
</resources>

It appears that you only need it if you copied the sample code verbatim directly from the Cloud Messaging for Android guide. Here is the example line:

String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),              GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

Solution

If you want to be able to switch API projects for different build types or product flavors you can just define your own constants and choose the appropriate one when calling the getToken() API.

private static final String SENDER_ID = "111111111111";
private static final String SANDBOX_SENDER_ID = "222222222222";

String token = instanceID.getToken(
        BuildConfig.DEBUG ? SENDER_ID : SANDBOX_SENDER_ID,
        GoogleCloudMessaging.INSTANCE_ID_SCOPE,
        null);

For Product Flavors

The above code works for switching between debug and release builds. For product flavors you would define different API keys in a java source file and place the files in their corresponding product flavor directory. For reference: Gradle Build Variants

Zwinglian answered 24/9, 2015 at 18:59 Comment(1)
@swimmingtomars You may be applying the google-service plugin unnecessarily. If you use this method you can't apply the google-services plugin. See the accepted answer if you require this plugin for service other than GCM.Zwinglian
P
3

Simplifying what @Scotti said. You need to create Multiples apps with different package name for a particular Project depending on the product flavor.

Suppose your Project is ABC having different product flavors X,Y where X has a package name com.x and Y has a package name com.y then in the firebase console you need to create a project ABC in which you need to create 2 apps with the package names com.x and com.y. Then you need to download the google-services.json file in which there will be 2 client-info objects which will contain those pacakges and you will be good to go.

Snippet of the json would be something like this

{
  "client": [
    {
      "client_info": {
        "android_client_info": {
          "package_name": "com.x"
        }

    {
      "client_info": {
        "android_client_info": {
          "package_name": "com.y"
        }
      ]

    }
Pare answered 1/9, 2016 at 8:20 Comment(0)
S
3

Just add the flavours app id and name of the flavour as app in the same project, Download the google-service.json file in the end and it will have all the flavours in the client array[] which will be fine for all flavours.

Google service json screen shot of client array

Supraliminal answered 1/12, 2021 at 12:44 Comment(1)
This is the best solution but unfortunately it is not applicable if flavors are already in different Firebase projects.Scold
M
2

The point of the google-services plugin is to simplify integration of Google features.

Since it only generates android-resources from the google-services.json file, over-complicated gradle-logic negates this point, I think.

So if the Google-docs don’t say which resources are needed for specific Google-features, I would suggest to generate the JSON-file for each relevant buildtype/flavor, see what resources get generated by the plugin and then put those resources manually into their respective src/buildtypeORflavor/res directories.

Delete the references to google-services plugin and the JSON-file after that, and you are done.

For detailed information about the inner workings of google-services gradle-plugin see my other answer:

https://mcmap.net/q/66142/-what-does-google-services-json-really-do

Medici answered 12/10, 2015 at 14:58 Comment(1)
I do not understand how using your answer, I can include 2 google-service.json. 1 for debug and another for releaseButterfish
M
2

Hey Friends also looks for name use only lowercase then u don't get this error

Maniple answered 14/9, 2016 at 11:41 Comment(0)
C
2

Short answer:

  • Implementation: By default, you should copy google-services.json to app dir.

For other flavor, copy google-services.json to app/src/{flavor-name} dir

  • Test: Try to build, open Build tab, then check output message with Parsing json file:.....
Crandale answered 29/9, 2020 at 23:30 Comment(0)
W
1

Indeed, juste one google-services.json in MyApp/app/ directory is good, no need for aditional script with com.google.gms:google-services:3.0.0. But be careful to delete the file google-services.json from the app directory MyApp/app/src/flavor1/res/ to avoid the error type Execution failed for task ':app:processDebugGoogleServices'. > No matching client found for package

Wootan answered 5/4, 2017 at 22:23 Comment(0)
S
0

I'm currently using two GCM Project Id in the same app package. I put the google-service.json of my first GCM project but I switch from the first to the second one only changing the SENDER_ID:

    String token = instanceID.getToken(SENDER_ID,GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

(At this point I think that the google-services.json isn't mandatory )

Sentimentality answered 24/6, 2015 at 16:9 Comment(0)
C
0

You have many flavor, so it mean you will have many difference package id, right? So, just go to the page where you setup/generate your json file and config for each package name. All of it will add to json file.

I'm verry lazy to post picture now, but basically:

  • go to https://developers.google.com/mobile/add
  • select platform
  • select your app
  • IMPORTANT: type your flavor package name to field "android package name"
  • ... continue to get your configuration file. Download it!

When config the file, you can see that google show you the Server API Key + Sender ID. And it is same for all package (flavors)

At the end, you just need only one json file for all flavors.

One more question here that you have to test when you register to get Registration Token, check if is difference for each flavor. I don't touch on it but it think it should be difference. Too late now and i so sleepy :) Hope it help!

Carlile answered 14/7, 2015 at 16:11 Comment(0)
N
0

Inspired by @ahmed_khan_89 answer above. We can directly keep like this in gradle file.

android{

// set build flavor here to get the right Google-services configuration(Google Analytics).
    def currentFlavor = "free" //This should match with Build Variant selection. free/paidFull/paidBasic

    println "--> $currentFlavor copy!"
    copy {
        from "src/$currentFlavor/"
        include 'google-services.json'
        into '.'
    }
//other stuff
}
Nuzzle answered 21/10, 2015 at 15:14 Comment(0)
R
0

Place your "google-services.json" file under app/src/flavors respectively then in build.gradle of app, under android add below code

gradle.taskGraph.beforeTask { Task task ->
        if (task.name ==~ /process.*GoogleServices/) {
            android.applicationVariants.all { variant ->
                if (task.name ==~ /(?i)process${variant.name}GoogleServices/) {
                    copy {
                        from "/src/${variant.flavorName}"
                        into '.'
                        include 'google-services.json'
                    }
                }
            }
        }
    }
Runkle answered 27/2, 2017 at 9:3 Comment(0)
O
0
    ...
    gradle.taskGraph.beforeTask { Task task ->
        if (task.name ==~ /process.*GoogleServices/) {
            android.applicationVariants.all { variant ->
                if (task.name ==~ /(?i)process${variant.flavorName}(Debug|Release)GoogleServices/) {
                    copy {
                        from "src/tenants/${variant.flavorName}"
                        include 'google-services.json'
                        into '.'
                    }
                }
            }
        }
    }

    gradle.taskGraph.afterTask { Task task ->
        if (task.name ==~ /process.*GoogleServices/) {
            android.applicationVariants.all { variant ->
                if (task.name ==~ /(?i)process${variant.flavorName}(Debug|Release)GoogleServices/) {
                    delete fileTree(".").matching {
                        include 'google-services.json'
                    }
                }
            }
        }
    }
Omdurman answered 20/10, 2020 at 14:40 Comment(0)
G
0

None of proposed solutions worked for my case of multi-dimensional flavors. My app has 2 dimensions: product (for branding) and environment. I placed environment-dependent google-services.json files into src/environment/env1,..,env2 folders. Then in gradle copy them into corresponding folders of products.

afterEvaluate {
    android.applicationVariants.forEach { variant ->
        variant.preBuildProvider.get().doFirst {
            val environment = variant.productFlavors.find { x -> x.dimension == "environment" }!!.name
            val product = variant.productFlavors.find { x -> x.dimension == "product" }!!.name
            val targetDir = "src/$product/$environment"
            val fileName = "google-services.json"
            delete("$targetDir/$fileName")
            copy {
                from("src/environment/$environment")
                include(fileName)
                into(targetDir)
            }
        }
    }
}
Gossipmonger answered 7/12, 2023 at 18:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.