Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BuildType/Flavour Support #54

Closed
chrisjenx opened this issue Aug 31, 2015 · 97 comments
Closed

BuildType/Flavour Support #54

chrisjenx opened this issue Aug 31, 2015 · 97 comments

Comments

@chrisjenx
Copy link

I have had a look, I can't see another issue.

How do we enabled different configs per flavour/buildType? Most Common use case is where we have different analytics tracking and GCM senders per debug/release builds.

Favours would be an added bonus.

Thanks.

@ianbarber
Copy link
Contributor

If you vary on package name you should be OK - the gradle plugin should pull config from the JSON based on the app's package name.

@silvolu
Copy link
Contributor

silvolu commented Aug 31, 2015

It won't solve the GCM senders part though: you got one per app, so the different packages will share the same GCM sender ID.

@ajfclark
Copy link

@ianbarber Can you give an example of how to combine multiple google.services files together when the package name varies per flavour?

@chrisjenx
Copy link
Author

You just keep adding them to the config on the website and it combines them
all together in the JSON file.

On Tue, 24 Nov 2015, 14:28 Andrew Clark notifications@github.com wrote:

@ianbarber https://github.com/ianbarber Can you give an example of how
to combine multiple google.services files together when the package name
varies per flavour?


Reply to this email directly or view it on GitHub
#54 (comment)
.

@bigD666
Copy link

bigD666 commented Nov 24, 2015

Stop emailing me
On 25 Nov 2015 08:58, "Andrew Clark" notifications@github.com wrote:

@ianbarber https://github.com/ianbarber Can you give an example of how
to combine multiple google.services files together when the package name
varies per flavour?


Reply to this email directly or view it on GitHub
#54 (comment)
.

@ajfclark
Copy link

@chrisjenx Where? I go to https://developers.google.com/mobile/add, pick android, Pick the app and package name, add analytics as a service and then the only option is to generate the config file.

[edit: oh, I see now. You have to go in, add a service, generate a config, go back to the original url, add another service, etc. That's horribly non-intuitive.

Is there anywhere you can see what's already been added to a project, modify existing services, etc?]

@ajfclark
Copy link

@bigD666 I'm not. Github is. You must be watching this project or issue or something?

@chrisjenx
Copy link
Author

@ajfclark correct, pick the same "App Name" then add new package names:

If you pick the same package name and continue, you can add/see whats added to that config.

See example:
screen shot 2015-11-24 at 16 07 32

@ajfclark
Copy link

It'd be nice if there was an "add another service" or something button to make it obvious that you could do that.

@samtstern
Copy link
Contributor

@ajfclark agreed, we are currently considering the best way to support build flavors in the UI.

@yairkukielka
Copy link

@samtstern yes, please. This would be great. I have another tricky case with our app:

We have 4 build variants: FreeDev, FreeProd, PaidDev and PaidProd. Each of these variants has a Google Services project, so we have 4 Google Services project ids: Free dev, Free prod, Paid dev and Paid prod.

Is there a way to get only one google-services.json for all these Google Services projects? If I had only one Google Services account with multiple flavors (package names) I see that I could apply what @chrisjenx is saying, but how do I achieve that for different Google Services projects?

If it's not possible, how should I use different google-services.json files in my local project?

This is what I see when I try to enable Google Services for my app:
screen shot 2015-12-04 at 11 56 11 am

@samtstern
Copy link
Contributor

@yairkukielka there is no way (and there probably never will be) to get one google-services.json file for multiple distinct projects. However with build flavor support you would just have four google-services iles and it would look something like this:

app/
  src/
    FreeDev/google-services.json
    FreeProd/google-services.json
    PaidDev/google-services.json
    PaidDev/google-services.json

@yairkukielka
Copy link

ok, Thank you Sam!

I thought the plugin only worked when the google-services.json file was placed on the /app root folder. It it works placing the google-services.json file in every flavour's folder, that's not a big deal :)

@ajfclark
Copy link

ajfclark commented Dec 5, 2015

@yairkukielka That's what we're asking for, not what's currently supported.

@yairkukielka
Copy link

I see... In that case, +1 to this issue. Flavor support would be very interesting.

@stsandro
Copy link

stsandro commented Dec 9, 2015

Wow, implementing/including Google Play Services has really become complicated since the last time I've done some Android development!
+1 for this issue! I need this to build multiple apps with different app-ids from the same code base!

@chrisjenx
Copy link
Author

I think another work around for now would be to create a "core" module which is effectively a library project.
Then create child projects which have their own google-services.json

core
|- freedev
|- freeprod
|- paiddev
|- paidprod

By no means a "good" solution but that would let you do what you need for now.

@samtstern
Copy link
Contributor

There is a workaround for all of this, which involves not using the
google-services plugin at all and just recreating what it would do. The
plugin is meant to be a convenience and it doesn't do anything you can't do
yourself.

The main thing it does is create R.string.google_app_id using the value of
the "mobilesdk_app_id" field from the JSON file.

The other things it does are optional and depend on the APIs you're using.
If you're using GCM it creates R.string.gcm_default_senderId and if you're
using Ads it creates R.xml.global_tracker. If you need these resources,
you can simply create them yourselves.

Most of the other data in the JSON file is not currently used by the plugin
so you can get away with just creating the resources you need in each build
flavor you need them. The plugin does not affect any of your project's
Java code and your app will run fine without it.

On Wed, Dec 9, 2015, 7:08 AM Christopher Jenkins notifications@github.com
wrote:

I think another work around for now would be to create a "core" module
which is effectively a library project.
Then create child projects which have their own google-services.json

/ core
|- / freedev
|- / freeprod
|- / paiddev
|- / paidprod

By no means a "good" solution but that would let you do what you need for
now.


Reply to this email directly or view it on GitHub
#54 (comment)
.

@chrisjenx
Copy link
Author

@samtstern OK great, thats good to know, thanks for that!

@samtstern
Copy link
Contributor

Good News Everyone

As of the build com.google.gms:google-services:2.0.0-alpha3 you should be able to put your google-services.json file inside your build flavors directories like this:

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

I will leave this issue open so that we can collect feedback on whether or not this solves your problems. Thanks for your patience thus far.

@sregg
Copy link

sregg commented Dec 24, 2015

This is still not working for me.
I have app/src/debug/google-services.json and app/src/release/google-services.json and the plugin is still complaining that google-services.json is missing in the root folder.
(using com.google.gms:google-services:2.0.0-alpha3)

@m-i-k-e-e
Copy link

@sregg probably because you're not using flavors but buildTypes

@renejahn
Copy link

renejahn commented Jan 6, 2016

So I understand that this could help me with flavors. But in our gradle configuration the dev buildType adds ".dev" to the package name which does not match the package name of google-services.json. Also I have no place for buildType specific google-services.json files. So how do I handle flavors and buildTypes which both append something to the package name?

@samtstern
Copy link
Contributor

Here is the more official google-services document, as promised:
https://developers.google.com/android/guides/google-services-plugin

I hope that answers many of the questions on this thread. If it does not, feedback appreciated.

(Comment edited 1/8/2016 at 9:31am)

@sregg
Copy link

sregg commented Jan 8, 2016

Thanks Sam but that link looks like a private Google link (it asks for username/password)...

@rjam
Copy link

rjam commented Apr 15, 2016

@samtstern I'm still faced with the same issue as @adrien-aubel regarding multi-flavor variants..Any place where we can track the implementation of that feature?

@jvanderwee
Copy link

Has a feature request been raised for this issue?

@samtstern
Copy link
Contributor

@jvanderwee we have seen that request and logged a FR, no hard timeline on when that will be a part of the plugin. Thanks for following up.

@jeffreydelooff
Copy link

jeffreydelooff commented Jun 2, 2016

My current set-up includes flavors with custom root directories specified in the sourceSets:

{flavor}.setRoot("src/environments/{flavor}")

However, the google services plugin doesn't look in those folders. Will this be supported in the future or is there a way to have the project.file resolving of "google-services.json" also look into these custom root directories?

@atanascu
Copy link

atanascu commented Jul 4, 2016

@samtstern We don't have multiple flavors on our app, but we do have multiple build types. I can see multiple apps in the Firebase console, one per build type. Is there a point in having a google-services.json file per build type considering that the files are identical and they contain multiple client entries, one for each build type? And do you know why ads_service has a status 1 by default?

@samtstern
Copy link
Contributor

If you don't need the build types to behave differently with respect to
Google/Firebase then there's no reason to have multiple JSON files.

As for ads service I believe that's just because the back end has been set
up for you already if you decide to use AdMob. If you're not using the
AdMob SDK nothing will happen due to that value.

On Mon, Jul 4, 2016, 8:43 AM schopy notifications@github.com wrote:

@samtstern https://github.com/samtstern We don't have multiple flavors
on our app, but we do have multiple build types. I can see multiple apps in
the Firebase console, one per build type. Is there a point in having a
google-services.json file per build type considering that the files are
identical and they contain multiple client entries, one for each build
type? And do you know why ads_service has a status 1 by default?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#54 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AIEw6g627p66Cp6Z7p6uBzXYl7OD1C5Lks5qSSobgaJpZM4F1F4I
.

phil-lopreiato added a commit to the-blue-alliance/the-blue-alliance-android that referenced this issue Jul 11, 2016
Move the default google-services.json (so fresh clones and travis can
build because the gradle plugin requires the file to be present) to the
lowest priority location, and ensure that the flavor-specific locations
are ignored. This way, prod builds can have its file in
android/src/prod/ and a debug build pointing to a dev instance can have
one in android/src/debug/

See this comment:
googlesamples/google-services#54 (comment)
for the order of file location searches
@bulatgaleev
Copy link

What if i want to use different google-services.json within 1 flavor? (my app should be able to dynamically switch environments - each environment is a seperate Google Project).

@originx
Copy link

originx commented Oct 28, 2016

Is there any way to raise prio on #54 (comment)

Like this it would be much easier to have a clean setup per dimension, especially if they are separate firebase projects.

Another alternative would be combining all projects and apps into 1 google-json file but I believe supporting fallback to dimensions before going to main would solve all flavor type issues.

or ability to define google-json file location per product flavor config which would override default file traversal algorithm

@filipmaelbrancke
Copy link

@localhostEU : I arrived at this issue looking for a solution to the same problem, and I'd like to point out that there is some information now: https://firebase.googleblog.com/2016/12/working-with-multiple-firebase-projects-in-an-android-app.html

@ElineDeMeyer
Copy link

Is there already a solution for this issue?

@cubbuk
Copy link

cubbuk commented Jan 24, 2017

I just need to create 2 flavors for staging and production. I created folders under src respectively and copied google-services.json under folders src/staging and src/production. Each google-services.json under flavor directories contains correct package name for android_client_info i.e. com.myapp.staging or com.myapp.production. However rest of the json files are same i.e. using same api_key etc, only the package name changes according to the flavor name. Do I need to generate new json files from developer console for each flavor, or just changing the package name of each json file is enough? Thanks

@Cassio90
Copy link

I'm also looking for a solution to scanning non-combined flavor dimension folders as described here.
Is this feature planned?

@ghost
Copy link

ghost commented Nov 27, 2017

For the issue from comment #204587543:

Google is solving the world problems. They're sending their engineers around NASA, Tesla, Whit House to tackle world problems. Last time I heard, they were building smart condoms. Next API for you Android devs would be Condom Wearable.

Again, what do your tiny projects mean to Google? => null/NPE/NullPointerException

No one likes NullPointerException. That's my honest advice.

When I say "honest", I have workaround:

First, add *.json to your .gitignore.

Then:

applicationVariants.all { variant ->
    // Verify your dimension if needed
    if (variant.productFlavors[-1].dimension != 'xxx') return

    // Here's your original json file
    def orgJsonFile = new File(project.projectDir, ...)

    // Here's the temp file
    def tmpJsonFile = new File(project.projectDir, "src/${variant.dirName}/google-services.json")

    // Check to make directory if not existed: tmpJsonFile.parentFile
    // For any parent directory that you make, call #deleteOnExit()

    if (you're on Linux)
        java.nio.file.Files.createSymbolicLink(tmpJsonFile.toPath(), orgJsonFile.toPath())
    else
        tmpJsonFile.text = orgJsonFile.text()

    // Finally:
    tmpJsonFile.deleteOnExit()
}

@bskim45
Copy link

bskim45 commented Nov 27, 2017

@ghost
App developers are also engineers managing to solve world problems in different dimensions.
Its funny that those projects are treated as 'tiny projects' 🙃

@toxxmeister
Copy link

My current workaround is attaching to the plugin's task and copying the required flavor's JSON to the module's root:

val gmsPattern = Regex("""process([A-Z][a-z]*).*GoogleServices""")
tasks.withType<GoogleServicesTask> {
    gmsPattern.matchEntire(name)?.destructured?.let { (flavor) ->
        doFirst {
            copy {
                from("src/${flavor.toLowerCase()}/google-services.json")
                into(".")
            }
        }
    }
}

It's written in Gradle Script Kotlin, but it shouldn't be much different in Groovy.

@jpardogo
Copy link

jpardogo commented Mar 1, 2018

It is solved now in classpath 'com.google.gms:google-services:3.2.0'

https://bintray.com/android/android-tools/com.google.gms.google-services/3.2.0

@flasher297
Copy link

Oh my god! With 3.2.0 it finally woks. @jpardogo big thanks for flagging!
I have two flavor dimensions an three build types. Moreover there are six Firebase projects,
And henceforth I can avoid copypasting JSON configurations,

@tokou
Copy link

tokou commented Apr 18, 2018

Thanks for the update.
There's still an issue for flavor names that contain uppercase characters though 🤔
If I have flavors firstFlavor of dimension dim1 and second of dimension dim2, it only looks in the folders first and firstFlavorSecond but not firstFlavor

@jpardogo
Copy link

jpardogo commented Apr 23, 2018

With 2 Flavours dimensions: client & platform.
Log after deleting google-services.json for a client:

Could not find google-services.json while looking in
[

  • mobile/src/client/platform/debug,
  • mobile/src/clientPlatform/debug,
  • mobile/src/debug/clientPlatform,
  • mobile/src/client/debug,
  • mobile/src/client/platform,
  • mobile/src/client/platformDebug,
  • mobile/src/clientPlatform,
  • mobile/src/debug,
  • mobile/src/clientPlatformDebug,
  • mobile/src/client,
  • mobile/src/clientDebug,
  • mobile/
    ]

Those are the paths where the file is searched inside the module.

@huck1eberry
Copy link

Have the same issue with flavor names containing uppercase characters. Flavor root folder (module/src/<flavour_with_some_uppercase_letters>) is "ignored" by the plugin. The search is performed only within module's root and module/src/<flavour_with_some_uppercase_letter>/debug (or release) folder.

@Tharkius
Copy link

Tharkius commented Nov 19, 2018

Have the same issue with flavor names containing uppercase characters. Flavor root folder (module/src/<flavour_with_some_uppercase_letters>) is "ignored" by the plugin. The search is performed only within module's root and module/src/<flavour_with_some_uppercase_letter>/debug (or release) folder.

I'm also facing this issue, took a while to understand it was a bug. I see the compiler prints a message saying something like "MyFlavour/debug/ failed to parse into flavors. Please start all flavors with a lowercase character".

This is completely unacceptable, IMO. There are many projects out there (including the one I'm working on), which already have the flavour dimensions set-up with uppercase letters, and it makes no sense to me that we should be changing our configurations, just because the plugin won't work with uppercase letters.

Is there a separate issue for this bug?

EDIT: For those struggling with the same issue, I have found a workaround at this link.

@jgil-krasamo
Copy link

Okay, the current problem is that if you're using two dimensions, the file is searched in the folder of the first declared dimension, but never in the folder of the second one.

@ashish-bahl
Copy link

Have the same issue with flavor names containing uppercase characters. Flavor root folder (module/src/<flavour_with_some_uppercase_letters>) is "ignored" by the plugin. The search is performed only within module's root and module/src/<flavour_with_some_uppercase_letter>/debug (or release) folder.

I stumbled upon this comment and decided to give this a try. Changed all the upper class flavor folder names to lower case and gave it a whirl. It all works like a charm now, thanks a ton! :)

@sky-danilomenezes
Copy link

So in our case we have many more flavours and build types combinations than what gradle would generate the correct folders for us, so we have some custom sourceSets.

We have 3 flavorDimensions (proposition, store and environment), 9 productFlavors (2 propositions, 2 stores and 5 envs) and 3 build types. Which would then generate a variant somewhat like this PROPOSITIONStoreEnvironmentBuildtype

The problem for us is that the plugin is stopping the search on the first matching case where it finds a json. We have a json for PROPOSITION and PROPOSITIONRelease folders, and it will stop the search when it finds the one inside PROPOSITION...

I don't see any way of working around this, any ideas?

@Tharkius
Copy link

Tharkius commented Mar 16, 2022

So in our case we have many more flavours and build types combinations than what gradle would generate the correct folders for us, so we have some custom sourceSets.

We have 3 flavorDimensions (proposition, store and environment), 9 productFlavors (2 propositions, 2 stores and 5 envs) and 3 build types. Which would then generate a variant somewhat like this PROPOSITIONStoreEnvironmentBuildtype

The problem for us is that the plugin is stopping the search on the first matching case where it finds a json. We have a json for PROPOSITION and PROPOSITIONRelease folders, and it will stop the search when it finds the one inside PROPOSITION...

I don't see any way of working around this, any ideas?

In your case I would say to get rid of the PROPOSITION folders, create a PROPOSITIONRelease folder for every possible configuration and add the json file in each of those folders, duplicating if need be.

You will probably end up with a lot of folders and duplicate jsons, but hey, it's a solution :D

I actually had to do that for the project I was working on at the time...

@sky-danilomenezes
Copy link

sky-danilomenezes commented Mar 17, 2022

So in our case we have many more flavours and build types combinations than what gradle would generate the correct folders for us, so we have some custom sourceSets.
We have 3 flavorDimensions (proposition, store and environment), 9 productFlavors (2 propositions, 2 stores and 5 envs) and 3 build types. Which would then generate a variant somewhat like this PROPOSITIONStoreEnvironmentBuildtype
The problem for us is that the plugin is stopping the search on the first matching case where it finds a json. We have a json for PROPOSITION and PROPOSITIONRelease folders, and it will stop the search when it finds the one inside PROPOSITION...
I don't see any way of working around this, any ideas?

In your case I would say to get rid of the PROPOSITION folders, create a PROPOSITIONRelease folder for every possible configuration and add the json file in each of those folders, duplicating if need be.

You will probably end up with a lot of folders and duplicate jsons, but hey, it's a solution :D

I actually had to do that for the project I was working on at the time...

So we got it working with a different approach but with the same motto (it works)

  • We've created a folder app/src/google-services
  • Inside that we've created subfolders for the PROPOSITION then a subfolder for each proposition build type, eg PROPOSITION1/Release
  • We've then created a script attached to the afterEvaluate of the app gradle file which creates a task that will evaluate which combination we're running and then copy the correct google-services.json to /app/src/
  • And then we added the google-services.json of the root to our gitignore
afterEvaluate {
    android.applicationVariants.all { variant ->
        def prepareJsonTask = tasks.create(
                name:"${variant.name}PrepareGoogleServices",
                type: Copy
        ) {
            description = 'Switches to google-services.json depending on flavor'
            from "src/google-services/${getGoogleServicesSrcPath(variant)}"
            include "google-services.json"
            into "."
        }

        variant.preBuildProvider.get().dependsOn(prepareJsonTask)
    }
}

Edit: We actually got it working by creating the build types folder under the proposition... PROPOSITION/debug, PROPOSITION/release etc. Plugin worked just fine after that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests