Google-Services.Json For Different Productflavors

google-services.json for different productFlavors

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:

Sample Image

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

configure mulitple google-services.Json for different flavours in FCM

The article you are referring to is old. A little while back Firebase changed the implementation of supporting different flavors. There is now only one google-services.json file generated by Firebase which holds a reference to all the flavors.


You have to add multiple apps in the same Project in the Firebase console, and download the updated google-service.json and put in the root folder.


Follow the latest guide provided by Firebase. Read their instructions on how to add different variants:

Adding apps to a Firebase project

Add Firebase to your Android project

Edit google-services.json for different flavors in Gradle

Answer updated

First of all I must explain I'm using Jenkins to compile my application, so the build process is not exactly the same than in Android Studio. In my case Jenkins only build the release version and is not getting the flavors on the same way than the IDE. I'll explain both solutions:

In the build.gradle (Module: app)

Mine

buildscript{
...
}
android {
...
}

afterEvaluate {
android.applicationVariants.all { variant ->
preBuild.doLast {
setGoogleServicesJson(variant)
}
}
// Only for Jenkins
assembleRelease.doFirst {
deleteGoogleServicesJson()
}
}

def setGoogleServicesJson(variant) {
def originalFileName = "google-services.bak"
def newFileName = "google-services.json"
def originalFile = "./$originalFileName"
def newFile = "./$newFileName"
def applicationId = variant.applicationId
def regularExpression = "\\\"package_name\\\" : \\\"(\\w(\\.\\w)?)+\\\""
def packageName = "\\\"package_name\\\" : \\\"$applicationId\\\""

copy {
from (originalFile)
into ("./")
rename (originalFileName, newFileName)
}
ant.replaceregexp(
file: newFile,
match: regularExpression,
replace: packageName,
byLine: true)
}

def deleteGoogleServicesJson() {
file("./google-services.json").delete()
}

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

Jenkins is getting the google-services.json located in the 'Project/app/' folder and it doesn't use the flavor ones, so for each variant and as soon as possible (after the preBuild task) I'm creating a new JSON from my *.bak file, overriding the package_name and letting Gradle continues with the building.

When everything is done and before it release the app (assembleRelease.doFirst) I delete the google-services.json and I keep the *.bak.

In my case I only want to change the package_name value of my JSON, but this solution won't work if I want to change another value as the project_number, the client_id or whatever else depending on the flavor.

Alternative solution (using flavors)

afterEvaluate {
android.applicationVariants.all { variant ->
def fileName = "google-services.json"
def originalFile = "./$fileName"
def flavorName = variant.flavorName
def destinationPath = "."
// If there is no flavor we use the original path
if (!flavorName.empty) {
destinationPath = "$destinationPath/src/$flavorName/"
copy {
from file(originalFile)
into destinationPath
}
}
def regularExpression = "\\\"package_name\\\" : \\\"(\\w(\\.\\w)?)+\\\""
def packageName = "\\\"package_name\\\" : \\\"$variant.applicationId\\\""
ant.replaceregexp(
file: "./$destinationPath/$fileName",
match: regularExpression,
replace: packageName,
byLine: true)
}
}

In this solution I have the google-services.json in the 'Project/app/' folder and I make a copy of it in each flavor folder. Then I override the package_name. In case you are working without flavors, the app will use the original JSON to compile.

You can check if another JSON exists in the flavor folder before override it, in case you have different values for the rest of the values.


Old solution

I've found a solution mixing this and this answers.

This is my build.gradle (Module: app) right now:

afterEvaluate {
android.applicationVariants.all { variant ->
def applicationId = variant.applicationId
ant.replaceregexp(file: './google-services.json', match:'package_name_value', replace: applicationId, byLine: true)
}
}

where package_name_value is the "regular expression" I've defined to be replaced.

The location of the google-services.json is "MyProject/ppp/google-services.json", and I've tested that if you put another googler-services.json inside your flavor folder, it overrides the first one.

*There is (at least) one problem when you have more than one flavor defined at the same time, because this task is always overriding the same file, so the final application id will be the last you have defined.

If you have another way, feel free to post it.

Multiple google-services.json Per Product Flavour

The only way I was able to do this was to bypass use of google-services.json and create FirebaseApp instance dynamically e.g.

    if (<is dev>) {
apiKey = <dev api key>;
databaseUrl = <dev database url>;
} else if (<is test> {
apiKey = <>;
databaseUrl = <>;
} else // production {
apiKey = <>;
databaseUrl = <>;
}


FirebaseOptions firebaseOptions = new FirebaseOptions.Builder()
.setApiKey(apiKey)
.setApplicationId(context.getString(R.string.google_app_id))
.setDatabaseUrl(databaseUrl)
.build();

return FirebaseApp.initializeApp(context, firebaseOptions, "MyApp");

Is there any way to have no google-services.json for some of product flavors?

I think that you could just place an empty google-services.json file in those flavors.

File google-services.json is missing when combining multiple product flavors with flavor dimensions

I end up by solving this issue with a couple of extra tasks for each merged productFlavor. I added this code after android :

afterEvaluate {

android.productFlavors.all { flavor ->
if (flavor.dimension == "vendor") {
task("copy${flavor.name.capitalize()}GoogleServicesFile", type: Copy) {
description = 'Switches to google-services.json depending on flavor' from "src/${flavor.name}"
include "google-services.json" into "."
}
task("delete${flavor.name.capitalize()}GoogleServicesFile", type: Delete) {
description = 'Delete google-services.json from base folder'
delete "./google-services.json"
}
}
}

android.applicationVariants.all { variant ->
def buildType = variant.buildType.name.capitalize()
def typeFlavorName = variant.productFlavors.get(0).name.capitalize()
def vendorFlavorName = variant.productFlavors.get(1).name.capitalize()
def copyFileTaskName = "copy${vendorFlavorName}GoogleServicesFile"
def deleteFileTaskName = "delete${vendorFlavorName}GoogleServicesFile"
def processGoogleServicesTaskName = "process${typeFlavorName}${vendorFlavorName}${buildType}GoogleServices"
tasks."${processGoogleServicesTaskName}".dependsOn "${copyFileTaskName}"
tasks."${processGoogleServicesTaskName}".finalizedBy "${deleteFileTaskName}"
}
}

This way, for each typeFlavorName, vendorFlavorName and buildType variation, the google-services.json file is copied to app/ before process{typeFlavorName}{vendorFlavorName}{buildType}GoogleServices and deleted afterwards.



Related Topics



Leave a reply



Submit