I'm trying to use Google's App Invites API with my Android app and according to their guide, I need to put a config file that is generated from the developer console in the app/ directory of the project. My app has multiple build flavors, one for production, qa, and debug. I don't know how this works (since it is a pluging) with multiple build flavors and am hoping that someone can shed some light on this issue.

2

There are 2 answers

0
Maragues On

According to the Google services gradle plugin documentation, the plugin supports different google-services.json per buildType, but not per flavor

[...] as of version 2.0.0-alpha3 of the plugin support was added for build types, which would make the following directory structure valid:

app/src/

main/google-services.json
dogfood/google-services.json
mytype1/google-services.json

However, it's not working for me. I'm using 2.0.0-alpha9 and Gradle still complains that it can't find a google-services.json file in root folder

Error:Execution failed for task ':app:processProdReleaseGoogleServices'.

File google-services.json is missing from module root folder. The Google Services Plugin cannot function without it.

I've filed a bug: https://code.google.com/p/android/issues/detail?id=200116

0
arne.jans On

I investigated a bit regarding the google-services plugin and json and found the sources to this plugin.

First things first:

The gradle-plugin google-services that is referenced by classpath and with apply is a build-time plugin only! So it only influences the build-process of your app, but not the runtime-process!

This plugin is only meant as a quickstart-helper to integrating Google-services quickly in your app. Obviously, the process is somewhat convoluted and not documented, so Google should have made it clear what this process does.

In fact, I found the source code for the plugin version com.google.gms:google-services:1.4.0-beta3 and didnt find any specific reference in it regarding appinvites nor did I find any Google API for App Invites! (But maybe it just uses a generic API project with its project id, I didnt try this)

What it does:

The google-services gradle-plugin looks for the mentioned google-services.json file in your app-module. Then it looks for configured settings like project-id's and tracking-id's and such, generated by the Google API developer console into the google-services.json file. From the settings it found, Android resource values are generated into the following path:

$project.buildDir/generated/res/google-services/$variant.dirName/values/values.xml

For example for a debug-build of your app:

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

E.g. if you followed the GCM tutorial, the JSON file would include the API project's id as the following android-resource:

<string name="gcm_defaultSenderId">project-id</string>

So this plugin and JSON file are not essential to running or publishing your app, it is just a quickstart helper to generate some basic android-resource files for easier integration of specific Google API features.

Notice in the source code referenced below that the google-services plugin always generates those android-resources for every app-variant that is defined in your app/build.gradle.

If you don't want that, you should use those generated resources in the app-variants you want, and delete the others. Don't forget to remove the google-services plugin apply from app/build.gradle, or else it will be regenerated for all app-variants.

What it does not:

This plugin and JSON-file do NOT directly influence the inner workings of said Google-features for your app! If you already have followed older tutorials on developer.android.com on how to integrate e.g. GCM or Google Analytics, then you don't even need to integrate either the gradle-plugin google-services or the google-services.json file!

Notice about where I found the sources:

After you integrated the google-services gradle-plugin and when sync your project, Gradle automatically downloads the google-services dependency to a path similar to this (on Windows, you might need to look into your home/.gradle for Linux):

C:\Users\user\.gradle\caches\modules-2\files-2.1\com.google.gms\google-services\1.4.0-beta3\f1580f62e3be313eba041ce19b64fd3f44cf8951\google-services-1.4.0-beta3-sources.jar

If you extract this jar-file, you will find two files:

GoogleServicesPlugin.groovy
GoogleServicesTask.java

which contain the plain source code of the gradle-plugin.

GoogleServicesPlugin.groovy

contains the handling of the app-variants and basic definitions of paths etc.

GoogleServicesTask.java

contains the actual task-definition, look for the following method to see what it really does:

@TaskAction
public void action() throws IOException {
    checkVersionConflict();
    // google-services.json
    if (!quickstartFile.isFile()) {
        getLogger().warn("File " + quickstartFile.getName() + " is missing from module root folder." +
                " The Google Services Plugin cannot function without it.");

        // Skip the rest of the actions because it would not make sense if `quickstartFile` is missing.
        return;
    }

    // delete content of outputdir.
    deleteFolder(intermediateDir);
    if (!intermediateDir.mkdirs()) {
        throw new GradleException("Failed to create folder: " + intermediateDir);
    }

    JsonElement root = new JsonParser().parse(Files.newReader(quickstartFile, Charsets.UTF_8));

    if (!root.isJsonObject()) {
        throw new GradleException("Malformed root json");
    }

    JsonObject rootObject = root.getAsJsonObject();

    Map<String, String> resValues = new TreeMap<String, String>();

    handleProjectNumber(rootObject, resValues);

    JsonObject clientObject = getClientForPackageName(rootObject);

    if (clientObject != null) {
        handleAnalytics(clientObject, resValues);
        handleAdsService(clientObject, resValues);
        handleGoogleAppId(clientObject, resValues);
    } else {
        getLogger().warn("No matching client found for package name '" + packageName + "'");
    }

    // write the values file.
    File values = new File(intermediateDir, "values");
    if (!values.exists() && !values.mkdirs()) {
        throw new GradleException("Failed to create folder: " + values);
    }

    Files.write(getValuesContent(resValues), new File(values, "values.xml"), Charsets.UTF_8);
} 

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.