Skip to content

google map crashed with instrumentation test #211

@rakshitsoni02

Description

@rakshitsoni02

Device: Pixel 5 API 30
sdk version: 2.5.3 & 2.7.2

i've implemented GoogleMap with ComposeView, it's crashing in the instrumentation test case with the following stack trace:

 com.google.maps.api.android.lib6.common.apiexception.c: Not on the main thread
    at com.google.maps.api.android.lib6.common.m.i(:com.google.android.gms.dynamite_mapsdynamite@[email protected] (150400-0):0)
    at com.google.maps.api.android.lib6.common.r.a(:com.google.android.gms.dynamite_mapsdynamite@[email protected] (150400-0):2)
    at com.google.maps.api.android.lib6.impl.bj.p(:com.google.android.gms.dynamite_mapsdynamite@[email protected] (150400-0):1)
    at com.google.android.gms.maps.internal.i.ba(:com.google.android.gms.dynamite_mapsdynamite@[email protected] (150400-0):186)
    at en.onTransact(:com.google.android.gms.dynamite_mapsdynamite@[email protected] (150400-0):4)
    at android.os.Binder.transact(Binder.java:1043)
    at com.google.android.gms.internal.maps.zza.zzc(com.google.android.gms:play-services-maps@@18.1.0:2)
    at com.google.android.gms.maps.internal.zzg.clear(com.google.android.gms:play-services-maps@@18.1.0:2)
    at com.google.android.gms.maps.GoogleMap.clear(com.google.android.gms:play-services-maps@@18.1.0:1)
    at com.google.maps.android.compose.MapApplier.onClear(MapApplier.kt:46)
    at androidx.compose.runtime.AbstractApplier.clear(Applier.kt:213)
    at androidx.compose.runtime.CompositionImpl.dispose(Composition.kt:601)
    at com.google.maps.android.compose.GoogleMapKt$GoogleMap$10.invokeSuspend(GoogleMap.kt:229)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at androidx.compose.ui.test.ApplyingContinuationInterceptor$SendApplyContinuation.resumeWith(ApplyingContinuationInterceptor.kt:70)
    at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234)
    at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:190)
    at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:161)
    at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
    at kotlinx.coroutines.CancellableContinuationImpl.cancel(CancellableContinuationImpl.kt:183)
    at kotlinx.coroutines.CancellableContinuationImpl.parentCancelled$kotlinx_coroutines_core(CancellableContinuationImpl.kt:190)
    at kotlinx.coroutines.ChildContinuation.invoke(JobSupport.kt:1475)
    at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1500)
    at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:795)
    at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:755)
    at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:671)
    at kotlinx.coroutines.JobSupport.parentCancelled(JobSupport.kt:637)
    at kotlinx.coroutines.ChildHandleNode.invoke(JobSupport.kt:1466)
    at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1500)
    at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:900)
    at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:863)
    at kotlinx.coroutines.JobSupport.cancelMakeCompleting(JobSupport.kt:696)
    at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:667)
    at kotlinx.coroutines.JobSupport.cancelInternal(JobSupport.kt:632)
    at kotlinx.coroutines.JobSupport.cancel(JobSupport.kt:617)
    at kotlinx.coroutines.Job$DefaultImpls.cancel$default(Job.kt:183)
    at androidx.compose.runtime.Recomposer.cancel(Recomposer.kt:781)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withWindowRecomposer(ComposeUiTest.android.kt:324)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withWindowRecomposer(ComposeUiTest.android.kt:217)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1.invoke(ComposeUiTest.android.kt:291)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withTestCoroutines(ComposeUiTest.android.kt:334)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withTestCoroutines(ComposeUiTest.android.kt:217)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1.invoke(ComposeUiTest.android.kt:290)
    at androidx.compose.ui.test.junit4.EspressoLink.withStrategy(EspressoLink.android.kt:66)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1.invoke(ComposeUiTest.android.kt:289)
    at androidx.compose.ui.test.junit4.IdlingResourceRegistry.withRegistry(IdlingResourceRegistry.jvm.kt:157)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1.invoke(ComposeUiTest.android.kt:288)
    at androidx.compose.ui.test.junit4.ComposeRootRegistry.withRegistry(ComposeRootRegistry.android.kt:146)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.runTest(ComposeUiTest.android.kt:287)
    at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1.evaluate(AndroidComposeTestRule.android.kt:147)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:162)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
    at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:444)
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2205)

ComposeView:

 <androidx.compose.ui.platform.ComposeView
                android:id="@+id/map_compose_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/black_50"
                android:paddingHorizontal="14dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/venue_section" />

component:

@Composable
fun MiniMap(
    latLng: LatLng,
    modifier: Modifier = Modifier,
    cornerRadius: Int = 10,
    isMapUIControlsEnabled: Boolean = false,
    onMapViewClicked: (() -> Unit)? = null
) {
    val radius = LocalDensity.current.run { cornerRadius.dp.toPx() }
    Box(
        modifier = modifier
            .clip(RoundedCornerShape(radius))
    ) {
        val context = LocalContext.current
        val cameraPositionState = rememberCameraPositionState {
            position = CameraPosition.fromLatLngZoom(latLng, MAP_ZOOM_LEVEL)
        }
        val uiSettings by remember {
            mutableStateOf(
                MapUiSettings(
                    compassEnabled = false,
                    zoomControlsEnabled = isMapUIControlsEnabled,
                    zoomGesturesEnabled = isMapUIControlsEnabled,
                    tiltGesturesEnabled = isMapUIControlsEnabled,
                    indoorLevelPickerEnabled = isMapUIControlsEnabled,
                    mapToolbarEnabled = isMapUIControlsEnabled,
                    myLocationButtonEnabled = isMapUIControlsEnabled,
                    scrollGesturesEnabled = isMapUIControlsEnabled,
                    scrollGesturesEnabledDuringRotateOrZoom = isMapUIControlsEnabled,
                )
            )
        }
        GoogleMap(
            modifier = Modifier.fillMaxSize(),
            uiSettings = uiSettings,
            cameraPositionState = cameraPositionState,
            onMapClick = {
                onMapViewClicked?.invoke()
            },
            properties = MapProperties(
                mapStyleOptions = MapStyleOptions.loadRawResourceStyle(context, resourcesR.raw.google_map_style)
            )
        ) {
            Marker(
                state = MarkerState(position = latLng),
                onClick = {
                    onMapViewClicked?.invoke()
                    true
                },
                icon = ContextCompat.getDrawable(
                    context,
                    resourcesR.drawable.ic_dot_filled_36
                )?.let {
                    bitMapFromVector(
                        vectorDrawable = it,
                        iconTint = ContextCompat.getColor(context, resourcesR.color.dice_yellow)
                    )
                }
            )
        }
    }
}

I've tried running the test on the UI thread but no luck it seems like an issue when disposing of the mapview. The implementation used from the activity also tried setting different disposition strategy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs more infoThis issue needs more information from the customer to proceed.priority: p2Moderately-important priority. Fix may not be included in next release.releasedtype: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions