Android: Managing different server URL for development and release - android

I am developing an Android application that interacts with server via REST APIs. Obviously I need to use different URL for development and release builds. Commenting and un-commenting code is very tedious and error pron.
Which is the best way to handle this situation? Using different build types in gradle file is one which could automate the process, but I am not sure if this is the right way to go.
There is also a possibility of increase in number of build types viz. test, internal-release etc.

If you are using Android Studio, use buildConfigField to add custom fields to your BuildConfig class.
buildTypes {
debug {
buildConfigField "String", "SERVER_URL", '"http://test.this-is-so-fake.com"'
}
release {
buildConfigField "String", "SERVER_URL", '"http://prod.this-is-so-fake.com"'
}
mezzanine.initWith(buildTypes.release)
mezzanine {
buildConfigField "String", "SERVER_URL", '"http://stage.this-is-so-fake.com"'
}
}
Here, I have three build types: the standard debug and release, plus a custom mezzanine one. Each defines a SERVER_URL field on BuildConfig.
Then, in Java code, you just refer to BuildConfig.SERVER_URL. That field will have a value based on what build type you used to build that particular edition of the app.

It can be managed by using ProductFlavours in app build.gradle. ProductFlavours will manage different URL ie. development and release.
Please have a look it on medium.
It involves detailed explanation.

I had a similar issue and I solved it using
if (BuildConfig.DEBUG) { }
You will need to import
import com.commandsoftware.androidbookingapp.BuildConfig;

I had a similar problem with writing to logcat. I wanted to write all the messages if the app was signed with the debug key, otherwise write almost none of them. I solved the problem with this line of code:
boolean showAllMessages = ((getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
then using that boolean in my log writer. You should be able to do something similar when you initialize the URIs.
I am using Eclipse. I can't say with certainty that this will work in other IDE environments. This answer implies that it might be an Eclipse-only feature

Related

how to specify in case of an Android local development?

Is there a way to tell Android we are developing and testing the application locally ? so I can write something like that in the code to execute specific code that has to be executed in case of a local development vs when the application is intended to be deployed and fetch the right remote data :
if (LOCALLY) {
MyLocalTools.xdebugIntegration();
...
}
...
And when the application is to be shared, i just have to turn a global option to mute all the local code ?
If by "local development", you mean debug builds, and by "intended to be deployed", you mean release builds, you can use BuildConfig.BUILD_TYPE to distinguish those build types, or use BuildConfig.DEBUG to distinguish between builds that are debuggable versus those that are not. Or, if you need a particular constant, use buildConfigField to add that custom field to BuildConfig.
Product flavors, cited in another answer, are designed for cases where you need two separate release builds (e.g., one with Google's in-app purchasing APIs, one with Amazon's in-app purchasing APIs).
You can use build flavor and build variants.
In your build.gradle you can define some flavors like follows:
productFlavors {
dev {
buildConfigField "String", "SERVICE_URL_BASE", "\"dev.example/rest\""
applicationId "development.example.app"
}
prod {
buildConfigField "String", "SERVICE_URL_BASE", "\"prod.example/rest\""
applicationId "com.example.app"
}
}
As you can see we have defined 2 flavor with different variables to use. In my case I have defined two different endpoints for rest services and different application id.
Then on the bottom left of Android Studio you can select which build variant use to launch your app. Build variants are the union of build flavors and build types (defaults build types are debug and release).
In your code you can access variables defined in build.gradle file like follows:
BuildConfig.SERVICE_URL_BASE
And you can access your build type with of flavor with something like this:
BuildConfig.FLAVOR
BuildConfig.BUILD_TYPE
Using these variables you can implement all the switch you desire

Building two different android apps on the same codebase that only differ by const

I am building two android applications, which relay on the same codebase but differ by the server address which they grab their files from.
Till now i've created two line of my server's address constant, and builded the application once with the first const, and second with the second const.
Is there any way to make my app compile twice, once with the first constant, and second with the second one?
I am using Android studio with Gradle build.
Thank you!
You can use product flavors to teach Gradle to build two separate copies of your app, where your server address is defined in BuildConfig:
android {
// other stuff here
productFlavors {
flavorOne {
buildConfigField "String", "URL", '"https://..."'
}
flavorTwo {
buildConfigField "String", "URL", '"https://..."'
}
}
}
In your Java code, refer to BuildConfig.URL to get the URL to use.
Yeah, you can use Build Variants. You can move those strings into resources under the variants directory and the build will pull in the right one.
Here's the link to the full documentation for how to set them up: https://developer.android.com/studio/build/build-variants.html

Add build machine signature to gradle generated variable

I'd like to stamp some variable generated from gradle (in my case it's User Agent used later with HTTP requests) to later be able to distinguish which developer build the app (for example if some developer made a mistake and his app is DDoSing the server).
So for now I can distinguish release from debug with:
buildTypes {
debug {
buildConfigField "String", "USER_AGENT", "\"Android-debug\""
}
release {
buildConfigField "String", "USER_AGENT", "\"Android-release\""
}
}
But for the debug I'd like to add something to know who built the app instance, it may be git login, machine name, or something else.
A gradle build file is actually Groovy code, and you're free to put whatever you want in it. You just have to make sure that the code runs before it would be used in the DSL that describes the build. So if you want to grab something from the system, just write the Groovy code to do that. Groovy is a lot like Java, and you have the full JDK to work with at runtime, so it should be easy to get started.
If you want to access things about the build machine and environment, you might have to shell out to different commands in order to gather that data. Populate some variables with that data. Then use buildConfigField as you already are to drop those values into BuildConfig.java.
Bear in mind that you might want to provide some value in both debug and release so they both generate the same BuildConfig symbols. Otherwise your app might not compile in one config or the other.
BTW. You can tell the difference between debug and release with properties that are already added to BuildConfig, so you don't need to add anything more to tell the difference. Lines like these will always appear (look in the generated BuildConfig.java to see for yourself):
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String BUILD_TYPE = "debug";

Android Studio + Gradle to create different configurations

I am using Android Studio and Gradle to build Android applications. I would like to have different strings within the Java code based on which type of build it is (debug vs. release). What is the best way to do this?
For example - I want to have different URLs if I am in debug or release. Also, I want to specify different GUIDs and other keys / strings.
The obvious hacky way to do this is to do a search and replace of a string in AndroidManifest.xml or worse yet, in a Java file. This approach seems error prone and hacky to me - is there a better way to do this?
There are many ways you can do this, although I usually do
android {
buildTypes {
release {
buildConfigField("String", "URL", "your_url_on_release")
}
debug {
buildConfigField("String", "URL", "your_url_on_debug")
}
}
}
You then can access them on your java code by using:
BuildConfig.URL
You can test this using Android Studio Build Variants, by changing your application variant to debug or release ( e.g. http://prntscr.com/8waxkw)
You have many solutions to do this, here's a simple case:
buildTypes {
debug { ... }
release { ... }
}
productFlavors {
staging { ... }
production { ... }
}
build types are for build management proguarding, debugging, signing, etc.
productFlavors are for all app internal configuration.
If you want to add resources related to the flavours you can create and add to src/(flavor_name)/res/values/ folder your urls.xml config file.
With this, in android studio, you'll directly see, all the builds variants in the corresponding window and the right urls.xml file associated to the current context and leave the gradle config clean.
Of course, this method works also for any resource you would need in your app.
For more detail, you can read this : http://developer.android.com/tools/building/configuring-gradle.html#workBuildVariants
I would do it with product flavors as explained in this post.

How to define static String values in Android that change for test configurations with Gradle?

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.

Categories

Resources