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)
Related
Specifically for aar generated libraries, does the versionCode set either in the manifest or build file matter? Is it used anywhere for anything?
For an apk the docs say versionCode is used by the Play store API. I couldn't find any reference to versionCode relating to aars though.
For aar consumer it doesn't matter - they only need the maven artifact version.
For aar producer it matters - you may want to use it to add specific upgrade code to run only once (from version X to version Y).
I think AGP no longer requires specifying version name or code to non-app modules.
I have a library project with 2 flavors
configurations {
// Initializes placeholder configurations that the Android plugin can use when targeting
// the corresponding variant of the app.
internalDebug {}
internalRelease {}
externalDebug {}
externalRelease {}
}
flavorDimensions("outerInner")
productFlavors {
internal{dimension "outerInner"}
external{dimension "outerInner"}
}
No custom sourceSets defined in build.gradle
For one of the flavor I have custom layouts inside:
All other sources should be from main.
When I include this libaryr to app:
implementation project(path: ':sdk', configuration: 'internalDebug')
There no classes of the sdk library at all and all imports marks as red.
The question is why there is no sources from main's library folders in app?
Finally I got the solution as defining missingDimensionStrategy in app's build.gradle.
// Specifies a sorted list of flavors that the plugin should try to use from
// a given dimension. The following tells the plugin that, when encountering
// a dependency that includes a "minApi" dimension, it should select the
// "minApi18" flavor. You can include additional flavor names to provide a
// sorted list of fallbacks for the dimension.
missingDimensionStrategy 'outerInner', 'internal'
It means that if during the build gradle will found a dependency that have the flavorDimension outerInner it should use internal for that.
After this is applied I could simply include
implementation project(path: ':sdk')
For each app's buildType it will use appropriate debug or relese SDK build and fallback to internal implementation.
External implementation is delivered to maven with artifact bundleExternalDebugAar setting.
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.
I have a library project - let's call it lib1 which has custom flavorDimensions specified. More precisely there is buld dimension with actual flavors full and production.
This library is used by another library project (lib2) with no custom flavorDimensions specified and app project with dependency to lib2 but not directly to lib1.
To tell lib2 which flavor of lib1 to use I can specify missingDimensionStrategy 'build', 'full'. Great. Mission accomplished, right?
Well not really... Project won't sync because app project doesn't know which flavor of lib1 should it use??? I need to put the missingDimensionStrategy 'build', 'full' to the app project as well. You can imagine that if you try to build a well modularized app. This line will be practically in every build.gradle which transitively depends on lib1.
Is this how it should be? Can't I tell gradle somewhere globally what flavor to use? I wanted to add the dependency with debugApi project (path:':xxx', configuration: 'fullDebug') etc. but that doesn't work... :(
Can anybody give an advice? Thanks.
I have following project structure:
main-project/
modules/
moduleA/
moduleB/
main-project uses moduleA and moduleB as dependencies. Currently, these modules are library modules, however, I would like to be able to release them as standalone applications. Thus, I want to be able to release:
main-project application (dependent on moduleA and moduleB)
moduleA standalone application
moduleB standalone application
There are more submodules than just moduleA and moduleB, so creating application modules for each of them is not an option (unless it is possible to automatize it by Gradle).
Is there a possibility, using Gradle, to build main-project and its dependencies as separate APKs?
EDIT
To better illustrate my problem, here is less abstract example of my project structure:
cats-dogs-browser/
modules/
cats-browser/
dogs-browser/
I would like to release cats-dogs-browser, cats-browser, dogs-browser APKs. Both cats-browser and dogs-browser are able to work as standalone applications (they have own resources, activities etc.). Using flavours in cats-dogs-browser to include only one of modules is not an option as it contains a lot of logic that is not needed for cats-browser nor dogs-browser to work.
I know I can do it by providing application modules for cats-browser and dogs-browser (or using one such module with flavours), but in real project there is a lot more than 2 such modules so I am looking for better solution.
Have you tried to include another productFlavor with your module id?
Dunno if it's exactly what you want.
I can create 2 different applications sharing part of the code using the following gradle configuration:
flavorDimensions "Applications"
productFlavors {
Application1{
dimension "Applications"
applicationId "com.example.app1"
versionCode 1
versionName "1.0.0"
}
Application2 {
dimension "Applications"
applicationId "com.example.app2"
versionCode 1
versionName "1.0.0"
}
}