I'm trying out the Android's latest app packaging and delivery model, App Bundles.
I've created a dynamic feature module and defined a dependency on the main app.
implementation(':app')
Now my app module has different productFlavors.
productFlavors {
free {
...
}
pro {
...
}
}
My dynamic feature does not require any product flavors. But I now get the following error on gradle sync -
Unable to resolve dependency for ':dynamic_feature#debug/compileClasspath':
Could not resolve project :app.
I can fix this by defining the same productFlavors in my dynamic feature module, but is it absolutely necessary?
I am generalizing a case where I have many different submodules and productFlavors and defining productFlavors in each module feels redundant.
In this case you'll have to declare a missingDimensionStrategy for the dynamic feature module which doesn't have the flavor.
In your com.android.dynamic-feature module you'd add something like this
android {
// other things
defaultConfig {
// other things
missingDimensionStrategy 'pro' // or whichever dimension you want to use
}
}
You can find more about this and why this is necessary in the documentation.
Related
I need to generate AAR and APK from the same module base on different build flavor.
However APK requires an applicationId, while library doesn't. I have to add if-case inside build.gradle.
Is there any better way to achieve the same outcome ?
My current gradle file:
productFlavors {
generateAar {
versionCode buildVersionCode()
versionName getPackageName()
}
generateApk {
if (!library) {
applicationId "appId"
}
versionCode buildVersionCode()
versionName getPackageName()
}
A module can either be a library or application, never both.
You should probably consider wrapping all your code into a library module which can be used by the application module (only manifest and launcher resource drawables)
That way your logic can be packaged as an aar artifact from the library and your app module is able to use it either directly if in the same project or as a packaged artifact if in a separate project.
PS: when working with a local aar the transitive dependencies on the artifact need to be explicitly defined in the application module that’s dependent on it.
Additionally, depending on your use case you might want to consider how you approach modularisation of your project either by features or layer (data, domain, presentation etc)
So I am trying to architect my project based on a MVP pattern for Android. I have used this excellent article as my base. While it works great, I was wondering how would I be able to maintain different build flavors(Staging & Production) across modules.
More details -
I have a module named common which contains a Constants.java file which has URL's and other base settings/constants. What I want to be able to do is have different Constants.java file for staging and production. In the same module, it is easily done, but since my common module is separate from my main app module, I am not sure how would I achieve this.
Any pointers would be appreciated. Thanks
Though I haven't done this myself yet, according to the documentation, you can have different flavors for your library module and reference them from a flavored app module as follows:
//:app build.gradle
productFlavors {
stage {
}
prod {
}
}
dependencies {
stageCompile project(path: ':common', configuration: 'stageRelease')
prodCompile project(path: ':common', configuration: 'prodRelease')
}
//:common build.gradle
android {
publishNonDefault true
}
productFlavors {
stage {
}
prod {
}
}
I am having troubles with product flavors, my project contains library named Core and application named i.e. App.
In build.gradle file of my App module I am compiling this library project like this:
dependencies {
compile project(':Core')
}
This is working fine but issue comes when I want to introduce specific product flavors in both my library project "Core" and my application module "App".
In Core buid.gradle file I have defined one product flavor :
productFlavors {
flavor1 {
}
}
sourceSets.flavor1 {
java {
exclude '**/SomeFilePath/*'
}
}
Now once I've added this new flavor to my Core library, I want to change build.gradle in my App application module so that I can compile only this productFlavor named flavor1 from my Core project.
I tried something like this, but it fails with error "No configuration with named "flavor1Release" found."
dependencies {
compile project(path: ':Core', configuration: 'flavor1Release')
}
Just to sum it all, I want to have multiple flavors in my App application module and each of this flavors would compile different flavor from my Core library project. This way every flavor from my App module would have different files included in build from this Core library.
Does anyone know how can I accomplish this?
As I can see you are explicitly providing the configuration to compile your project. But you don't need to do that because "Android Studio" already provide that option
To work on files from a particular flavor, click on Build Variants on
the left of the IDE window and select the flavor you want to modify in
the Build Variants panel,
For product flavors you need to specify following things:
productFlavors {
demo {
applicationId "com.buildsystemexample.app.demo"
versionName "1.0-demo"
}
full {
applicationId "com.buildsystemexample.app.full"
versionName "1.0-full"
}
}
I have an Android project (already ported to Android Studio and using Gradle) that is made up of different modules.
The project is actually used to create two different apps, where the code is pretty much the same, except for some resources.
Thus the resources have been split into two different modules.
The original author of this project used to work in Eclipse and switch the resource modules included in the dependencies based on which app he wanted to build. And he also used to change by hand the package name in AndroidManifest.xml
I would like to automate all of this and still have a single code base, but have two build targets with specific modules for each target. Is that doable with Gradle?
Update:
To make things even harder, my project has a hierarchy that is pretty much the following:
--+--MainProject
+--LibData
+--LibBase
+--LibResA
+--LibResB
Where:
MainProject depends on LibBase and LibData.
LibData depends on LibBase
LibBase either depends on LibResA or LibResB based on the final APK that I need to build.
As suggested, I've tried implementing this with flavors by adding in the MainProject build.gradle the following:
productFlavors {
producta {
}
productb {
}
}
And then in LibBase I've added the following to its build.gradle:
dependencies {
productaCompile project(':LibResA')
productbCompile project(':LibResB')
}
But then, when I build the project, LibData can't find the classes and resources inherited from LibBase. So now I'm stuck with this error. To me it looks like LibBase isn't being copied to the intermediates of LibData. That way LibData can't resolve the classes in LibBase, but it's just my assumption.
Update 2:
I kept investigating this issue and now I've changed my build.gradle files to look like this:
Main Project build.gradle:
defaultPublishConfig "productaRelease"
publishNonDefault true
productFlavors {
producta {
applicationId "com.producta"
}
productb {
applicationId "com.productb"
}
}
dependencies {
compile project(':LibData')
}
LibData build.gradle (has no product flavors, just the dependencies):
dependencies {
compile project(':LibBase')
}
LibBase build.gradle:
defaultPublishConfig "productaRelease"
publishNonDefault true
productFlavors {
producta {
}
productb {
}
}
dependencies {
productaCompile project(path: ':LibResA')
productbCompile project(path: ':LibResB')
}
This way I get no errors when doing the usual gradle clean build but I can see that the resources included are always those of LibResA just like the defaultPublishConfig is the only one used at all times.
If I open this project in Android Studio (0.8.1 atm) the result is that if I try to switch the build variant of the LibBase module and set it to productbRelease, the following error is being shown: Error:Module 'LibBase' has variant 'productbRelease' selected, but the module ''LibData'' depends on variant 'productaRelease'.
I'm running out of ideas.
Since you already have the product flavors:
productFlavors {
producta {
}
productb {
}
}
Define your dependencies prefixed with flavor name.
Example:
dependencies {
productaImplementation 'com.google.android.gms:play-services:11.0.2'
productbImplementation 'com.google.android.gms:play-services:12.0.1'
}
Common dependencies will be defined normally.
Now build apk for individual flavors.
Not the best way to do it, but if productFlavors is not enough to specify conditional dependencies you can rely on an inline if and evaluate it based on some value that can be injected via external properties.
For example here is how I toggle LeakCanary (no-op is just the empty implementation of the other one):
build.gradle
dependencies {
compile "com.squareup.leakcanary:leakcanary-android"+(project.ext.has("leakCanary")?"":"-no-op")+":1.3.1"
}
To build with com.squareup.leakcanary:leakcanary-android:1.3.1:
$ ./gradlew :app:assembleDebug -PleakCanary
By default it builds with the empty implementation com.squareup.leakcanary:leakcanary-android-no-op:1.3.1:
$ ./gradlew :app:assembleDebug
This provides a quick and more flexible way to toggle things using build command, but too much of it and things will get messy real quick.
Yes, it is. New Android build system based on Gradle supports your use case with its concept of product flavors. http://tools.android.com/tech-docs/new-build-system/user-guide
Note that you will likely want to switch from Eclipse to Android Studio when you do migration to Gradle build.
I'm dealing with a project that has a large number of dependencies. This has become a problem because when adding new SDK's we're going past the maximum limit of methods that an APK can hold (65536).
I'm looking at using the new build system in Android Studio in order to create build variants that rely on subsets of our dependencies. I was able to find a number of tutorials that help with creating different class alternatives using build flavours, but I didn't find anything regarding specifying different dependencies for each flavour. Is this even possible? What would the whole workflow look like?
For example, I would like to create a build variant that removes Flurry support. I would be able to create a different class that does not instantiate the Flurry SDK, but I would also like to be able to remove the lib dependency entirely, in order to reduce the total number of methods in the APK.
I'm also open to any suggestion regarding managing this kind of issue :)
This works (making sure dependencies are listed after productFlavors):
android {
...
productFlavors {
flavor1 { ...
...
dependencies {
flavor1Compile ...
}
But this won't work:
android {
...
dependencies {
flavor1Compile ...
}
...
productFlavors {
flavor1 { ...
...