Let's say we have strings_test.xml, which stores string values for testing and should be shown in a debug-release. When the apk gets build as a release version all values should be change to an empty string e.g. <string name="test_some_card_text">#string/empty</string>.
Is there a possibility to achieve this?
As always, thanks in advance.
Yes you can do that inside your app gradle under buildTypes..
buildTypes {
mybuild {
resValue "string", "test_some_card_text", '"test"'
resValue "string", "other_text", '"other"'
}
debug {
resValue "string", "test_some_card_text", '"test"'
resValue "string", "other_text", '"other"'
}
}
Then access it like this.
getApplicationContext().getResources().getString(R.string.test_some_card_text);
getApplicationContext().getResources().getString(R.string.other_text);
For build you need to select that build variants and have to build it.
Yes, Gradle lets you override strings.
Add this inside buildTypes{} in your app/build.gradle
debug {
applicationIdSuffix "debug"
}
That should create a directory titled debug next to main. If not then manually create one. (Seriously, I haven't tried this, but I know this is possible.)
Then if your strings_test.xml is under res/values, create similar directory structure under debug/ and put your strings_text.xml with debug specific strings there. This will show up in your debug build. The ones under release/main/res/values will show up in your release build.
PS: You can override all res and asset data like this according to buildTypes and flavor. You can't override Java files though, you could however add them.
As #Aditya Naik said it is possible using Flavors.
Official doc says
BuildType -> Flavor -> main -> Dependencies.
This means that if a resource is declared in both the Build Type and in main, the one from Build Type will be selected.
Note that for the scope of the merging, resources of the same (type, name) but different qualifiers are handled separately.
This means that if src/main/res has
res/layout/foo.xml
res/layout-land/foo.xml
and src/debug/res has
res/layout/foo.xml
Then the merged resource folder will contain the default foo.xml from src/debug/res but the landscape version from src/main/res
for more info visit Official doc - Resource Merging
It is not possible to change the string value after creation of the apk.
But you can assing the value to text or edittext ... etx dynamically after creation of the apk.
For those who come here looking for some way to apply a similar method to raw resources, I dealt with it using buildConfigField.
gradle
...
buildTypes {
debug {
...
buildConfigField "int", "shared_resource_name", 'R.raw.debug_resource_name'
...
}
prod {
...
buildConfigField "int", "shared_resource_name", 'R.raw.prod_resource_name'
...
}
}
Pay attention to the quotes. After that, place BuildConfig.shared_resource_name in the files wherever R.raw.resource_value used to be accessed directly.
This can be used to other resources I think.
Related
When I develop my application and correct it once and again, I would like to see if the one running now is the last I built. Hence, I would like to add a field, say a TextView, that will display the build time-of-day (e.g., 19:26).
How can I take the build time and embed it in activity_main.xml?
BTW - build version, a counter that progresses with every build, is also good. Anything that will indicate the last build.
Assuming that you're building with Gradle, you can add a BuildConfig field with the desired information in your app/build.gradle:
android {
defaultConfig {
def buildTime = new Date()
buildConfigField "String", "BUILD_TIME", "\"${buildTime.format('yyyy-MM-dd HH:mm:ss')}\""
... other stuff ...
}
...other stuff ...
}
And then in your Kotlin/Java code:
myTextView.text = BuildConfig.BUILD_TIME
Another alternative is to replace the buildConfigField line in the above example with:
resValue "string", "build_time", "${buildTime.format('yyyy-MM-dd HH:mm:ss')}"
Which creates a string resource that you can use in your layout XML file, e.g.:
android:text="#string/build_time"
In my android app I have a file that I want to override for a specific flavor.
My structure:
However when I build the funki flavour I still see that the Computer class from main is used.
In my build.gradle I have:
productFlavors {
somename{
resValue "string", "app_name", "some name"
}
funki {
resValue "string", "app_name", "Funki App"
applicationIdSuffix ".funki"
}
}
Every build I see that the Computer file from main is used.
All the other overrides e,g, res files are overriden based on the flavor i build.
How can I override a class for a specific flavor?
You should be getting a "duplicate class" build error — at least, that used to be the behavior. You cannot override a Java/Kotlin class in a flavor.
What you can do is remove the Java/Kotlin class from the main source set and have it in all of your flavors. So, move Computer.java from main to somename, and keep your other Computer.java in funki.
I ended up checking the productflavor inside the code like:
if(BuildConfig.FLAVOR.equals("funki")){
Based on the if/else I execute my desired code.
I want to do something like that: gradle build DemoApp, and have DemoApp.apk with application name "DemoApp" as output.
Also, can I change application icon if with the same flow?
And some inner parameters?
Product flavors - not a secret for me. I do not need different configurations, I need to change application name at the build time. For example, I have some Rest API, that allows to pass parameter and return apk with application named as that parameter. The same with icon and other.
Checkout Manifest Merger specifically placeholders. Below is an example of setting the app name in gradle file.
// AndroidManifest.xml
<application
android:label="${applicationName}"
// build.gradle
buildTypes {
release {
minifyEnabled false
manifestPlaceholders = [applicationName: "MobileWorkforce"]
}
The other option is to use #string/app_name and define different string.xml files based upon buildType/flavor.
Given that you don't know how to use flavours properly, a mix of other solutions.
AndroidManifest.xml
<application
android:label="${applicationName}"
MyHttpThing.java
callserver(BuildConfig.ENDPOINT + "/api/v3/", "stuff")
build.gradle
buildTypes {
release {
minifyEnabled false
manifestPlaceholders = [applicationName: myappname]
buildConfigField "String", "ENDPOINT", myendpoint
}
and call with
gradle -Pmyappname=namy_name_name -Pmyendpoint="http://google.com" build DemoApp
Looks like you're looking for Product Flavors, they're exactly for having multiple customized versions of the app with shared codebase. You can customize the icon, as long as any other resource. And yes, the .apk will be named according to the name of the flavor.
I am using gradle.build for auto building my app. I want to generate three different APK's each pointing to different Service URL's.
How can I make use of buildVariants (productFlavors in gradle). But I'm not able to figure out where to set the three URL's in the Gradle.
How can I do this?
It is really easy to do with gradle.
productFlavors {
first_server {
buildConfigField "String", "SERVER_URL", "\"https://first_server_url/\""
}
second_server {
buildConfigField "String", "SERVER_URL", "\"https://second_server_url/\""
}
}
You may want to find more information here.
So later you can easy access this variable by BuildConfig.SERVER_URL
You can use as like following,
In Gradle:
productFlavors{
serverone {
applicationId "com.example.krishna.mysample.serverone"
version 1.1
}
servertwo {
applicationId "com.example.krishna.mysample.servertwo"
version 1.1
}
serverthree {
applicationId "com.example.krishna.mysample.serverthree"
version 1.1
}
}
In folder structure In App:
src
-->main
-->serverone
-->servertwo
-->serverthree
If MainActivity is required to different logic then, that MainActivity is place in serverone, servertwo and serverthree folder remaining classes are keep in main folder only. And do diffent functionality on that Activities.
Hey I am trying to statically define String values that change according to the configuration I am running. So if I run a test configuration, it uses the test API url, but if I run a regular build, it statically sets the real API URL.
I am using two strings files right now, one in the main folder and one in the androidTest folder in Android Studio. This works well for getting different Strings per configuration, but I'de like to do it statically rather than dealing with Resource fetches.
Is this possible?
I have seen this answer for ANT, but I am not sure how to do it with Gradle.
You can generate gradle constants like this:
build.gradle
android {
buildTypes {
debug {
buildConfigField "String", "FOO", "\"foo\""
}
release {
buildConfigField "String", "FOO", "\"bar\""
}
}
}
And access them in your code through BuildConfig.FOO
Note you may need to clean and/or restart your IDE for the to come in to effect.