compose-multiplatform icon indicating copy to clipboard operation
compose-multiplatform copied to clipboard

Using ProgressIndicator leads to a NoSuchMethodError crash on Android

Open zacharee opened this issue 1 year ago • 9 comments

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:

  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]

zacharee avatar Jan 22 '24 14:01 zacharee

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

FunkyMuse avatar Jan 25 '24 11:01 FunkyMuse

I reproduced it with slightly different parameters :

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

Hsb511 avatar Jan 25 '24 11:01 Hsb511

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.

chrisbanes avatar Jan 25 '24 12:01 chrisbanes

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()
        }
    }
}

igordmn avatar Jan 25 '24 13:01 igordmn

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

softartdev avatar Jan 28 '24 14:01 softartdev

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

zt64 avatar Jan 31 '24 01:01 zt64

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

siftoshka avatar Feb 03 '24 18:02 siftoshka

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

MatkovIvan avatar Feb 03 '24 19:02 MatkovIvan

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 avatar Feb 07 '24 09:02 igordmn

Fixed in 1.6.0-rc01

igordmn avatar Feb 19 '24 14:02 igordmn

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()

c4software avatar Feb 19 '24 16:02 c4software

Do you have a project on which we can look?

igordmn avatar Feb 19 '24 17:02 igordmn

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?

c4software avatar Feb 19 '24 19:02 c4software

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")

igordmn avatar Feb 19 '24 20:02 igordmn

Seems okay with alpha version too.

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

c4software avatar Feb 19 '24 21:02 c4software

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

okushnikov avatar Jul 14 '24 15:07 okushnikov