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.
Related
I have old apps using non compliant applicationId. I trying to migrate them with flavorDimensions to share so common assets & code.
I have this flavors setup :
defaultConfig {
applicationId "com.example"
}
flavorDimensions 'fruit', 'env'
productFlavors {
pear {
dimension 'fruit'
}
banana {
dimension 'fruit'
}
staging {
dimension 'env'
}
prod {
dimension 'env'
}
}
I would like to have these applicationId by flavor combination :
pearStaging : com.example.pear_staging (note the "_")
pearProd : com.example.pear
bananaStaging : com.example.banana_staging (note the "_")
bananaProd : com.example.banana
I have tried to use applicationIdSuffix :
productFlavors {
pear {
dimension 'fruit'
applicationIdSuffix 'pear'
}
banana {
dimension 'fruit'
applicationIdSuffix 'banana'
}
staging {
dimension 'env'
applicationIdSuffix '_staging'
}
prod {
dimension 'env'
}
}
but suffixes are separated with dot by default. So it's generate wrong applicationId, ex:
flavor pearStaging : com.example.pear._staging (note the "." before "_")
I saw answers on this thread :
How to set different applicationId for each flavor combination using flavorDimensions?
They talk about a workaround using mergedFlavor.setApplicationId(...) to override applicationId at the end. But this not working if I use in combination with google services gradle plugin.
Because during plugin process phase, I got this error :
* What went wrong:
Execution failed for task ':app:processPearStagingDebugGoogleServices'.
> No matching client found for package name 'com.example'
As you see, it use default applicationId/package name, not the appId overrided in android.applicationVariants.all phase.
So there is a better way to defined my applicationId per flavor combination that works with google services task ? (I need to keep these applicationId with "_", can't change it).
It is not possible with the current way that google services gradle plugin works. Maybe there's a way to feedback to Google about that, but meanwhile, the only way to achieve the application IDs with "_" is to rename the application ID after the apk is built. So, the flavour-specific application ID would be built with "." separators first, then rename the application ID after the apk is built.
This could be done with the standard procedure of using apktool to open the apk, change the application ID to what you need, then repackage with apktool, zipalign, re-sign, etc. If it may be too tedious, there are GitHub projects that attempt to do the same, but they may not work on all apks.
For example:
https://github.com/testwhat/PackageRenamer
https://github.com/sjitech/ApkRename
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" -> ...
}
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 have already asked similar question But could not find what i seek . Hence asking again .
I want to run separate flavor apk on same device simultaneously.
I have used build.gradle(app) to create different flavors of apk. But installing different flavors of same apk overrides the previous one. I want to create different apks to run on same device simultaneously. I want to create different apk with different appicon which can be installed on same device and run simultaneously. Any link or tutorial or direct help is appreciated.
My build.gradle is as below
productFlavors {
production {
applicationId
"com.abc.def"
buildConfigField 'String', 'HOST', '"http://example.com/api/"'
}
staging {
applicationId
"staging.com.abc.def"
buildConfigField 'String', 'HOST', '"http://example.com/api/"'
}
backendtesting {
applicationId
"backendtesting.com.abc.def"
buildConfigField 'String', 'HOST', '"http://example.com/api/"'
}
}
Do not put line breaks between the gradle command and it's argument. It will read each line separately since line breaks are command separators for gradle.(like how ; is for java)
For example, use:
applicationId "com.abc.def"
instead of
applicationId
"com.abc.def"
This post explains step by step how to configure your directory structure and gradle file.
The main steps are:
add the product flavours container to the app build.gradle file
productFlavors {
free {
applicationId "antoniocappiello.com.buildvariantsexample.free"
}
paid {
applicationId "antoniocappiello.com.buildvariantsexample.paid"
}
}
create inside src a directory with the exact name of the product flavour that you want to look different from the main variant, for example with the configuration at step 1 the directory name could be paid or free . And inside that directory create the subfolder res/drawable where you are going to place your new app launcher icon.
Directory structure example
You can set different applicationId for different flavors. In this way different flavors will be treated as different applications and will not overwrite each other when you install them on same device.
As an example, following snippet will create two flavors, prod and dev with different app packages. You can install them both together on the device.
productFlavors {
dev {
applicationId "com.swagata.devbuild"
}
prod {
applicationId "com.swagata.prodbuild"
}
}
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.