I have an old maven project which I'm trying to migrate over to gradle for practice. It uses a configurations.properties file to configure different apks. For example, I would use it set a boolean for the target marketplace, and would do this from the command line like so:
mvn install -DexampleFlag=true
There are a few of these flags, and they are used at various points throughout the app. Is there a way to create this file using gradle?
Or, of course, if you have a better solution I'd be happy to hear that too.
EDIT
Okay, so I've got flavors, and I'm adding values to fields in the generated BuildConfig class like so:
android {
flavor1 {
buildConfigField 'boolean', 'EXAMPLE_FLAG', 'true'
}
}
And that works for the main app subproject. However, I also have an api subproject which needs to be able to access the flags too - which it can't, as the app subproject is the one with the flavors. If it helps, the api subproject is a dependency of app.
Any help here is appreciated.
Usually, this wouldn't be managed using flags but by defining multiple application flavors. For more information on flavors, see the Android Gradle plugin docs.
Related
Short question:
How can I change the package name for debug or release build type in a library module?
Context:
In an Android project with MVP + Clean architecture, we have the repository pattern in a library module. We want to include Firebase on that library with two environments (development and production).
I already created the project in Firebase (com.example.com and com.example.com.dev) and then downloaded the respective google-services.json to src/main and src/debug folders.
Gradle google-services plugin validates the module package name with the client ID defined in the google-services.json, but Android restrict to change the applicationId in a library (I can't find the technical reason why)
Things that I tried:
Have two AndroidManifest.xml with different package property. com.example.com in the src/main and com.example.com.dev in src/debug/ but the second one it is just ignored
Set manifest.srcFile in Gradle sourceSets. The file is in the list when I run ./gradlew sourceSets but the package name doesn't change
Two different flavors in the library module and set different manifests for each one. The package anyway doesn't change.
At this moment I have just two suitable solutions:
1. Keep the Firebase setup and implementation in the app module outside of the repository.
2. Have only one environment for Firebase.
Thanks a lot for any help or advice.
EDIT:
Consider that I need to modify the package in a module (library), not in the app. For some weird reason Gradle shows this error when I try to use applicationIdSuffix or applicationId in a module:
ERROR: Library projects cannot set applicationIdSuffix.
Library projects cannot set applicationId.
This is the designed behaviour of Android Library project.
Two different flavors in the library module and set different
manifests for each one. The package anyway doesn't change.
Probably you need to change your Build Variants to that particular flavor/buildtype then you can see the updated package name taking effect.
See below screenshot.
I spent some time investigating and trying different alternatives to achieve two different package name per flavor or build type in a library module, and my short answer is: You can't, at least without doing something tricky and dirty.
Some guys that recommend using the parameter applicationIdSuffix or applicationId, that option doesn't work because of the design of library modules restricts those parameters to the app module. In a library, the package must be defined in the manifest.
That restriction delimits options to flavors, but, the package attribute in the manifest isn't merged, and you get an error when having different package name for the scr/main/AndroidManifest.xml and src/flavor/AndroidManifest.xml.
A tricky solution is to get the currently selected flavor form the task name and then change the main manifest in the sourceSets.
sourceSets {
main {
manifest.srcFile "src/$flavor_name/AndroidManifest.xml"
}
}
This hack works but in general is a bad idea, and I prefer to change the design of my architecture and implement the repository for both Firebase variants in a different way.
Gradle plugin: 3.2.0
I have 3 jar files in my Android project's app/libs folder:
api-dev.jar
api-qa.jar
api-prod.jar
I want to use api-dev.jar when I work on the app in the studio (default), build a version of the app using api-qa.jar which will be tested by the QA team, then release the production app with api-prod.jar.
How should I do?
So far I read that I should add a
configurations {
qaCompile
...
}
element to app/build.gradle and use
android {
buildTypes {
...
qa {
...
}
}
}
to define the builds.
I don't know how to point to the appropriate libs/dependencies, I don't know how to make one the default one either, especially in my case where the default one is not the one for the production release...
Also if the API requires a specific key for dev, qa and prod, how do I set it up?
By the way the features are exactly the same between the different builds, the user experience is exactly the same, it's why I want to use builds, not flavors.
Check this out - Add dependency to specific productFlavor and buildType in gradle
Add you jars to the libs directory
Create a build type and product flavor
Use the name to create a specific compile command
Use that to specify your jar file in the libs directory
I have an app with more than a few buildFlavors and three different buildTypes.
I generate the signed apks from Build -> Generate Signed APK.... (Unless there is no other go I'd like to continue using the wizard and not create a script, because i have a constantly increasing set of apps and do not want to modify the script every time.)
The generated apks are named in the following pattern:
app-flavorName-buildType.apk
How can i change the naming pattern to something like this:
app_flavorName_buildType_versionCode.apk
Changes I want to make:
Suffix file name with versionCode
Replace hyphens with underscores
I used to do it in ant using task, but not sure how to do it with gradle.
Trying to figure a solution to create the name straight away in the new pattern rather than trying to rename it once it is generated. Is that possible?
I tried looking under Settings -> Gradle but did not find anything. Any other place i should be looking?
It is not exactly what you are looking for.
You can use your build.gradle to set this attribute:
android {
//...
defaultConfig {
//...
project.ext.set("archivesBaseName", "app_"+ defaultConfig.versionCode);
}
}
Assigning the archivesBaseName you will obtain something like:
app_0.9.6-flavorName-buildType.apk
This attribute requires the gradle-plugin 1.3.1 or higher.
Otherwise you have to use a task to rename the apk after building.
If I set a property in my gradle.properties file using the command line like so:
gradle build -Dproperty=myString
and in my Android project have a configuration.properties in my resources directory, how can I get configuration.properties to read the new property from the gradle.properties file?
I've tried the following setup:
gradle.properties
property=defaultString
anotherProperty=defaultBoolean
configuration.properties
myProperty=#property#
POTENTIAL SOLUTION 1
Using a configuration.properties file for each flavor.
The per-flavor resources sounded like a great idea, but I wanted to have a default list in main, and only override the properties needed. I have a lot of properties, and some flavors would only need to override one. So this does work, but is not ideal.
POTENTIAL SOLUTION 2
Using buildConfigField to pass what I need to the Java code.
The problem here is that I have two modules: app and api - where api is a dependency of app. Setting a buildConfigField in the app build.gradle lets me access them in the app code, but I would also need to access it from the api module.
To vary property values per flavor, you can use per-flavor resource files. For more information, check the Android Gradle plugin docs.
PS: If the property values are only used to activate different parts of the codebase, consider using per-flavor code instead.
Is it possible to have an Application subclass that's used only for tests when building with gradle? I've done something like this in the past before the gradle build system, but I can't find a way to do so now. The problem seems to be that it's impossible to customize the AndroidManifest.xml used for the instrumentation test APK.
You can create build variants which would at let you have a different version of the Application class and let you override the manifest. You could then test only that specific variant. http://tulipemoutarde.be/2013/10/06/gradle-build-variants-for-your-android-project.html
http://tools.android.com/tech-docs/new-build-system/user-guide
"For instance, if the flavors are used to generate a ads-based app and a paid app, one of the flavors could have a dependency on an Ads SDK, while the other does not.
dependencies {
flavor1Compile "..."
}
In this particular case, the file src/flavor1/AndroidManifest.xml would probably need to include the internet permission."