Transitive dependencies for library build flavours on Android using api - android

I have a library that is built via Jitpack containing the following build flavors
productFlavors {
play {
dimension "default"
versionName versionString + "-play"
}
nonplay {
dimension "default"
versionName versionString + "-nonplay"
}
}
In the libraries dependencies section, I include a different dependency based on flavour like so
playApi "com.google.android.gms:play-services-location:$playServicesVersion"
nonplayApi "com.mapzen.android:lost:$lostVersion"
When I include this library in a new apps build.gradle, with, for example, nonplay
implementation ("com.xxx:someproject:1.0.0:nonplay#aar") {
transitive = true
}
I expect to see "com.mapzen.android:lost:$lostVersion" transitively included in my apps dependences list.
However I only see dependencies transitively included that do not use a flavour specific include i.e. api instead of nonplayApi. To avoid runtime crashes, I need to also add the nonplayApi dependencies in my app module.
How do I get my flavour specific nonplayApi or playApi dependencies to include transitively in my app module?

Related

Build app with multiple build variants of library in android

I have created a library called mylibrary with two product flavors like virtual and nonvirtual like below
flavorDimensions "dev"
productFlavors {
virtual {
dimension "dev"
}
nonvirtual {
dimension "dev"
}
}
and I have implemented the library in my project LibraryTesting like below
implementation project(path: ':mylibrary')
Now, when I trying to select different build variant its showing errors like "Module 'LibraryTesting.mylibrary' has variant 'nonvirtualDebug' selected, but the module 'LibraryTesting.app' depends on variant 'virtualDebug'"
please find the below image for more information
I want change the library build variant and build the app with that selected variant.
Please help me.
Your app module must decide what flavor to use.
For example, if you want app module to compile myLibrary module and virtual flavor, you need to add the following to android.defaultConfig block in build.gradle of app module:
missingDimensionStrategy 'dev', 'virtual'
Alternatively, if you want to be able to choose the variants from UI without errors, you can create 2 flavors in app module and each flavor will compile the corresponding flavor in myLibrary module:
flavorDimensions "app_dev"
productFlavors {
virtual {
dimension "app_dev"
missingDimensionStrategy 'dev', 'virtual'
}
nonvirtual {
dimension "app_dev"
missingDimensionStrategy 'dev', 'nonvirtual'
}
}
In any case, app module must declare missing dimension strategy

How to generate multi flavor apk by selectively bundling the dependency library?

My android app depends on multiple android library (say A,B,C,D). I would like to generate different apks out of them say apk1 needs to consume only on A,B and apk2 needs to consume B,C.
I've explored the option of Android's product flavor concept by doing something like this,
android {
...
defaultConfig {...}
buildTypes {
debug{...}
release{...}
}
// Specifies one flavor dimension.
flavorDimensions "version"
productFlavors {
demo {
// Assigns this product flavor to the "version" flavor dimension.
// If you are using only one dimension, this property is optional,
// and the plugin automatically assigns all the module's flavors to
// that dimension.
dimension "version"
applicationIdSuffix ".demo"
versionNameSuffix "-demo"
}
full {
dimension "version"
applicationIdSuffix ".full"
versionNameSuffix "-full"
}
}
}
Now it's generating apks with multiple products but it is including all libraries for each flavor. How can I avoid this?
Use flavor-specific directives for your dependencies. Instead of implementation, for example, you would use demoImplementation and fullImplementation. The demo builds would include the demoImplementation dependencies, while full builds would include the fullImplementation dependencies.
The documentation page that you linked to shows an example, using a free flavor:
dependencies {
// Adds the local "mylibrary" module as a dependency to the "free" flavor.
freeImplementation project(":mylibrary")
// Adds a remote binary dependency only for local tests.
testImplementation 'junit:junit:4.12'
// Adds a remote binary dependency only for the instrumented test APK.
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

How to compile with gradle different dependency module's dependencies based on build variants?

I have an Android app which has a module dependency. This module itself has a jar library as a dependency that comes in two variants, each relative to a build variant of the main app. When I switch build variant in the main app, I managed to automatically select the module's build variant which picks the correct jar, but this is not reflected in the code, where the specific classes from the jar are not found in the build variant specific code.
Here's the related code from the build.gradle files of the main app and the dependency module:
main app - build.gradle
buildTypes {
type1 {initWith(debug)}
type2 {initWith(debug)}
}
productFlavors {
live{}
test{}
}
dependencies {
type1Compile project(path: ':module', configuration: 'one')
type2Compile project(path: ':module', configuration: 'two')
}
module - build.gradle
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
useLibrary 'org.apache.http.legacy'
publishNonDefault true
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
}
buildTypes {
release {
minifyEnabled = false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
one {initWith(release)}
two {initWith(release)}
}
}
dependencies {
oneCompile files('libs/versionOne/mylib.jar')
twoCompile files('libs/versionTwo/mylib.jar')
}
So, when I build testType1 variant, Android Studio automatically selects one variant, and with a clean build it all goes fine. But if I switch to testType2, although module's two variant is selected, the editor will highlight missing classes and methods.
How can I make gradle pick the right jar when I switch between the app's build variants?
Some considerations:
The module needs the library, since it uses a few classes that are common between the 2 versions.
I know this may look like bad project design, but it's an app that has been built by different people in different times, and I now have to develop it "as is".
After some tinkering, I found some clues. First of all, my two jars where the same name, in different folders. After renaming the jars to have also different names, gradle manages to pick the correct one after the build variant switch, provided that an additional "Sync project with gradle files" is done. So now it's not immediate, but eventually it's working.

Multiple Build Flavors with and without Ads (new Google Developer Policy)

I have published an App with 2 Build Flavors: a "normal" version including ads and an ad-free-version.
In the Google Play Developer Console you now have to mark your App if it uses Ads. This is ok for the normal version but the ad-free-version uses the same dependencies as the pro version (especially google play services). So I get a warning when I set this version to ad-free because ad-libs were found.
Is it possible to change dependencies depending on gradle build flavor?
build.gradle:
android {
(...)
productFlavors {
lite {
signingConfig signingConfigs.Release
versionCode 14
versionName '1.1.5'
buildConfigField "boolean", "IS_PRO", "false"
}
pro {
applicationId 'com.example.exampleadfree'
signingConfig signingConfigs.Release
targetSdkVersion 21
versionCode 14
versionName '1.1.5'
buildConfigField "boolean", "IS_PRO", "true"
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-v4:21.0.3'
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.android.support:cardview-v7:21.0.2'
compile 'com.google.android.gms:play-services:6.1.+'
compile project(':libraries:SharedItems')
compile 'com.android.support:recyclerview-v7:21.0.2'
}
You can change
compile 'com.google.android.gms:play-services:6.1.+'
to
liteCompile 'com.google.android.gms:play-services:6.1.+'
and that will include the play services lib with your lite version only.
But you are not done, because now the code in your app that creates the AdView and related classes from the play services library will not compile when you create the pro version.
My solution in a similar situation (with the billing library) was to move all the code that refers to the excluded library and related classes to a source file which is also only built with the lite flavor, and then provide a dummy implementation for the pro version that does not refer to the library.
For example, create two flavor-specific src directories with the same-named java class in each:
src/lite/java/com/example/myapp/util/AdUtil.java
src/pro/java/com/example/myapp/util/AdUtil.java
In the lite version of AdUtil, you can make calls to google play services and get an AdView to return:
View getAdView(...)
{
View adView = new AdView(...);
adView.setAdSize(...);
adView.setAdUnitId(...);
...
return adView;
}
And in the pro version of that class, you can just put a dummy implementation that does not refer to the play services lib:
View getAdView(...)
{
return null;
}
Then in your main app code, when you call AdUtil.getAdView(), you will get a View in the lite version which you can place on the screen. In the pro version you will get a null so you skip adding the view (but you are likely already checking if you are pro or lite before trying to create the adview in the first place).
When a project declares Product Flavors, these extends the main configuration.
From here. So Product Flavors effectively adds new configurations for every flavor your declare. In gradle it is possible to add dependencies that are specific to a configuration. For example,
dependencies {
<configname> <dependency>
}
If you want to list all the configurations that your project has added:
configurations.findAll().each{println "$it.name"}
In the case if your project you'll see configs that are named the same as your product flavors. So as #cwbowron commented, to add a compile-time dependency for flavor lite:
dependencies {
liteCompile <dependency>
}
From the Google Play Support Chat I was addressed to say "No" in Google Play Console, despite the detection. So there shouldn't be problem in including the Google libs.
On the other hand, Doug's answer is elegant.
Regards,

Android Studio buildflavors

Getting started with the new android studio it seems very flexible but that usually brings a steep learning curve. Hoping to get some help with that here.
I've built an app and deployed it with this build.gradle file
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "23.0.0"
defaultConfig {
applicationId "me.test.simpleProject
minSdkVersion 10
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
signingConfigs {
release {
storeFile file("../my.keystore.jks")
storePassword System.getenv("and_ks_pw")
keyAlias System.getenv("and_ky_alias")
keyPassword System.getenv("and_k_pw")
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
debug {
debuggable true
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.1'
compile project(":Library:lib_my_lib_a")
compile project(":Library:lib_my_lib_b")
compile project(":Library:lib_my_lib_c")
}
This works pretty well and once I learn the syntax it'll be much easier to use than the previous system.
Now my question.
I would like to basically add a few product flavors.
I currently use google analytics to track clicks, usage stats, simple things like that.
In the past [before android studio] typically distribute my apps in a free/ paid version.
I would like to create say build flavors for:
google play free
google play paid
amazon free
amazon paid
The code for these apps should be mostly identical but they cannot be since, for example adding links to google play in your amazon apps gets you in a bit of trouble over there. So I will need to have unique classes across the build flavors.
I was reading some docs and watching google talks about setting up the build flavors but I am a bit confused.
Can someone help me define the folder structure for this project?
current application structure
test/
.gradle/
.idea/
app/
app/build
app/libs <-- empty
app/src
app/.gitignore
app/app.iml
app/build.gradle
app/proguard-rules.pro
build/
gradle/
Library/lib_a
Library/lib_b
Library/lib_c
.gitignore
build.gradle
gradle.properties
gradlew
gradlew.bat
local.properties
settings.gradle
test.iml
Can I place the new folders anywhere and how do I link them up with grade to properly build the variants?
The first thing you should do, is add these flavors to your gradle script, inside the android section:
productFlavors {
googleFree {
applicationId = "com.your.app.gfree"
}
googlePaid {
applicationId = "com.your.app.gpaid"
}
amazonFree {
applicationId = "com.your.app.afree"
}
amazonPaid {
applicationId = "com.your.app.apaid"
}
}
Note that you can define different package names for your app if needed, as well as some additional properties. Full details: Gradle Plugin - Build Variants
At this point you will have three different concepts in your app now:
Build types: Debug and Release
Product flavors: googleFree, googlePaid, amazonFree and amazonPaid
Build variants: Combination of build types and flavors
googleFreeDebug
googleFreeRelease
googlePaidDebug
googlePaidRelease
amazonFreeDebug
amazonFreeRelease
amazonPaidDebug
amazonPaidRelease
Flavor Specific resources:
For defining resources, you should have:
app
src
main
java
res
googlePaid
java
res
googleFree
java
res
amazonPaid
java
res
amazonFree
java
res
With that structure in place, you can place all your shared stuff under main, while the flavor specific stuff would live on each flavor's folder. Then, when building a specific variant of your app, android and gradle will resolve the right resources for you. If you are interested in more details, see Resource Merging.
Once the flavors have been added to your build.gradle file, if you sync your project, Android Studio will be able to pick your build variants and you may select these from the IDE:
To use flavors in your app you should have a structure like this:
app
src
flavor1
java
res
flavor2
java
res
main
java
res
You have to define the flavors in the build.gradle:
productFlavors {
flavor1 {
//
}
flavor2 {
//
}
}
Then you can have different dependencies using:
dependencies {
releaseCompile
debugCompile
flavor1Compile
flavor1DegubCompile
}
For example:
dependencies {
freeCompile 'com.google.android.gms:play-services:7.5.0'
}

Categories

Resources