compose-multiplatform: Using ProgressIndicator leads to a NoSuchMethodError crash on Android
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:
- Android
Versions
- Kotlin version*: 1.9.22
- Compose Multiplatform version*: 1.6.0-dev1378 and 1.6.0-dev1383
- OS version(s)* (required for Desktop and iOS issues): Android 14
- OS architecture (x86 or arm64): arm64
To Reproduce Steps and/or the code snippet to reproduce the behavior:
- Implement a
LinearProgressIndicator
from the Material 3 library. - 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]
About this issue
- Original URL
- State: closed
- Created 5 months ago
- Reactions: 18
- Comments: 15 (1 by maintainers)
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 classKeyframesSpecBaseConfig
, 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.
Androidx issue Reproducible on the pure Jetpack Compose template in Android Studio with:
(Jetpack Compose 1.6, Material3 1.1.2)
Reproducer:
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):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.
@siftoshka already merged - https://github.com/JetBrains/compose-multiplatform-core/pull/1044
I reproduced it with slightly different parameters :
With
1.6.0-beta01
, usingCircularProgressIndicator
on Android 14 and Android 10I’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