I have the next chunk of code in my build.gradle:
productFlavors {
//DIMENSION - APP
slid {
dimension "app"
applicationId "com.slid"
versionCode 1
versionName "1.0.0"
manifestPlaceholders = [one_app_id : "273e0-b8f-4c7f-87-0f4eb68da"]
}
}
What I want to do is access one_app_id from manifestPlaceholders inside my java code.
As I was unable to do so (or at least I was unable to find a way), I want to define a buildConfigField String with the same value 273e0-b8f-4c7f-87-0f4eb68da but I'd like to make it a reference to manifestPlaceholders/one_app_id so I don't write the ID two times.
My question is:
buildConfigField "String", "ONE__ID", '[reference_here]'
What do I set instead of [reference_here] ?
OR
How can I do i the other way, i.e. have the ID set as a buildConfigField and then set that reference in the manifestPlaceholder
For example manifestPlaceholders = [one_app_id: [?!reference_here?!]]
P.S. don't worry, the ID is not valid :)
Based on CommonsWare's suggestion I've managed to do it like so:
ext {
oneAppId = ""
}
android {
productFlavors {
//DIMENSION - APP
slid {
dimension "app"
applicationId "com.slid"
versionCode 1
versionName "1.0.0"
ext.oneAppId = '"273e0-8567-558da"'
manifestPlaceholders = [one_app_id : ext.oneAppId] //Used by the third party library
buildConfigField "String", "ONE_APPID", ext.oneAppId //I'll use this in java
}
}
}
Related
I need to build an application created with a flavor and create a dynamic variable who points to an applicationId of another flavor (Because the code of an internal library uses the applicationId of other applications) but I don't know how to do that.
Here is the sample code :
defaultConfig {
applicationId "com.sample.mycompany"
}
buildTypes {
release {
}
qualif {
applicationIdSuffix = ".qual"
}
debug {
applicationIdSuffix = ".dev"
}
}
flavorDimensions "client", "nature"
productFlavors {
ClientA {
dimension "client"
applicationIdSuffix = ".A"
}
ClientB {
dimension "client"
applicationIdSuffix = ".B"
}
NatureX {
dimension "nature"
applicationIdSuffix = ".X"
}
NatureY {
dimension "nature"
applicationIdSuffix = ".Y"
// A buildconfigField variable here to get com.sample.mycompany[client].X[buildTypes]
}
NatureZ {
dimension "nature"
applicationIdSuffix = ".Z"
// A buildConfigField variable here to get com.sample.mycompany[client].X[buildTypes]
}
}
When I compile with the Build Variant : ClientANatureYDebug
, final applicationId is com.sample.mycompany.A.Y.dev
I want a dynamic variable with buildConfigField (or something else to retrieve the new variable in Java) who is com.sample.mycompany.A.X.dev
I think to get the final applicationId and replace the applicationIdSuffix of the current nature compilation dimension by .X and get the result in a new variable but I do not know how. Can you help me ?
Fixed with :
buildConfigField "String", "VAL_SHARE_TO_RECEIVER_APP_ID", "APPLICATION_ID.replace(\".Y\", \".X\")"
I don't figure out how can I set a resource value (resValue) in my build.gradle, depending on the build variant selection.
Here a bit of explanation.
I'm working with the Skype For Business SDK (hereafter referred to as Sfb) and during is implementation, it ask me to add a resource value named ENTERPRISE_AUTHENTICATOR_ACCOUNT_TYPE.
So I was looking in their application example (available here) and found that in build.gradle they have added as follow the corresponding value :
android {
...
defaultConfig {
applicationId "com.microsoft.office.sfb.sfbdemo"
...
resValue ("string", "ENTERPRISE_AUTHENTICATOR_ACCOUNT_TYPE", "${applicationId}"
}
...
}
This value then used in a SfbSDK class, checking if it match the application package name.
And here is my trouble, I work with different flavorDimensions as describe in my build.gradle below.
apply plugin: 'com.android.application'
...
android {
...
defaultConfig {
applicationId "com.tsp.test"
...
resValue ("string", "ENTERPRISE_AUTHENTICATOR_ACCOUNT_TYPE", "${applicationId}"
}
...
flavorDimensions("customer", "version")
productFlavors {
a {
dimension "customer"
applicationIdSuffix ".a"
}
b {
dimension "customer"
applicationIdSuffix ".b"
}
alpha {
dimension "version"
applicationIdSuffix ".alpha"
}
beta {
dimension "version"
applicationIdSuffix ".beta"
}
release {
dimension "version"
applicationIdSuffix ".release"
}
}
}
...
Depending on my build variant selection, this will generate me 6 different APK :
com.tsp.test.a.alpha ; com.tsp.test.a.beta ; com.tsp.test.a.release
com.tsp.test.b.alpha ; com.tsp.test.b.beta ; com.tsp.test.b.release
So when the match checking is does, my application crash with the message error
Caused by: java.lang.RuntimeException: ENTERPRISE_AUTHENTICATOR_ACCOUNT_TYPE string not set to applicationId
at com.microsoft.office.sfb.appsdk.Application.initialize(Application.java:110)
at com.microsoft.office.sfb.appsdk.Application.getInstance(Application.java:144)
at com.tsp.test.RootActivity.onCreate(RootActivity.java:89)
Of course, because com.tsp.test doesn't match com.tsp.test.a.alpha (or any other APK).
How can I achieve a dynamic resValue depending on the build variant selected that match the right application package name ?
EDIT :
To explain a bit more. First I choose the Build Variants as follow :
Customer : A
Version : Alpha
Then, in my RootActivity#onCreate() (my launcher activity), I start to configure the SfbSDK with an application instance depending on the SfbSDK :
this.mApplication = com.microsoft.office.sfb.appsdk.Application.getInstance(this.getApplication().getApplicationContext());
Somewhere in getInstance() method, the SfbSDK do an equals() between the context.getPackageName() and context.getString(string.ENTERPRISE_AUTHENTICATOR_ACCOUNT_TYPE);
So, for debug, in my RootActivity#onCreate() I just wrote this two lines
String whatIWant = this.getPackageName(); // give me *com.tsp.test.a.alpha*
String whatIGet = this.getString(R.string.ENTERPRISE_AUTHENTICATOR_ACCOUNT_TYPE); // give me *com.tsp.test*
This doesn't match ! So in SfbSDK the condition wasn't passed.
Well, thanks to Radesh and this link he provided to me, I've found my solution.
I removed resValue from the defaultConfig block then I added a new block in the android plugin task, that create the resValue for each variant.
apply plugin: 'com.android.application'
...
android {
...
defaultConfig {
applicationId "com.tsp.test"
...
}
...
flavorDimensions("customer", "version")
productFlavors {
a {
dimension "customer"
applicationIdSuffix ".a"
}
b {
dimension "customer"
applicationIdSuffix ".b"
}
alpha {
dimension "version"
applicationIdSuffix ".alpha"
}
beta {
dimension "version"
applicationIdSuffix ".beta"
}
release {
dimension "version"
applicationIdSuffix ".release"
}
}
...
applicationVariants.all { variant ->
variant.resValue "string", "ENTERPRISE_AUTHENTICATOR_ACCOUNT_TYPE", "\"${applicationId}\""
}
}
...
This generate correctly the resValue with the package name of the selected variant.
For variant customer A and version Alpha, I get resValue = com.tsp.test.a.alpha.
you must declear variable ENTERPRISE_AUTHENTICATOR_ACCOUNT_TYPE in gradle.properties like below
//default
org.gradle.jvmargs=-Xmx1536m
ENTERPRISE_AUTHENTICATOR_ACCOUNT_TYPE=xxx
Is it possible to create two .properties files for two product flavors in Gradle?
I'm building an Android app with two flavors and I want to have separate properties for them, but have problems with overwritten variable here:
productFlavors {
flavor1 {
customProperties = getCustomProperties("flavor1.properties");
}
flavor2 {
customProperties = getCustomProperties("flavor2.properties");
}
}
My customProperties variable is always get values from flavor2 properties, even I build flavor1.
What am I doing wrong? :)
upd: defaultConfig:
defaultConfig {
minSdkVersion 17
targetSdkVersion 22
// Enabling multidex support.
multiDexEnabled true
}
I have use something like this:
flavorDimensions "default"
productFlavors {
stand {
def standPropsFile = file("${project.projectDir}/../stand.properties")
Properties standProps = new Properties()
if (standPropsFile.canRead()) {
standProps.load(new FileInputStream(standPropsFile))
}
manifestPlaceholders = standProps
applicationId = manifestPlaceholders["APP_ID"]
}
google {
def standPropsFile = file("${project.projectDir}/../google.properties")
Properties standProps = new Properties()
if (standPropsFile.canRead()) {
standProps.load(new FileInputStream(standPropsFile))
}
manifestPlaceholders = standProps
applicationId = manifestPlaceholders["APP_ID"]
}
}
manifestPlaceholders - is just setter for Map<String, Object> mManifestPlaceholders, so after "manifestPlaceholders = standProps" you can use values right by key how you have write it in .properties file.
You should also change the build variant and select the right flavor to bring every configuration for the desired flavor into effect.
Alternatively, if you have only a few fields in the properties file and just want different values for each flavor: you could use BuildConfigFields as follows:
buildConfigField 'String', 'FIELD1', '"value1"'
buildConfigField 'String', 'FIELD2', '"value2"'
buildConfigField "String", "FIELD3", "value2"
These can be accessed anywhere throughout the project using the BuildConfig class as follows:
BuildConfig.FIELD1
BuildConfig.FIELD2
BuildConfig.FIELD3
I have inherited a project which has the following flavor set up in gradle build file:
productFlavors {
def STRING = "String"
def BOOLEAN = "boolean"
def TRUE = "true"
def FALSE = "false"
def BASE_ENDPOINT = "BASE_ENDPOINT"
mock {
applicationId "com.example.myapp.mock"
buildConfigField STRING, BASE_ENDPOINT, '"mock://localhost/gt"'
}
qa {
applicationId "ca.example.myapp"
buildConfigField STRING, BASE_ENDPOINT, '"https://qa-somesite.com/gt"'
}
qaInternal {
applicationId ".ca.example.myapp.int"
buildConfigField STRING, BASE_ENDPOINT, '"https://internal-somesite.com/gt"'
}
beta {
applicationId "com.example.myapp.beta"
buildConfigField STRING, BASE_ENDPOINT, '"https://somesite.com/gt"'
}
prod {
applicationId "ca.ca.example.myapp"
buildConfigField STRING, BASE_ENDPOINT, '"https://somesite.com/gt"'
}
}
nothing special going on there just flavors for production qa, mocking , etc.
This is just for for a particular country though. Its for USA. So these flavors are all for USA. I need to use the same app. I'd like to create flavors for another country called France. The france flavors have different configurations.
i was thinking i could do something like this:
flavorDimensions "country","buildtype"
to get me the flavors by country. But then how would i create my own mock,qa,qaInternal,etc flavors for the new country.
So to be clear my end goal is to have product flavors for a new country called france given the code i've pasted above all in android studio.
UPDATE: Let me be more precise on what i desire and the issue. Look at the current product flavors: mock, qa, qaInternal,beta and prod. They all pretain to information about a USA build. This already exists in code. The code is currently built for USA customers. Now i have been asked to make the code also available for French customers so i need a french build.
The issue is things like the applicationID, and many buildConfigField are going to be different in the french build. How can i engineer a solution where i can have for example, a french mock, a french qa, a french qaInternal ,french beta, and a french prod just like i currently have for the USA build ?
The issue has nothing to do with locale per say, its just that we have two products a USA product and we want a french product which will have a different configuration then USA.
take for example the mock flavor. For french i need this to happen:
mock {
applicationId "french-com.example.mock"
versionName = versionOverride + 'french-mock'
buildConfigField STRING, BASE_ENDPOINT, '"mock://localhost/french-gt"'
}
What you are doing would work if you assign a flavorDimension to every productFlavor. So in your case the build.gradle could look like
flavorDimensions "country","buildtype"
productFlavors {
def STRING = "String"
def BOOLEAN = "boolean"
def TRUE = "true"
def FALSE = "false"
def BASE_ENDPOINT = "BASE_ENDPOINT"
mock {
dimension 'buildtype'
applicationId "com.example.myapp.mock"
versionName = versionOverride + '-mock'
buildConfigField STRING, BASE_ENDPOINT, '"mock://localhost/gt"'
}
qa {
dimension 'buildtype'
applicationId "ca.example.myapp"
versionName = versionOverride + '-qa'
buildConfigField STRING, BASE_ENDPOINT, '"https://qa-somesite.com/gt"'
}
qaInternal {
dimension 'buildtype'
applicationId ".ca.example.myapp.int"
versionName = versionOverride + '-qaInt'
buildConfigField STRING, BASE_ENDPOINT, '"https://internal-somesite.com/gt"'
}
beta {
dimension 'buildtype'
applicationId "com.example.myapp.beta"
versionName = versionOverride + '-beta'
buildConfigField STRING, BASE_ENDPOINT, '"https://somesite.com/gt"'
}
prod {
dimension 'buildtype'
applicationId "ca.ca.example.myapp"
versionName = versionOverride + '-prod'
buildConfigField STRING, BASE_ENDPOINT, '"https://somesite.com/gt"'
}
usa {
dimension 'country'
// whatever else you want
}
france {
dimension 'country'
// whatever else you want
}
}
With the flavorDimensions set up, you will now have a combination of productFlavors with dimension&buildtype, In this case it will be mockUsa, mockFrance, qaUsa, qaFrance etc..
Given the fact that there are actual buildtypes debug and release, you might end up with a huge list of variants!
I think you should create multiple buildTypes instead of flavors.
if you have build types France and USA, and flavors mock, qa and ... , then you would have these build variants : qaUSA , qaFrance, mockUSA, mockFrance and etc.
here is build.gradle example :
productFlavors {
mock {
...
}
qa {
...
}
}
buildTypes {
USA {
...
}
France {
...
}
}
I need to create different app names depending on the product flavour used.
While this was easy by simply setting a string resource, I can no longer do that because when the app is uploaded to hockeyapp the app name is set as '#string/app_name' instead of the value of app_name.
I have made some progress by setting the label in the manifest to be '${applicationName}' and setting the value with
manifestPlaceholders = [ applicationName : appName ];
in the product flavour block so that the value gets set at compile time.
The problem comes when I try to append the build type to the application name. I can't seem to find a way to know what build type is currently being used within the product flavour.
This is a stripped down version of the build for readability
android {
buildVersionName "1.0.0
buildTypes {
release {
... nothing special
}
uat {
signingConfig signingConfigs.debug
buildType = "uat"
applicationIdSuffix = "." + buildType
}
debug {
signingConfig signingConfigs.debug
buildType = "uat"
applicationIdSuffix = "." + buildType
}
}
productFlavors{
flavor1{
def appName = "app name " + buildType;
manifestPlaceholders = [ applicationName : appName ];
applicationId [id]
def clientIteration = [client iteration]
versionName buildVersionName + clientIteration
versionCode [version code]
}
flavor2{
... same as above with different app name
}
flavor3{
... same as above with different app name
}
}
}
This code works fine except the variable 'buildType' is always the last buildtype (in this case debug) which means the app name always has debug on the end.
Probably worth noting that I don't need to have anything appended on the end of the app name for releases.
You can append the values like this
android {
productFlavors {
Foo {
applicationId "com.myexample.foo"
manifestPlaceholders = [ appName:"Foo"]
}
Bar {
applicationId "com.myexample.bar"
manifestPlaceholders = [ appName:"Bar"]
}
}
buildTypes {
release {
manifestPlaceholders = [ appNameSuffix:""]
}
debug {
manifestPlaceholders = [ appNameSuffix:".Debug"]
applicationIdSuffix ".debug"
}
}
}
and in the manifest
<application
android:label="${appName}${appNameSuffix}"
...
</application>
If you want to access different values based on build type you can do it like this
buildTypes {
debug{
buildConfigField "String", "Your_string_key", '"yourkeydebugvalue"'
buildConfigField "String", "SOCKET_URL", '"some text"'
buildConfigField "Boolean", "LOG", 'true'
}
release {
buildConfigField "String", "Your_string_key", '"yourkeyreleasevalue"'
buildConfigField "String", "SOCKET_URL", '"release text"'
buildConfigField "Boolean", "LOG", 'false'
}
}
And to access those values using build variants:
if(!BuildConfig.LOG)
// do something with the boolean value
Or
view.setText(BuildConfig.yourkeyvalue);
I know I'm a bit late for the party but if you want different names based on the flavours, you should have something like this:
productFlavors{
flavour 1 {
applicationId "your_app_id"
resValue "string", "app_name", "Flavour 1 app name"
.......
}
flavour 2 {
applicationId "your_app_id"
resValue "string", "app_name", "Flavour 2 app name"
.......
}
}
and in your AndroidManifest.xml:
android:label="#string/app_name"
Hope this helps.
This link http://inaka.net/blog/2014/12/22/create-separate-production-and-staging-builds-in-android/ may help you out.
If you have two productFlavors (Production and Staging, for instance)
You should create two different resource folders:
project/app/src/production/res/values/strings.xml
<resources>
<string name="root_url">http://production.service.com/api</string>
</resources>
project/app/src/staging/res/values/strings.xml
<resources>
<string name="root_url">http://staging.service.com/api</string>
</resources>
You should add this following code inside the android {}:
productFlavors {
production {
applicationId "com.inaka.app.production"
}
staging {
applicationId "com.inaka.app.staging"
}
}
It's a good idea to have different icons for different productFlavors, just add the icon inside each different resource folder.