I'm working on an Android application that has two different flavours and I'm looking at the Gradle Play Publisher to automate the release to the alpha channels by using the Gradle wrapper command line.
Each of the two flavours corresponds to a different developer account on Google Play.
The issue that I'm facing now, is that the Play Publisher plugin only takes one Google Play configuration ( service account + auth key ).
I'm not particularly familiarised with Gradle, but I'm guessing is flexible enough to iterate over the flavours and execute a task with a 'per-flavour' buildscript config.
Does anyone know how can I accomplish this? Maybe examples of other projects that manipulate buildscript configuration based on flavours?
Thanks in advance.
Relevant part of the build.gradle script.
android {
...
productFlavors {
flavour1 {
applicationId 'com.example.1'
}
flavour2 {
applicationId 'com.example.2'
}
}
}
...
play {
serviceAccountEmail = '<SERVICE_ACCOUNT>'
pk12File = file('<PATH_TO_KEY>')
}
Adding two solutions that I found in Github to work around this issue, as no official support for this feature is provided by the project developers.
Solution #1: Using environment variables
https://github.com/Triple-T/gradle-play-publisher/issues/65
Solution #2: Using Gradle Task and custom config files
https://github.com/Triple-T/gradle-play-publisher/issues/76#issuecomment-121756953
You can follow the complete discussion here:
https://github.com/Triple-T/gradle-play-publisher/issues/76
Related
I'm trying to release my app on amazon and apparently I can't use R8 if I want to use IAP.
Currently I'm handling pretty much everything just using Gradle flavors. So how can I tell it to not use R8 for my Amazon flavor on Gradle?
Thanks.
I don't think that there is a way to use different shrinkers on a flavor level.
However, the issue with Amazon IAP has been fixed (see https://issuetracker.google.com/134766810), and is included in Android Studio 3.6, which is avaliable as a release candidate on https://developer.android.com/studio/preview.
If you want to use the fix in Android Studion 3.5 you can get that to use a newer version of R8 by adding the following to you top level build.gradle file:
buildscript {
repositories {
maven {
url "http://storage.googleapis.com/r8-releases/raw"
}
}
dependencies {
classpath 'com.android.tools:r8:1.6.67' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
}
}
The usage of Google Services requires the use of this Gradle plugin:
apply plugin: 'com.google.gms.google-services'
This thread on the Gradle forum has lead me to conclude that you can't selectively enable or disable a plugin, meaning that is not an option. I've tried a number of solutions offered by older threads involving conditionals surrounding the apply plugin statement and none of them work now.
The plugin itself is configured by a google-services.json that Google generates and is placed into the project directory. I'm aware that you can have different configurations for each flavour by having multiple google-services.json files, but what are we meant to do for build flavours that we explicitly want to not use Google Services (e.g. for targeting devices that do not have Play Services installed)? Blank files or dummy JSON files don't work as the plugin will refuse to accept it.
So the only solution that I can think of would be to manually disable the plugin (comment out that line) each time I want to test/build my flavour. Surely there has to be a better way to control how the plugin works?
I finally got a version to work. Tested with gradle 4.6, build tools 3.0.1, google-services plugin 3.1.1
apply plugin: 'com.google.gms.google-services'
android.applicationVariants.all { variant ->
if (variant.name == 'someVariantNameYouDontwantFirebase') {
project.tasks.getByName('process' + variant.name.capitalize() + 'GoogleServices').enabled = false
}
}
I have an app where I'd like to add an Android Wear app extension. The main app has three build types (debug, beta and release). Beta builds have an applicationIdSuffix which allows me to install the play-store version and the current development version in parallel on the same device. This all worked fine until I added the wear app.
The main app`s build.gradle looks like this:
apply plugin: 'com.android.application'
android {
...
defaultConfig {
...
applicationId "com.example.mainApp"
...
}
buildTypes {
debug {
applicationIdSuffix '.debug'
}
beta {
applicationIdSuffix '.beta'
}
release {
}
}
}
dependencies {
...
wearApp project(':wear')
}
The Wear-App has the same build types with the same applicationIdSuffix values. However, when I build the beta app (by calling gradle assembleBeta) the build process builds :wear:assembleRelease instead of :wear:assembleBeta which is why I get the following error message during build:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:handleBetaMicroApk'.
> The main and the micro apps do not have the same package name.
How can I tell the build process to build the correct build type when packaging the main app with build type beta?
Following the link posted by Scott Barta (http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication) I came up with this :
In the build.gradle of the wear app, add publishNonDefault true (to publish all variants):
android {
publishNonDefault true
}
In the build.gradle of the main app,
Replace
wearApp project(':wear')
By
debugWearApp project(path:':wear', configuration: 'debug')
releaseWearApp project(path:':wear', configuration: 'release')
You can't do what you want; the build variant of a module isn't propagated to the builds of dependent modules on build. This is tracked in https://code.google.com/p/android/issues/detail?id=52962
There's a facility to make one module depend on a specific variant of another one, as documented in http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication, but I don't think this mechanism can be extended to do differential packaging of Wear apps.
UPDATE
Now there is official support for build variants (see answer of Cyril Leroux). Hence this answer is deprecated.
I found a very (very) ugly solution which has some drawbacks but works for now until there is support for build variants for wear apps.
I set a global variable in the rootProject which contains the applicationIdSuffix of the currently built main app.
Within build.gradle of the main app I added the following:
// Set a global variable, depending on the currently built build-type.
// This allows us to set the applicationIdSuffix of the wear app depending on
// the build-type of the main app.
android.applicationVariants.all { variant ->
def task = variant.checkManifest
def suffix = variant.buildType.applicationIdSuffix
task.doLast {
rootProject.ext.currentApplicationIdSuffix = suffix
}
}
In the build.gradleof the wear app I added the following snipped:
android.applicationVariants.all { variant ->
def task = variant.generateBuildConfig
task.dependsOn(propagateApplicationIdSuffix)
}
task propagateApplicationIdSuffix << {
project.android.buildTypes.all { type ->
if (rootProject.hasProperty('currentApplicationIdSuffix')) {
type.applicationIdSuffix = rootProject.ext.currentApplicationIdSuffix
}
}
}
This has several drawbacks:
You can't build multiple variants (i.e. gradle assembleBeta assembleRelease) because the wear app is only built once and hence the second build type fails
gradle check fails because of reason 1
The wear app is still built with build type release but the package name is just changed according to to application id suffix of the main app
Don't worry, you CAN do what you want to do. I just did it for the enterprise app I work on.
The key is NOT to use wearApp project(':wear'), since that only works when you have the same applicationId in your wear app as your main app. And let's face it, how often in real life does that situation happen? If it happens, you probably aren't using Gradle to the best of it's ability.
You want to follow the instructions for Package Manually in the google wear docs
https://developer.android.com/training/wearables/apps/packaging.html#PackageManually
Unfortunately, this will require you to build your wear app with the same applicationId as the particular build variant you are making at the time, but it does allow you to successfully package the wear app inside an app with multiple applicationId.
Also, one trick I do that helps is to not put the wear apk inside /res/raw, but in /assets, that way you don't have to deal with Andriod Studio compressing the apk.
Hope this helps! Drove me crazy for a couple days finding a solution. And the only tutorial out there is in French, and I had to translate the website to read it!
https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=http%3A%2F%2Fblog.octo.com%2Fpackager-une-application-android-wear-dans-la-vraie-vie%2F
So ultimately I'm trying to separate my integration tests from the unit tests in an Android Studio project. I've found a few resources on the subject:
http://selimober.com/blog/2014/01/24/separate-unit-and-integration-tests-using-gradle/
https://blog.safaribooksonline.com/2013/08/22/gradle-test-organization/
Separating integration tests from unit tests in Android Studio
All these seem to indicate that the way to go is to create a new sourceSet for the integration tests, and then to create a new test task which builds and runs the tests in that source set. I can't get past the first step of creating a source set which is recognized by Android Studio.
Here's what I have within app/build.gradle, which builds without errors, but does not result in an integrationTest source root I can add classes to:
android{
...
sourceSets{
integrationTest {
java.srcDir('src/integrationTest/java')
}
}
}
My questions are:
Where precisely do I have to add the sourceSets block? In build.gradle? in app/build.gradle? In app/build.gradle inside the android block?
Once I've added my source set in he right place using the correct syntax, is this sufficient for Android Studio to detect and present it in the UI along side the main and test sources, or are there additional steps?
edit:
I've attempted to follow the instructions in marius' answer, but integrationTest isn't showing up in my build variants. Here's what I'm seeing:
This is enough:
android{
...
productFlavors{
integrationTest {
}
}
}
Regarding your 1st question: The productFlavors block should be in your app/build.gradle, inside android block.
Regarding your 2nd question: Once you add this to your build.gradle file, you also need to create your folders /src/integrationTest and /src/integrationTest/java . Once that is done, sync your gradle files and choose your new Build Variant from the Build Variant window, in order for the IDE to detect it as the active source folder.
I'm dealing with a project that has a large number of dependencies. This has become a problem because when adding new SDK's we're going past the maximum limit of methods that an APK can hold (65536).
I'm looking at using the new build system in Android Studio in order to create build variants that rely on subsets of our dependencies. I was able to find a number of tutorials that help with creating different class alternatives using build flavours, but I didn't find anything regarding specifying different dependencies for each flavour. Is this even possible? What would the whole workflow look like?
For example, I would like to create a build variant that removes Flurry support. I would be able to create a different class that does not instantiate the Flurry SDK, but I would also like to be able to remove the lib dependency entirely, in order to reduce the total number of methods in the APK.
I'm also open to any suggestion regarding managing this kind of issue :)
This works (making sure dependencies are listed after productFlavors):
android {
...
productFlavors {
flavor1 { ...
...
dependencies {
flavor1Compile ...
}
But this won't work:
android {
...
dependencies {
flavor1Compile ...
}
...
productFlavors {
flavor1 { ...
...