Android Gradle flavor to have less language support than Main - android

I want to have 3 product flavors, and one of them will have less language support than Main.
For example, only support /values-fr.
Is there a filter function in Gradle? Thanks.

From Android Gradle Build System, since version 0.7.0:
New option on product Flavor (and defaultConfig) allow filtering of resources through the -c option of aapt
You can pass single value (resConfig) or multiple values (resConfigs) through the DSL.
All values from the default config and flavors get combined and passed to aapt.
See "basic" sample.
In the "basic" sample:
defaultConfig {
...
resConfig "en"
resConfigs "nodpi", "hdpi"
}
So, try the following to achieve what you asked for:
productFlavors {
...
frOnly {
resConfig "fr"
}
...
}
Note that you might also want to include *dpi, port, land, etc.. as well

Related

Manage same Project with different package name in GIT

I have a project lets say Project A( Main Project/ Master). I need to create same projects but with same code and different package name Project B and Project C.
If the changes are applicable to all then I will make changes in Project A, so that if I update Project B and Project C automatically they should get the changes.
But if any customization came for project level then I need to change in Project B only. It should not affect to Project A or C. Like this how can I handle all three projects using git.
Will it work with using branches.?
Thanks in Advance...
Use build variants in your code, instead of relying on multiple branches in git. This way, a single source code can be generated as multiple applications.
android {
compileSdkVersion ...
buildToolsVersion ...
defaultConfig {
applicationId "com.yourapp"
...
}
// Specify the build dimension and flavors
flavorDimensions "type"
productFlavors {
typeA {
dimension "type"
applicationIdSuffix '.typea' // Add this to differentiate the application ID
versionNameSuffix "-typea" // Add this to differentiate version naming
}
typeB {
dimension "type"
applicationIdSuffix '.typeb'
}
typeC {
dimension "type"
applicationIdSuffix '.typec'
}
}
}
It doesn't matter if your classes are in the same package, as long as your application ID differs, you can install multiple version of the app at the same time on your device.
To build each specific app, simply change the chosen variant in Android Studio.
For specific flavor implementation in your code, you can use BuildConfig.FLAVOR to check which flavor the current application is.
when (BuildConfig.FLAVOR) {
"typeA" -> {
// Do stuff for typeA app
}
"typeB" -> ...
"typeC" -> ...
}

'ProductFlavor.resConfigs' has a value 'auto' which is obsolete and has not been replaced

How to fix the warning below? Are there any alternatives to 'auto'?
Warning:DSL element 'ProductFlavor.resConfigs' has a value 'auto' which is obsolete and has not been replaced. It will be removed at the end of 2018
android {
...
flavorDimensions "device", "paid", "market"
productFlavors {
phone {
// Phone config version for the application
resConfigs ("auto")
dimension "device"
matchingFallbacks = ['mobile']
}
...
}
...
}
This is the error after updating to Android Studio 3.1:
Based on the official advise here the best thing to do is removing the tag entirely if you support all the languages or supply an array with the language's code your app supports like:
resConfigs "en", "de", "it", "fr" // etc. etc.
More info:
This is one of the resources optimization proposed by the official documentation here so i decided to test this flag with those FirebaseUI dependencies in a sample project
implementation "com.firebaseui:firebase-ui-auth:$firebase_ui_version"
implementation "com.firebaseui:firebase-ui-database:$firebase_ui_version"
implementation "com.firebaseui:firebase-ui-storage:$firebase_ui_version"
creating the debug APK with both the options and those are the results:
Using resConfigs "auto" the debug APK was: 3,793 KB
Using resConfigs "en" (so 1 language only) the debug APK was: 3,294 KB
This means that with all the string resources for all the languages of those dependencies I got only ~500KB of size increase. That's something you could reason about, you definitely should make a test with the dependencies you use and see if the size increase is negligible or not and consequently decide to provide the list of supported languages or remove the resConfigs option.
PS: If you are using Android FirebaseUI this was one of the suggested optimizations, I've created an issue here about the thing and this has been solved immediately by the awesome guy called SUPERCILEX
auto is no longer supported because it created a number of issues with multi-module projects. Instead, you should specify the locale that your app supports. Android plugin 3.1.0 and higher ignore the auto argument, and Gradle packages all string resources your app and its dependencies provide.
com.android.tools.build:gradle:3.2.0-alpha08 BaseFlavor.java
* <p><b>Note:</b> <code>auto</code> is no longer supported because it created a number of
* issues with multi-module projects. Instead, you should specify the locale that your app
* supports, as shown in the sample above. Android plugin 3.1.0 and higher ignore the <code>auto
* </code> argument, and Gradle packages all string resources your app and its dependencies
* provide.

Android App Name Per Build Type AND Flavour

My application is having multiple build types and flavours gradle.
buildTypes {
release {}
test {}
debug {}
}
productFlavors {
europe {}
asia {}
}
How can I name the app according to the combination of build type and flavor?
Example:
Flavour europe will have app name AppEurope
BuildType test will add "Test" suffix behind the app name, AppEuropeTest
I was facing the same problem within my watch face and tried to combine flavor dependent application names with build type dependent application label values. I ended up doing it as follows:
Use manifestPlaceholder in the build.gradle to inject buildType specific string resource links:
In the build.gradle file:
buildTypes {
release {
manifestPlaceholders = [ applicationLabel: "#string/app_name"]
}
debug {
manifestPlaceholders = [ applicationLabel: "#string/app_name_dev" ]
}
}
In the AndroidManifest.xml:
<application
[..]
android:label="${applicationLabel}">
In the strings.xml file:
<resources>
<string name="app_name">Classic & Essential</string>
<string name="app_name_dev">Classic & Essential (DEV)</string>
</resources>
Use flavor specific versions of string.xml resource files overriding the values for the flavor.
I also described this in one of my blog posts:
https://www.journal.deviantdev.com/android-build-type-app-name-label/
Your questions has been answered here -
How to change app name per Gradle build type
Create separate versions of string.xml for each build type for all
the flavours.
There is a a sample project here.
https://github.com/commonsguy/cw-omnibus/tree/master/Gradle/HelloBuildType
Edit 1
android.sourceSets.europe {
res.srcDirs = ['flavor_resources/europe/res']
}
android.sourceSets.europe.debug {
res.srcDirs = ['flavor_resources/europe/debug/res']
}
Related link shows how to do this for flavors, and the concept is identical when expanding to include build types - we can think of both flavors and build types as combining to create "variants", and we can configure variants as easily as the flavors that make them.
Assume:
You have these build types:
release
test
debug
You have these flavors:
europe
asia
You have a default app_name string resource declared in the normal place
src/main/res/values/strings.xml
<string name="app_name">App</string>
Manifest file:
There is no need for manifest placeholders in this simple case. If your case requires, you can configure them as per the other answers.
Simply use app_name in the manifest directly. Trust that the changes you make for the variants will reflect correctly.
e.g.
<application
android:label="#string/app_name"
etc...
Different names for variants:
As standard, gradle allows for resource files to be declared at in variant source folders (like the flavor or build type source folders) and these will automatically override the defaults.
There is no need for source sets in this simple case.
Simply add a new strings.xml file for each variant, redefining the app_name to match that variant.
e.g. For the Europe Test build, add your file at the variant folder named europeTest, and override the name:
src/europeTest/res/values/strings.xml
<string name="app_name">AppEuropeTest</string>
Different variants will also get their own override strings files as required.
App name suffix per flavor:
With app ID, each flavor can be configured to add a bit to the app ID.
This is not currently possible with the normal build system, so you cannot currently configure the test build to append the name "Test" to the main name, and then configure the europe flavor to append "Europe".
That would be really nice, but is not supported natively.
This answer suggests a library that you can use for an alternative way of combining the app names, and could probably be used to make a more logical naming system, especially with more flavor dimensions (similar to how one would do it for application ID).

Override resources with gradle depending on buildType

I want to override some strings in my res/strings.xml with gradle.
I know that since Android Gradle Plugin 0.7.+ theres the possibilty to have a variant specific source folder.
But my app has a lot of flavors and I don't want to add additionally variant specific folders.
UPDATE 2014-01-17
What I want in detail:
I have some variables in my Resources that are depending only by the buildType (e.g. "release").
First I thought my SOLUTION_1 (override data after resources were merged) is nice, because if I have to change these variables I just have to change them in the build.config (just one place).
But as Scott Barta wrote in the comment below there are some good reasons why this solution is NOT a good idea.
So i tried another solution SOLUTION_2 (just merge the right resources) based on this GitHub project of shakalaca. I think this way is more elegant and I still have the advantage just to change the variables in one place!
SOLUTION_1 (override data after resources were merged):
What I did in AS 0.4.2:
in build.gradle I try to override the string "Hello World" to "OVERRIDE" (based on my answer at this post):
android.applicationVariants.all{ variant ->
// override data in resource after merge task
variant.processResources.doLast {
overrideDataInResources(variant)
}
}
def overrideDataInResources(buildVariant){
copy {
// *** SET COPY PATHS ***
try {
from("${buildDir}/res/all/${buildVariant.dirName}") {
// println "... FROM: ${buildDir}/res/all/${buildVariant.dirName}"
include "values/values.xml"
}
} catch (e) {
println "... EXCEPTION: " + e
}
into("${buildDir}/res/all/${buildVariant.dirName}/values")
// println "... INTO: ${buildDir}/res/all/${buildVariant.dirName}/values"
// --- override string "hello_world"
filter {
String line ->
line.replaceAll("<string name=\"hello_world\">Hello world!</string>",
"<string name=\"hello_world\">OVERRIDE</string>");
}
// *** SET PATH TO NEW RES ***
buildVariant.processResources.resDir = file("${buildDir}/res/all/${buildVariant.dirName}/values/values/values.xml")
// println "... NEW RES PATH: " + "${buildDir}/res/all/${buildVariant.dirName}/values/values/values.xml"
}
}
The copy and filter task works fine, but I couldn't set the "new" values.xml as string resource.
SOLUTION_2 (just merge the right resources)
define a floavor for specific buildType (e.g. "releaseRes")
merge this resourses with the flavor you want to build:
android.applicationVariants.all{ variant ->
variant.mergeResources.doFirst{
checkResourceFolder(variant)
}
}
def checkResourceFolder(variant){
def name = variant.name;
if(name.contains("Release")){
android.sourceSets.release.res.srcDirs = ['src/releaseRes/res']
android.sourceSets.flavor1.res.srcDirs = ['src/flavor1/res']
}
}
You should strive to come up with a solution that doesn't involve writing any custom code in your build files, especially code that does tricky things with reassigning source sets on the fly. Custom Gradle code is a little funky to write, and it's difficult to debug and maintain. The new build system is extremely powerful and already has tons of flexibility, and it's likely that you can already do what you want; it's just a matter of learning how.
Especially if you're just learning the ins and outs of Android-Gradle projects (and it's so new that we all are), it's best to try hard to work with the functionality built into the system before thinking outside the box.
Some recommendations:
It's unlikely you need to vary resources based on build type. A build type in Android-Gradle is supposed to be something like debug or release, where the difference is in debuggability, compiler optimization, or signing; build types are supposed to be functionally equivalent to each other. If you look at the properties you can set on a build type through the Groovy DSL, you can see the intent: debuggable, jniDebugBuild, renderscriptDebugBuild, renderscriptOptimLevel, packageNameSuffix, versionNameSuffix, signingConfig, zipAlign, runProguard, proguardFile, proguardFiles.
If you still think you want to vary resources based on build type, there's already an easy way to do that with the current build system. You can have a build-type-specific resource directory, put your resources in there, and the resource merging in the build system will take care of things for you at build time. This is one of the powerful features in Android/Gradle. See Using Build Flavors - Structuring source folders and build.gradle correctly for information on how to make that work.
If you want to vary something based on build type and your needs are very quick and simple, you might want to do the switch in Java code instead of resources and instead of in the build system. There's the BuildConfig mechanism for that sort of thing -- it's a Java class that defines a DEBUG flag based on debug/release build status, and you can add your own custom Java code from different build types to do more meaningful things. BuildConfig was intended for allowing small functional differences between build types, for cases where a debug build might want to perform some wasteful operation to assist in development, like doing more extensive data validation or creating more detailed debug logging, and those wasteful things are best optimized out of release builds. Having said that, it might be an appropriate mechanism to do what you want.
Consider using flavors for what you're using build types for now. Conceptually a flavor is kind of like a build type in that it's another variant of your application that can be built; the build system will create a matrix of flavors vs. build types and can build all combinations. However, flavors address a different use case, where different flavors share most code but can have significant functional differences. A common example is a free vs. paid version of your application. Inasmuch as a different resource in different variants of your app represents different functionality, that might indicate a need for a different flavor. Flavors can have different resource directories that are merged at build time in the same way as build configs; see the question linked above for more info.
I don't believe you need to customize the build script at all to achieve what you want. According to my reading of http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants; when the build runs, resources will be merged from the following folders, if they exist;
src/[flavour][buildType]/res
src/[buildType]/res
src/[flavour]/res
src/main/res
So I believe you can achieve what you want by simply add the resources in src/release/res.
Though you can tweak the folder names by specifying the relevant sourceSets.[type].res.srcDirs if you really want to change them.
If anyone stumble upon this
buildTypes {
debug{
buildConfigField "String", "Your_string_key", '"yourkeyvalue"'
buildConfigField "String", "SOCKET_URL", '"some text"'
buildConfigField "Boolean", "LOG", 'true'
}
release {
buildConfigField "String", "Your_string_key", '"release text"'
buildConfigField "String", "SOCKET_URL", '"release text"'
buildConfigField "Boolean", "LOG", 'false'
}
}
And to access those values using build variants:
if(!BuildConfig.LOG)
// do something with the boolean value
Or
view.setText(BuildConfig.yourkeyvalue);

Separate source files per build variant in Gradle (Android)?

Our application has a free and a paid version. We also make branded-versions, which means that the application vary in two dimensions.
Four versions could be:
The App, Nike ed. free
The APP, Nike ed. paid
The App, Adidas ed. paid
The App, Adidas ed. free
My solution now is to have two build-types, paid and free:
buildTypes {
paid {
packageNameSuffix ".paid"
}
free {
packageNameSuffix ".free"
}
}
And two build flavors:
productFlavors{
nike{
packageName "com.example.theapp.nike"
}
adidas{
packageName "com.example.theapp.adidas"
}
}
Every free-version of the app make us of a content-provider, a content provider which is specific per flavor-build type combination. The problem is that I don't understand where to put a source file based on build variant. Source files put into /src/nike or /src/free will be picked up depending on build type or flavor. But how about source files that are depending on the build variant (the combination of type and flavor)?
You can create a new folder under src for every build or flavor that you have. i.e: 'free', 'paid', 'nike', 'adidas'.
The files that you put in any of these folders gets picked up when building depending on the type and build both.
According to Gradle Plugin User Guide on Android Tools Project Site:
Similar to Build Types, Product Flavors also contribute code and
resources through their own sourceSets.
and
The following rules are used when dealing with all the sourcesets used
to build a single APK:
All source code (src/*/java) are used together as multiple folders generating a single output.
Manifests are all merged together into a single manifest. This allows Product Flavors to have different components and/or
permissions, similarly to Build Types.
All resources (Android res and assets) are used using overlay priority where the Build Type overrides the Product Flavor, which
overrides the main sourceSet.
Each Build Variant generates its own R class (or other generated source code) from the resources. Nothing is shared between
variants.
meaning that your java files for the buildType "free" will overwrite the ones for your flavors "nike" if they have the same name.
But if you're adding something to a manifest, according to the second point in the list above the final manifest will be a merge of all of the manifests.
If you need more customization you can put your files in your build variant's folder "src/freeNike/".
I had similar problem with build types overriding flavors due to the overlay rules.
I ended up redirecting the build type source sets into different folders depending on which flavor was built.
android.applicationVariants.all { variant ->
switch (variant.name) {
case "FreeNike":
variant.mergeResources.doFirst {
android.sourceSets.free.setRoot("src/freeNike")
}
break;
case "FreeAdidas":
variant.mergeResources.doFirst {
android.sourceSets.free.setRoot("src/freeAdidas")
}
break;
case "PaidNike":
variant.mergeResources.doFirst {
android.sourceSets.paid.setRoot("src/paidNike")
}
break;
case "PaidAdidas":
variant.mergeResources.doFirst {
android.sourceSets.paid.setRoot("src/paidAdidas")
}
break;
}
}
You are of course free to use a different folder structure. See example here: Folder naming convention for gradle build variants
Have a look at newest Gradle plugin it now allows to have variant specific resources
http://tools.android.com/tech-docs/new-build-system
And here You have example of usage
https://android.googlesource.com/platform/tools/build/+/master/tests/overlay3/
Have you tried to put the srcDir in the sourceSets ?
Like so:
sourceSets {
main {
java {
srcDirs 'src/java'
}
}
}
That should output a javaResources with two source codes, nike and adidas.

Categories

Resources