5

I'm creating an Android Library for basic dialogs. Right now, all I have is a basic-dialogs module along with the app module. I'm calling a composable in the basic-dialogs module from the Activity in the app module, and I keep getting the exception error message below about a No static method when I try to run the app. What could be wrong with the code?

java.lang.NoSuchMethodError: No static method BasicDialog(Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V in class Lcom/<domain>/basic_dialogs/BasicDialogKt; or its super classes (declaration of 'com.<domain>.basic_dialogs.BasicDialogKt' appears in /data/app/~~DOqVbMGsnzDWFS7_YdNgtw==/com.<domain>.composedialogs-_5IuirMOFh5F8pL884Urnw==/base.apk!classes2.dex)

Activity

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeDialogsTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    BasicDialog(onDismiss = {  }, onConfirmClick = {  }, title = "Test Dialog", confirmButtonText = "Open") {
                        Text("This is a test dialog.")
                    }
                }
            }
        }
    }
}

BasicDialog Composable

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun BasicDialog(
    title: String = "",
    confirmButtonText: String,
    onDismiss: () -> Unit,
    onConfirmClick: () -> Unit,
    content: @Composable () -> Unit
) {
    Surface(
        shape = MaterialTheme.shapes.medium,
        color = MaterialTheme.colors.surface,
        modifier = Modifier
            .padding(4.dp)
    ) {
        Dialog(
            onDismissRequest = onDismiss,
            properties = DialogProperties(
                dismissOnBackPress = true,
                dismissOnClickOutside = true,
                usePlatformDefaultWidth = false
            ),
        ) {
            if (title != "") {
                Text(title)
                Spacer(Modifier.padding(5.dp))
            }

            content()
            Spacer(Modifier.padding(5.dp))
            TextButton(onClick = onDismiss) {
                Text(text = stringResource(id = R.string.dialog_cancel), fontSize = 16.sp)
            }
            TextButton(onClick = { onConfirmClick() }) {
                Text(text = confirmButtonText, fontSize = 16.sp)
            }
        }
    }
}

Project Gradle file

buildscript {
    ext {
        compose_version = '1.1.0-beta01'
    }
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id 'com.android.application' version '7.2.2' apply false
    id 'com.android.library' version '7.2.2' apply false
    id 'org.jetbrains.kotlin.android' version '1.5.31' apply false
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

app module Gradle file

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    compileSdk 32

    defaultConfig {
        applicationId "com.<domain>.composedialogs"
        minSdk 27
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary true
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        compose true
    }
    composeOptions {
        kotlinCompilerExtensionVersion compose_version
    }
    packagingOptions {
        resources {
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
        }
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.material:material:$compose_version"
    implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
    implementation 'androidx.activity:activity-compose:1.3.1'
    implementation project(path: ':basic-dialogs')
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
    debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
    debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
}

basic-dialog module Grade file

plugins {
    id 'com.android.library'
    id 'org.jetbrains.kotlin.android'
}

android {
    compileSdk 32

    defaultConfig {
        minSdk 27
        targetSdk 32

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {

    implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.material:material:$compose_version"
}
Raj Narayanan
  • 2,443
  • 4
  • 24
  • 43

3 Answers3

24

The following needs to be added to the basic-dialogs module's build.gradle file:

buildFeatures {
    compose true
}
composeOptions {
    kotlinCompilerExtensionVersion compose_version
}

Entire Gradle file

plugins {
    id 'com.android.library'
    id 'org.jetbrains.kotlin.android'
}

android {
    compileSdk 32

    defaultConfig {
        minSdk 27
        targetSdk 32

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        compose true
    }
    composeOptions {
        kotlinCompilerExtensionVersion compose_version
    }
}

dependencies {

    implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.material:material:$compose_version"
}
Raj Narayanan
  • 2,443
  • 4
  • 24
  • 43
3

Let me hopefully save someone the 3 hours this just cost me. If you are using the Compose BOM in a multi-module project and need an updated version of an individual dependency different to what is specified in the BOM, and your modules also share the BOM, then be very careful sharing dependencies across modules.

In my example I had:

    implementation(platform(libs.androidx.compose.bom))
    api("androidx.compose.material3:material3:1.1.0-rc01") // Relatively new and needed for date & time pickers

in one module, then a load of other modules depending on this one. Some of those modules also specified:

implementation(libs.androidx.compose.material3)

This caused havoc with the app, where one module was perfectly fine and other unrelated ones were crashing at runtime telling me they didn't know what a TextField was.

Daniel Wilson
  • 18,838
  • 12
  • 85
  • 135
1

Cleaning build, then rebuilding fixed the issue for me.

leo
  • 113
  • 3
  • 11