JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
16.27k stars 1.18k forks source link

Using ProgressIndicator leads to a NoSuchMethodError crash on Android #4157

Closed zacharee closed 8 months ago

zacharee commented 9 months ago

Describe the bug With 1.6.0-dev1378 and 1.6.0-dev1383, using ProgressIndicator on Android throws a NoSuchMethodError.

Affected platforms Select one of the platforms below:

Versions

To Reproduce Steps and/or the code snippet to reproduce the behavior:

  1. Implement a LinearProgressIndicator from the Material 3 library.
  2. Run the project on Android.

Expected behavior Shouldn't crash.

Screenshots If applicable, add screenshots to help explain your problem.

Additional context This seems to have already been fixed in the upstream Material 3 library, so I'm reporting it here.

A functional workaround is to implement material3:1.2.0-beta02 directly from AndroidX in the Android target.

Stacktrace ``` 09:29:49.092 E FATAL EXCEPTION: main Process: tk.zwander.samsungfirmwaredownloader, PID: 11953 java.lang.NoSuchMethodError: No virtual method at(Ljava/lang/Object;I)Landroidx/compose/animation/core/KeyframesSpec$KeyframeEntity; in class Landroidx/compose/animation/core/KeyframesSpec$KeyframesSpecConfig; or its super classes (declaration of 'androidx.compose.animation.core.KeyframesSpec$KeyframesSpecConfig' appears in /data/app/~~hVLqfMVUIjfm3yZx5d2c_Q==/tk.zwander.samsungfirmwaredownloader-HCfLxnJv1JTMzSgi61XBmg==/base.apk) at androidx.compose.material3.ProgressIndicatorKt$LinearProgressIndicator$firstLineHead$1.invoke(ProgressIndicator.kt:124) at androidx.compose.material3.ProgressIndicatorKt$LinearProgressIndicator$firstLineHead$1.invoke(ProgressIndicator.kt:122) at androidx.compose.animation.core.AnimationSpecKt.keyframes(AnimationSpec.kt:649) at androidx.compose.material3.ProgressIndicatorKt.LinearProgressIndicator-2cYBFYY(ProgressIndicator.kt:122) at tk.zwander.commonCompose.view.components.ProgressInfoKt$ProgressInfo$1$1.invoke(ProgressInfo.kt:60) at tk.zwander.commonCompose.view.components.ProgressInfoKt$ProgressInfo$1$1.invoke(ProgressInfo.kt:55) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.animation.AnimatedVisibilityKt.AnimatedEnterExitImpl(AnimatedVisibility.kt:818) at androidx.compose.animation.AnimatedVisibilityKt$AnimatedEnterExitImpl$4.invoke(Unknown Source:27) at androidx.compose.animation.AnimatedVisibilityKt$AnimatedEnterExitImpl$4.invoke(Unknown Source:10) at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:192) at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2556) at androidx.compose.runtime.ComposerImpl.skipToGroupEnd(Composer.kt:2850) at androidx.compose.animation.AnimatedVisibilityKt.AnimatedVisibilityImpl(AnimatedVisibility.kt:761) at androidx.compose.animation.AnimatedVisibilityKt.AnimatedVisibility(AnimatedVisibility.kt:283) at tk.zwander.commonCompose.view.components.ProgressInfoKt.ProgressInfo(ProgressInfo.kt:53) at tk.zwander.commonCompose.view.components.ProgressInfoKt$ProgressInfo$2.invoke(Unknown Source:10) at tk.zwander.commonCompose.view.components.ProgressInfoKt$ProgressInfo$2.invoke(Unknown Source:10) at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:192) at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2556) at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2827) at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3314) at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3265) at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:938) at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:1155) at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:127) at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:583) at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:551) at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:41) at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109) at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41) at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1337) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1348) at android.view.Choreographer.doCallbacks(Choreographer.java:952) at android.view.Choreographer.doFrame(Choreographer.java:878) 09:29:49.094 E at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1322) at android.os.Handler.handleCallback(Handler.java:958) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8177) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971) Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.runtime.PausableMonotonicFrameClock@6d5edf6, androidx.compose.ui.platform.MotionDurationScaleImpl@9db75f7, StandaloneCoroutine{Cancelling}@46cac64, AndroidUiDispatcher@8240ecd] ```
FunkyMuse commented 9 months ago

I've no idea why 1.6.0-beta01 is targeting Material 1.6.0-rc01 but M3 component is Material3 1.1.2

Lots of migrations and fixes for M3 landed in their https://developer.android.com/jetpack/androidx/releases/compose-material3#1.2.0-rc01

Hsb511 commented 9 months ago

I reproduced it with slightly different parameters :

With 1.6.0-beta01, using CircularProgressIndicator on Android 14 and Android 10

chrisbanes commented 9 months ago

I think there's a bigger question of how this breaks at runtime. Looks like the KeyframesSpecConfig.at() function in 1.5.0 was refactored in 1.6.0 and moved to a super class KeyframesSpecBaseConfig, which breaks binary compatibility (but not source compatibility).

This function wasn't experimental so it's worth following up with the AndroidX team as to how this wasn't caught as a breaking change.

igordmn commented 9 months ago

Androidx issue Reproducible on the pure Jetpack Compose template in Android Studio with:

implementation(platform("androidx.compose:compose-bom:2024.01.00"))

(Jetpack Compose 1.6, Material3 1.1.2)

Reproducer:

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.LinearProgressIndicator

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            CircularProgressIndicator()
//            LinearProgressIndicator()
        }
    }
}
softartdev commented 9 months ago

Reproduce with kotlin 1.9.22 & compose 1.6.0-beta01: https://github.com/softartdev/NoteDelight/actions/runs/7682327242/job/20937252856#step:6:786

zt64 commented 9 months ago

Interestingly I'm also getting this error but instead from proguard while trying to package my program for desktop

Warning: androidx.compose.material.ProgressIndicatorKt$CircularProgressIndicator$endAngle$2: can't find referenced method 'androidx.compose.animation.core.KeyframesSpec$KeyframeEntity at(java.lang.Object,int)' in program class androidx.compose.animation.core.KeyframesSpec$KeyframesSpecConfig
Warning: androidx.compose.material.ProgressIndicatorKt$CircularProgressIndicator$startAngle$2: can't find referenced method 'androidx.compose.animation.core.KeyframesSpec$KeyframeEntity at(java.lang.Object,int)' in program class androidx.compose.animation.core.KeyframesSpec$KeyframesSpecConfig
Warning: androidx.compose.material.ProgressIndicatorKt$LinearProgressIndicator$firstLineHead$2: can't find referenced method 'androidx.compose.animation.core.KeyframesSpec$KeyframeEntity at(java.lang.Object,int)' in program class androidx.compose.animation.core.KeyframesSpec$KeyframesSpecConfig
Warning: androidx.compose.material.ProgressIndicatorKt$LinearProgressIndicator$firstLineTail$2: can't find referenced method 'androidx.compose.animation.core.KeyframesSpec$KeyframeEntity at(java.lang.Object,int)' in program class androidx.compose.animation.core.KeyframesSpec$KeyframesSpecConfig
Warning: androidx.compose.material.ProgressIndicatorKt$LinearProgressIndicator$secondLineHead$2: can't find referenced method 'androidx.compose.animation.core.KeyframesSpec$KeyframeEntity at(java.lang.Object,int)' in program class androidx.compose.animation.core.KeyframesSpec$KeyframesSpecConfig
Warning: androidx.compose.material.ProgressIndicatorKt$LinearProgressIndicator$secondLineTail$2: can't find referenced method 'androidx.compose.animation.core.KeyframesSpec$KeyframeEntity at(java.lang.Object,int)' in program class androidx.compose.animation.core.KeyframesSpec$KeyframesSpecConfig
siftoshka commented 9 months ago

Can we expect material3 rc01 on one of the beta releases of 1.6.0?

MatkovIvan commented 9 months ago

@siftoshka already merged - https://github.com/JetBrains/compose-multiplatform-core/pull/1044

igordmn commented 9 months ago

Compose Multiplatform 1.6.0-beta02 shouldn't has this issue out of the box (because it bundles Material3 1.2-rc01), but we still have binary incompatibility between 1.5 and 1.6.

I will close it after meging Jetpack Compose 1.6.1 with the fix.

igordmn commented 8 months ago

Fixed in 1.6.0-rc01

c4software commented 8 months ago

Hi @igordmn not in my case, In fact it's seems partially fixed :

With material 3 no problem :

import androidx.compose.material3.CircularProgressIndicator

CircularProgressIndicator()

With material 2, same issue, the application is crashing :

import androidx.compose.material.CircularProgressIndicator

CircularProgressIndicator()
igordmn commented 8 months ago

Do you have a project on which we can look?

c4software commented 8 months ago

Hi @igordmn

Finally, while trying to create a minimalist sample, I realized that the problem came from:

com.google.accompanist:accompanist-permissions (version 0.35.0-alpha)

Even if I don't use it, just having the dependency causes the crash when loading the Material 2CircularProgressIndicator component.

Do you still want a sample to test?

igordmn commented 8 months ago

No need, thanks.

com.google.accompanist:accompanist-permissions depends on Jetpack Compose 1.7.0-alpha01 which doesn't contain the binary compatibility fix (release was on January 24, the fix was on January 26)

Try to force using Jetpack Compose 1.7.0-alpha02 (but be aware that it is an alpha):

implementation("androidx.compose.foundation:foundation:1.7.0-alpha02")
c4software commented 8 months ago

Seems okay with alpha version too.

Meanwhile, I upgraded my application to use Material 3, which also seems to fix the issue.

okushnikov commented 4 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.