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"
Related
I'm currently working on modularizing my application, so I'm putting each feature in a library module. In one of my features, I access the version code and name. However, although I defined them in the build.gradle file specific for that module
they were not there in the generated BuildConfig file
I cannot reference the BuildConfig file of the original :app module since I cannot let my feature modules have a dependency on that module.
is there an alternative way of accessing this info from the library module?
Version code and version name are properties of an application package and they are not supported for a library module.
At runtime, you can pass in a Context and access this application package metadata with the help of PackageManager. Example: Detect my app's own android:versionCode at run time
While the answer above is okay, IMO it's not the best way to go about it. Generally speaking, you want your version name and code stored somewhere outside of the build.gradle file. Very often we do that so we can easily access it from the outside of the app, or to update it automatically for CI systems, etc.
A very simple example: You can put those in the gradle.properties file, like so:
<!-- add to the end of the file: -->
VERSION_NAME=0.0.1
VERSION_CODE=1
Then you can simply access them in any build.gradle via properties object, and add them to BuildConfig like so (note: they will only become available after a successful build):
// build.gradle file of the chosen module
def versionName = properties["VERSION_NAME"]
def versionCode = properties["VERSION_CODE"]
buildTypes.all {
buildConfigField "String", "VERSION_NAME", "\"$versionName\"" // Escaping quote marks to convert property to String
buildConfigField "int", "VERSION_CODE", "$versionCode"
}
Alternatively, you can put those in a dedicated version.properties file. Then you can do the same like this:
def versionProps = loadPropertiesFile(project.file('version.properties'))
buildTypes.all {
buildConfigField "String", "VERSION_NAME", getPropEscaped("VERSION_NAME", versionProps)
buildConfigField "int", "VERSION_CODE", getProp("VERSION_CODE", versionProps)
}
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.
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.
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.