On our Android app we're passing strings resources via build script using the resValue, something like this:
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
resValue "string", "foo", "foo_value"
resValue "string", "bar", "bar_value"
... etc
How to add translated version of those strings. To go on values-de, values-ch, values-sp, etc folders?
Apparently it is not possible to do it from the gradle file as mentioned here. If you just want to use the values, better use the buildConfigField instead
Related
Is it possible to build apk with more than 1 product flavor?
For example:
I have a Project with 3 flavors (App1 - App2 - App3).
and each app has its own configurations such as applicationId and so on.
and now I want to build different templates (different XML layouts), and the user should be able to switch from layout to another from inside the app.
My problem is the res folder will be huge and it will be hard to maintain, so I'm trying to find a way to separate the different layouts and keep it clean as much as possible.
And if it's possible to do so, then how do I intent or restart the app to the other flavors build?
Another thing I had in mind was to build all XML files in the main res and choose different qualifiers like when we do while creating different screen size (sm - larg - etc.. ) but i couldnt find anyway to add custom qualifiers.
My Gradle code is like this :
flavorDimensions "default"
productFlavors {
demo {
applicationId "test.demo"
versionCode 2
versionName "1.1.2"
resValue "string", "backage_name_file", "test.demo.fileprovider"
resValue "string", "bc", "com.demo"
resValue "string", "bc_e", "extra_data.com.demo"
resValue "string", "default_hostname", "demo.test.com"
resValue "string", "default_username", "demo"
resValue "string", "default_password", "demo"
}
AppOne {
applicationId "test.AppOne"
versionCode 2
versionName "1.1.2"
resValue "string", "backage_name_file", "test.AppOne.fileprovider"
resValue "string", "bc", "com.AppOne"
resValue "string", "bc_e", "extra_data.com.AppOne "
resValue "string", "default_hostname", "AppOne.test.com"
resValue "string", "default_username", "AppOne"
resValue "string", "default_password", "AppOne"
}
AppTwo {
applicationId "test.AppTwo"
versionCode 2
versionName "1.1.2"
resValue "string", "backage_name_file", "test.AppTwo.fileprovider"
resValue "string", "bc", "com.AppTwo"
resValue "string", "bc_e", "extra_data.com.AppTwo"
resValue "string", "default_hostname", "demoAppTwotest.com"
resValue "string", "default_username", "AppTwo"
resValue "string", "default_password", "AppTwo"
}
}
You cannot build an APK with multiple flavours, just as you cannot build one in both debug and release buildTypes. The selected flavour's config / resources gets pulled into the actual APK metadata / manifest, so cannot be modified at runtime.
You will need to include all of your content inside the res folder, but there are a few ways that may help make it easier to manage. I'd recommend the first 3 options, and the 4th if you have a very large number of code + layout files with different behaviour:
Use Fragments to avoid most of your Java / Kotlin code needing to be duplicated.
Include XML layouts instead of redefining everything each time to reuse common elements.
Carefully name your files, for example template1_background, template2_background.
Use multiple modules, one for each "template". You'll then have multiple sensible res folders.
I can see why flavours might have seemed like the solution, but since you need all flavours in one app, this approach is unfortunately not going to work. You'll likely find step #2 will remove almost all of the duplicate files, avoiding the issue entirely!
You can merge resources from different flavours using sourceSets command.
SourceSet Allows you to congifure buildVariants resources folders
for example you can configure your App2 flavour to include App2 res folder and App1 res folder.
Example code:
sourceSets {
App2Debug{
res.srcDirs = ['src/App1/res', 'src/App2/res']
}
}
How do I take an environment variable at build-time and make it available as R.string.api_key at app runtime?
A typical pattern is to put the string in gradle.properties:
API_KEY=whatever-it-is
If you really want it to be a string resource, you can then use resValue in build.gradle:
defaultConfig {
// other stuff here
resValue "string", "api_key", API_KEY
}
(as values in gradle.properties get exposed as global variables to your Gradle script)
Or, if you need the value in Java code, you could use buildConfigField:
defaultConfig {
// other stuff here
buildConfigField "String", "API_KEY", '"'+API_KEY+'"'
}
then reference it as BuildConfig.API_KEY.
And, of course, do not check gradle.properties into version control.
I need your help. I wish to add the build name of my app to the gradle file. The thing is I do NOT want it to be visible to user on the market, so this:
versionName "3.1.0.5486"
does not suits me. But I need it in a way so I can read it via code (In the about screen for example) and increment it each build. How can you advise me?
Just use standard versionCode parameter. You can read it from code using
BuildConfig.VERSION_CODE.
You can set the version code and name inside the defaultConfig element in the build.gradle:
defaultConfig {
versionCode 1
versionName "1.0"
}
And use it as is:
String.format(getString(R.string.some_text_with_int_placeholder), BuildConfig.VERSION_CODE);
If you want create your own variable just use buildConfigField, something like:
buildTypes {
debug {
buildConfigField "int", "FOO", "42"
buildConfigField "String", "FOO_STRING", "\"foo\""
buildConfigField "boolean", "LOG", "true"
}
}
And access it via BuildConfig.FOO
I'm interested in defining my many flavors of my apps more so in the strings.xml files rather than the build.gradle. Given multiple flavors, I'd like a simplified release/debug variant:
buildTypes {
release {
signingConfig signingConfigs.release
resValue "string", "app_name", "#string/prod_name"
}
debug {
applicationIdSuffix ".beta"
resValue "string", "app_name", "#string/beta_name"
}
Then in each of my build flavors' custom res/values/strings.xml files, I would define each their own "prod_name" and "beta_name". I also want to use this similar framework for defining providers' authorities etc...
This currently will build fine via gradle command-line, but fails to be recognized by Android Studio.
Android Studio Error:
I find this within 'generated.xml'
<!-- Values from build type: debug -->
<string name="app_name">#string/beta_name</string>
Which is typical of how one string references another. But this time Android Studio gives me this error:
Error:(7, 29) No resource found that matches the given name
(at 'app_name' with value '#string/beta_name').
I'm using Android Studio 2.1 Preview 5
This is actually possible. All you have to do is declare those strings as empty in your defaultConfig, like this:
defaultConfig {
resValue "string", "prod_name", ""
resValue "string", "beta_name", ""
}
In my experience you can't resolve a #string/my_string in the resValue DSL. Gradle put the value as a simple string inside the resource file.
In this case you can use different folder to achieve it:
Just use:
src/release/res/values/strings.xml
src/debug/res/values/strings.xml
If you would like to use different resource for each build variant (build type+flavor) you can use:
src/flavor1Release/res/values/strings.xml
src/flavor1Debug/res/values/strings.xml
src/flavor2Release/res/values/strings.xml
src/flavor2Debug/res/values/strings.xml
It is possible you can add res values inside the gradle for your build flavors
productFlavors {
prod {
dimension "default"
resValue "string", "app_name", "your prod app name"
}
staging {
dimension "default"
resValue "string", "app_name", "your staging app name"
}
}
I'm devolping an android app that heavily uses Rest Services.
For developing and debugging, I run the Rest server locally (on my notebook). At home, I have static IP Adresses and therefore, I can put
a static String in my build.gradle.
But if I work from somewhere else, I always have to check my notebook's ip address and edit my build.gradle.
Now I'm curious: Is there a way to insert the current local IP address into my build.gradle automatically?
android {
...
buildTypes {
debug {
...
resValue "string", "host_name", "192.168.0.102" // <--- should be set automatically
}
release {
...
resValue "string", "host_name", "example.com/rest/"
}
}
You can use Groovy methods to find the local IP address:
resValue "string", "host_name", InetAddress.localHost.canonicalHostName
Alternatively you also could use hostAddress instead of canonicalHostName.
I'm adding an awser because I'll probably need this in the future
In build.graddle of the project add into default config the buildConfigField line :
defaultConfig {
applicationId "com.foo.bar"
minSdkVersion 25
targetSdkVersion 25
buildConfigField 'String', 'IP_LOCAL_SERVER', "\"${InetAddress.localHost.hostAddress}\""
}
Then in you code you can call
localIP = BuildConfig.IP_LOCAL_SERVER;