Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.lang.NoSuchMethodError: No static method graphicsLayer #15

Open
PICO443 opened this issue Mar 15, 2023 · 1 comment
Open

java.lang.NoSuchMethodError: No static method graphicsLayer #15

PICO443 opened this issue Mar 15, 2023 · 1 comment
Assignees
Labels
bug Something isn't working

Comments

@PICO443
Copy link

PICO443 commented Mar 15, 2023

java.lang.NoSuchMethodError: No static method graphicsLayer-Ap8cVGQ$default(Landroidx/compose/ui/Modifier;FFFFFFFFFFJLandroidx/compose/ui/graphics/Shape;ZLandroidx/compose/ui/graphics/RenderEffect;JJIILjava/lang/Object;)Landroidx/compose/ui/Modifier; in class Landroidx/compose/ui/graphics/GraphicsLayerModifierKt; or its super classes (declaration of 'androidx.compose.ui.graphics.GraphicsLayerModifierKt' appears in /data/app/com.pico.learningcanvas-1/base.apk) at com.linc.audiowaveform.AudioWaveformKt.AudioWaveform-x4UjrtE(AudioWaveform.kt:76)
It's the same issue in #9 and I don't know why the issue is closed without providing a solution for it :')

  • Here is my project gradle.build file:

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

  • App level gradle.build file:

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

android {
namespace 'com.pico.learningcanvas'
compileSdk 33

  defaultConfig {
      applicationId "com.pico.learningcanvas"
      minSdk 23
      targetSdk 33
      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 '1.2.0'
  }
  packagingOptions {
      resources {
          excludes += '/META-INF/{AL2.0,LGPL2.1}'
      }
  }

}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.3.1'
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation 'androidx.compose.material3:material3:1.0.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
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"

  implementation 'com.github.lincollincol:amplituda:2.2.2'
  implementation 'com.github.lincollincol:compose-audiowaveform:1.1.1'
  implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'

}
`

  • I tried to copy the source code as a file in my project files, and it works totally fine
  • Here is the source code I copied:

`

import android.view.MotionEvent
import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.runtime.*
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.DrawStyle
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.coerceIn
import androidx.compose.ui.unit.dp
import com.linc.audiowaveform.model.AmplitudeType
import com.linc.audiowaveform.model.WaveformAlignment
import kotlin.math.ceil
import kotlin.math.roundToInt

private val MinSpikeWidthDp: Dp = 1.dp
private val MaxSpikeWidthDp: Dp = 24.dp
private val MinSpikePaddingDp: Dp = 0.dp
private val MaxSpikePaddingDp: Dp = 12.dp
private val MinSpikeRadiusDp: Dp = 0.dp
private val MaxSpikeRadiusDp: Dp = 12.dp

private const val MinProgress: Float = 0F
private const val MaxProgress: Float = 1F

private const val MinSpikeHeight: Float = 1F
private const val DefaultGraphicsLayerAlpha: Float = 0.99F

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun AudioWaveform(
    modifier: Modifier = Modifier,
    style: DrawStyle = Fill,
    waveformBrush: Brush = SolidColor(Color.White),
    progressBrush: Brush = SolidColor(Color.Blue),
    waveformAlignment: WaveformAlignment = WaveformAlignment.Center,
    amplitudeType: AmplitudeType = AmplitudeType.Avg,
    onProgressChangeFinished: (() -> Unit)? = null,
    spikeAnimationSpec: AnimationSpec<Float> = tween(500),
    spikeWidth: Dp = 4.dp,
    spikeRadius: Dp = 2.dp,
    spikePadding: Dp = 1.dp,
    progress: Float = 0F,
    amplitudes: List<Int>,
    onProgressChange: (Float) -> Unit
) {
    val _progress = remember(progress) { progress.coerceIn(MinProgress, MaxProgress) }
    val _spikeWidth = remember(spikeWidth) { spikeWidth.coerceIn(MinSpikeWidthDp, MaxSpikeWidthDp) }
    val _spikePadding = remember(spikePadding) { spikePadding.coerceIn(MinSpikePaddingDp, MaxSpikePaddingDp) }
    val _spikeRadius = remember(spikeRadius) { spikeRadius.coerceIn(MinSpikeRadiusDp, MaxSpikeRadiusDp) }
    val _spikeTotalWidth = remember(spikeWidth, spikePadding) { _spikeWidth + _spikePadding }
    var canvasSize by remember { mutableStateOf(Size(0f, 0f)) }
    var spikes by remember { mutableStateOf(0F) }
    val spikesAmplitudes = remember(amplitudes, spikes, amplitudeType) {
        amplitudes.toDrawableAmplitudes(
            amplitudeType = amplitudeType,
            spikes = spikes.toInt(),
            minHeight = MinSpikeHeight,
            maxHeight = canvasSize.height.coerceAtLeast(MinSpikeHeight)
        )
    }.map { animateFloatAsState(it, spikeAnimationSpec).value }
    Canvas(
        modifier = Modifier
            .fillMaxWidth()
            .requiredHeight(48.dp)
            .graphicsLayer(alpha = DefaultGraphicsLayerAlpha)
            .pointerInteropFilter {
                return@pointerInteropFilter when (it.action) {
                    MotionEvent.ACTION_DOWN,
                    MotionEvent.ACTION_MOVE -> {
                        if (it.x in 0F..canvasSize.width) {
                            onProgressChange(it.x / canvasSize.width)
                            true
                        } else false
                    }
                    MotionEvent.ACTION_UP -> {
                        onProgressChangeFinished?.invoke()
                        true
                    }
                    else -> false
                }
            }
            .then(modifier)
    ) {
        canvasSize = size
        spikes = size.width / _spikeTotalWidth.toPx()
        spikesAmplitudes.forEachIndexed { index, amplitude ->
            drawRoundRect(
                brush = waveformBrush,
                topLeft = Offset(
                    x = index * _spikeTotalWidth.toPx(),
                    y = when(waveformAlignment) {
                        WaveformAlignment.Top -> 0F
                        WaveformAlignment.Bottom -> size.height - amplitude
                        WaveformAlignment.Center -> size.height / 2F - amplitude / 2F
                    }
                ),
                size = Size(
                    width = _spikeWidth.toPx(),
                    height = amplitude
                ),
                cornerRadius = CornerRadius(_spikeRadius.toPx(), _spikeRadius.toPx()),
                style = style
            )
            drawRect(
                brush = progressBrush,
                size = Size(
                    width = _progress * size.width,
                    height = size.height
                ),
                blendMode = BlendMode.SrcAtop
            )
        }
    }
}

private fun List<Int>.toDrawableAmplitudes(
    amplitudeType: AmplitudeType,
    spikes: Int,
    minHeight: Float,
    maxHeight: Float
): List<Float> {
    val amplitudes = map(Int::toFloat)
    if(amplitudes.isEmpty() || spikes == 0) {
        return List(spikes) { minHeight }
    }
    val transform = { data: List<Float> ->
        when(amplitudeType) {
            AmplitudeType.Avg -> data.average()
            AmplitudeType.Max -> data.max()
            AmplitudeType.Min -> data.min()
        }.toFloat().coerceIn(minHeight, maxHeight)
    }
    return when {
        spikes > amplitudes.count() -> amplitudes.fillToSize(spikes, transform)
        else -> amplitudes.chunkToSize(spikes, transform)
    }.normalize(minHeight, maxHeight)
}


internal fun <T> Iterable<T>.fillToSize(size: Int, transform: (List<T>) -> T): List<T> {
    val capacity = ceil(size.safeDiv(count())).roundToInt()
    return map { data -> List(capacity) { data } }.flatten().chunkToSize(size, transform)
}

internal fun <T> Iterable<T>.chunkToSize(size: Int, transform: (List<T>) -> T): List<T> {
    val chunkSize = count() / size
    val remainder = count() % size
    val remainderIndex = ceil(count().safeDiv(remainder)).roundToInt()
    val chunkIteration = filterIndexed { index, _ ->
        remainderIndex == 0 || index % remainderIndex != 0
    }.chunked(chunkSize, transform)
    return when (size) {
        chunkIteration.count() -> chunkIteration
        else -> chunkIteration.chunkToSize(size, transform)
    }
}

internal fun Iterable<Float>.normalize(min: Float, max: Float): List<Float> {
    return map { (max-min) * ((it - min()) / (max() - min())) + min }
}

private fun Int.safeDiv(value: Int): Float {
    return if(value == 0) return 0F else this / value.toFloat()
}

`
I really don't know if it's ok to use it like that

@lincollincol lincollincol self-assigned this Aug 6, 2023
@lincollincol lincollincol added the bug Something isn't working label Aug 6, 2023
@trinadhthatakula
Copy link

I am facing the same issue

java.lang.NoSuchMethodError: No static method drawRoundRect-ZuiqVtQ$default(Landroidx/compose/ui/graphics/drawscope/DrawScope;Landroidx/compose/ui/graphics/Brush;JJJFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;IILjava/lang/Object;)V in class Landroidx/compose/ui/graphics/drawscope/DrawScope; or its super classes (declaration of 'androidx.compose.ui.graphics.drawscope.DrawScope' appears in /data/app/~~QlVBT0ordaNSs-jft0tSEQ==/com.rms.musicplayer.music.audio.songs.media.mp3player-nwKc4yrj3ljnCG2s_p8RoQ==/base.apk) at com.linc.audiowaveform.AudioWaveformKt$AudioWaveform$2.invoke(AudioWaveform.kt:98) at com.linc.audiowaveform.AudioWaveformKt$AudioWaveform$2.invoke(AudioWaveform.kt:72) at androidx.compose.ui.draw.DrawBackgroundModifier.draw(DrawModifier.kt:116) at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105) at androidx.compose.ui.node.LayoutNodeDrawScope.draw-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:86) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:364) at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:353) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:176) at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:361) at androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers(NodeCoordinator.kt:54) at androidx.compose.ui.node.NodeCoordinator$drawBlock$1$1.invoke(NodeCoordinator.kt:383) at androidx.compose.ui.node.NodeCoordinator$drawBlock$1$1.invoke(NodeCoordinator.kt:382) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2303) at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:500) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:256) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133) at androidx.compose.ui.node.NodeCoordinator$drawBlock$1.invoke(NodeCoordinator.kt:382) at androidx.compose.ui.node.NodeCoordinator$drawBlock$1.invoke(NodeCoordinator.kt:380) at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:209) at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:335) at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:1236) at android.view.View.draw(View.java:24664) at android.view.View.updateDisplayListIfDirty(View.java:23469) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4628) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4601) at android.view.View.updateDisplayListIfDirty(View.java:23404) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4628) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4601) at android.view.View.updateDisplayListIfDirty(View.java:23404) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4628) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4601) at android.view.View.updateDisplayListIfDirty(View.java:23404) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4628) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4601) at android.view.View.updateDisplayListIfDirty(View.java:23404) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4628) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4601) at android.view.View.updateDisplayListIfDirty(View.java:23404) at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:736) at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:745) 16:51:47.875 E at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:851) (Ask Gemini) at android.view.ViewRootImpl.draw(ViewRootImpl.java:5670) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:5313) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4419) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2976) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:10422) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1671) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1680) at android.view.Choreographer.doCallbacks(Choreographer.java:1191) at android.view.Choreographer.doFrame(Choreographer.java:1063) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1650) at android.os.Handler.handleCallback(Handler.java:958) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:222) at android.os.Looper.loop(Looper.java:314) at android.app.ActivityThread.main(ActivityThread.java:8600) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:565) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants