Once I introduced dynamic feature modules into my app, I was able to successfully refactor feature one (orders), build and deploy. But on refactoring the second module, i.e moving files and resources to that module, I get this error on build:
Execution failed for task ':features:catalog:createDebugCompatibleScreenManifests'.
> Failed to calculate the value of task ':features:catalog:createDebugCompatibleScreenManifests' property 'applicationId'.
> Failed to query the value of property 'testedApplicationId'.
> Collection has more than one element.
I have tried the following fixes:
- invalidate cache
- reclone project
- ensure all gradle files are identical (except for
applicationId
bit) - checked that there are no errors in the manifest files
- confirmed that no two modules share the same application ID.
- rebase the project to the last working commit.
Any pointers as to what is causing this build issue?
Other info: I'm using dependency injection with koin.
App/Main module manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.app">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature
android:name="android.hardware.camera2"
android:required="false" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".ExampleApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="AllowBackup,GoogleAppIndexingWarning">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="${crashlyticsCollectionEnabled}" />
<activity android:name="com.kyosk.app.ui.fragment.login.LoginActivity" />
<activity android:name="com.kyosk.app.ui.activity.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.kyosk.app.ui.activity.Home" />
<service
android:name=".service.MessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name=".location.services.LocationUpdatesService"
android:exported="false" />
<service
android:name=".location.services.MapsLocationUpdatesService"
android:exported="false" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>
App/Main module build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: "androidx.navigation.safeargs.kotlin"
apply plugin: 'realm-android'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: (BuildPlugins.dependencyUpdateChecker)
android {
compileSdkVersion AndroidSDK.compileSDKVersion
buildToolsVersion Versions.buildTools
defaultConfig {
applicationId "com.example.app"
minSdkVersion AndroidSDK.minimumSDKVersion
targetSdkVersion AndroidSDK.targetSDKVersion
versionCode Versions.versionCode
versionName Versions.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {
manifestPlaceholders = [crashlyticsCollectionEnabled: "false"]
applicationIdSuffix(".debug")
versionNameSuffix("-debug")
buildConfigField("String", "BASE_URL", debug_url)
}
staging {
initWith(release)
manifestPlaceholders = [crashlyticsCollectionEnabled: "false"]
applicationIdSuffix(".staging")
versionNameSuffix("-staging")
buildConfigField("String", "BASE_URL", staging_url)
}
release {
manifestPlaceholders = [crashlyticsCollectionEnabled: "true"]
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
buildConfigField("String", "BASE_URL", production_url)
}
}
buildFeatures {
viewBinding = true
dataBinding = true
}
kotlinOptions {
jvmTarget = '1.8'
}
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
kapt {
correctErrorTypes = true
}
dynamicFeatures = [':features:kiosks', ':features:catalog', ':features:checkout', ':features:summary', ':features:orders']
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation Libraries.kotlinStandardLibrary
implementation Libraries.appCompat
implementation Libraries.constraintLayout
api Libraries.materialComponents
implementation Libraries.navigationFragment
implementation Libraries.navigationUI
implementation Libraries.preferences
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
//firebase libs
implementation Libraries.firebaseMessaging
implementation Libraries.firebaseConfig
// Recommended: Add the Firebase SDK for Google Analytics.
implementation Libraries.firebaseAnalytics
implementation Libraries.firebaseCrashlytics
// DI
api Libraries.koinAndroid
api Libraries.koinLifecycle
api Libraries.koinViewmodel
//maps
implementation 'com.google.android.gms:play-services-maps:17.0.0'
//own modules
implementation project(path: ':location-services')
implementation project(path: ':network')
api project(path: ':helpers')
//glide
implementation 'com.github.bumptech.glide:glide:4.11.0'
kapt 'com.github.bumptech.glide:compiler:4.11.0'
//loading button
api Libraries.buttonProgress
//pagination lib
implementation Libraries.jdroidCoder
//EventBus
api Libraries.eventBus
//logging
api Libraries.timber
//anko
api Libraries.ankoDesign
api Libraries.ankoCommons
//play core library
implementation(Libraries.playCore)
implementation(Libraries.playCorektx)
// paris for applying styles to views dynamically
implementation 'com.airbnb.android:paris:1.7.2'
// lottie for animations
implementation 'com.airbnb.android:lottie:3.5.0'
// Okhttp Profiler
implementation Libraries.loggingInterceptor
// Test libs
testImplementation(TestLibraries.junit4)
androidTestImplementation(TestLibraries.androidX)
androidTestImplementation(TestLibraries.espresso)
androidTestImplementation(TestLibraries.annotationLib)
}
Feature Module 1(orders) manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dist="http://schemas.android.com/apk/distribution"
package="com.example.app.orders">
<dist:module
dist:instant="false"
dist:title="@string/title_orders">
<dist:delivery>
<dist:install-time />
</dist:delivery>
<dist:fusing dist:include="true" />
</dist:module>
</manifest>
Feature 1 (orders) build.gradle
apply plugin: 'com.android.dynamic-feature'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: (BuildPlugins.dependencyUpdateChecker)
android {
compileSdkVersion AndroidSDK.compileSDKVersion
buildToolsVersion Versions.buildTools
defaultConfig {
applicationId "com.example.app.orders"
minSdkVersion AndroidSDK.minimumSDKVersion
targetSdkVersion AndroidSDK.targetSDKVersion
versionCode Versions.versionCode
versionName Versions.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {}
staging {}
release {}
}
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding = true
dataBinding = true
}
}
dependencies {
implementation project(":app")
implementation project(path: ':network')
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation Libraries.kotlinStandardLibrary
implementation Libraries.ktxCore
implementation Libraries.appCompat
implementation Libraries.constraintLayout
implementation Libraries.materialComponents
implementation Libraries.navigationFragment
implementation Libraries.navigationUI
implementation Libraries.buttonProgress
implementation Libraries.ankoDesign
implementation Libraries.ankoCommons
implementation(Libraries.coroutinesAndroid)
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
// Test libs
testImplementation(TestLibraries.junit4)
androidTestImplementation(TestLibraries.androidX)
androidTestImplementation(TestLibraries.espresso)
androidTestImplementation(TestLibraries.annotationLib)
}
The issue ended up being a library I had imported.
The library had plugin
apply plugin: 'com.android.application'
instead ofapply plugin: 'com.android.library'
As such, gradle build task was looking for
applicationId
andapplicationName
in the manifest, which was not there.Oops, developer error.