2

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:

  1. invalidate cache
  2. reclone project
  3. ensure all gradle files are identical (except for applicationId bit)
  4. checked that there are no errors in the manifest files
  5. confirmed that no two modules share the same application ID.
  6. 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)
}
Adhiambo Oyier
  • 215
  • 1
  • 11

3 Answers3

4

The issue ended up being a library I had imported.

The library had plugin apply plugin: 'com.android.application' instead of apply plugin: 'com.android.library'

As such, gradle build task was looking for applicationId and applicationName in the manifest, which was not there.

Oops, developer error.

Adhiambo Oyier
  • 215
  • 1
  • 11
0

For me it happened when adding a new dynamic feature module with multiple flavors.

I solved it by changing inside module.gradle:

implementation project(path: ':app', configuration: 'default')

into

implementation project(":app")

Then add flavors into module.gradle

flavorDimensions "app"

productFlavors {
    flavor1 {}
    flavor2 {}
    flavor3 {}
}

Here is my final module.gradle

apply plugin: 'com.android.dynamic-feature'

android {
    compileSdkVersion 29
    buildToolsVersion '29.0.3'

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    flavorDimensions "app"

    productFlavors {
        flavor1 {}
        flavor2 {}
        flavor3 {}
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation project(":app")
}
Alex
  • 390
  • 4
  • 14
  • Hey! I think this is what I'm looking for. Could you explain a bit more what you have done ? Adding "implementation project(path: ':app', configuration: 'default')" in dynamic module bring me another error : "Collection is empty"... Thanks – michgauz Apr 29 '21 at 09:19
  • Hi! Try to use this line "implementation project(":app")". Tell me if you need more help! – Alex Apr 29 '21 at 10:23
  • @michgauz, are you getting the same error? Check the plugins you have aaplied at the top of the module level build.gradle, to confirm that its: apply plugin: 'com.android.application' for app module, apply plugin: 'com.android.library' for lib modules and 'com.android.dynamic-feature' for dynamic modules – Adhiambo Oyier Apr 29 '21 at 11:42
  • Thanks for your answer but finally my problem was a bit different https://stackoverflow.com/questions/67336240/com-android-test-module-for-both-app-and-dynamicfeature-failing-with-co – michgauz May 01 '21 at 07:00
  • @Alex since our code from app module is using dynamic module, we should have `implementation project(path: ':dynamic-module')` in app's gradle. If we add `implementation project(":app")` to module's gradle, it will create circular reference error, wont it? – Lê Thái Phúc Quang May 28 '21 at 08:30
  • @LêTháiPhúcQuang yes in app.gradle you should have implementation project(":module") but I was talking about the inside of MODULE.GRADLE file. Also I had problems when using the longer version (path: "app") vs (":app") – Alex May 31 '21 at 10:29
  • I've tried both, but it doesnt work if module app's gradle declares dependencies to :module, also, this breaks the point of dynamic feature isn't it? – Lê Thái Phúc Quang May 31 '21 at 11:15
  • in my project the only dependency is inside module.gradle "implementation project(":app") not the other way around. Of course you could remove all dependencies between modules if you don't need them – Alex May 31 '21 at 13:08
-2

Uninstall the application from emulator and then restart it

Hamidreza
  • 139
  • 1
  • 12