Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.mapconductor.arcgis

import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.SaverScope
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.mapconductor.core.features.GeoPoint
import com.mapconductor.core.map.AttributionRule
import com.mapconductor.core.map.MapCameraPosition
import com.mapconductor.core.map.MapUISettings
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import android.os.Bundle
import android.os.Parcel

/**
* 回転などの構成変更で state が [ArcGISMapViewSaver] を通って作り直されても、デザイン(id・
* attributionRules ほか)と uiSettings・カメラが落ちないこと。Bundle は実機の Parcel を一度通す。
*/
@RunWith(AndroidJUnit4::class)
class ArcGISMapViewSaverTest {
private val rules =
listOf(AttributionRule("© test"), AttributionRule("© ranged", minZoom = 3, maxZoom = 15))

private val camera =
MapCameraPosition(
position = GeoPoint(21.38, -157.93),
zoom = 12.0,
bearing = 20.0,
tilt = 10.0,
)

@Test
fun keepsElevationSourcesAndAttributionRules() {
val design =
ArcGISDesign.Imagery.copy(
elevationSources = listOf("https://elevation.example.com/ImageServer"),
attributionRules = rules,
)
val state = ArcGISMapViewState(mapDesignType = design, id = "arcgis-1", cameraPosition = camera)
state.uiSettings = MapUISettings(rotateGesture = false, tiltGesture = false)

val restored = roundTrip(ArcGISMapViewSaver().createSaver(), state)

// 以前は id しか保存しておらず、elevationSources と attributionRules が落ちていた。
assertEquals(design, restored.mapDesignType)
assertCommon(restored, "arcgis-1")
}

@Test
fun keepsPresetDesign() {
val state = ArcGISMapViewState(mapDesignType = ArcGISDesign.DarkGray, id = "arcgis-2")
assertEquals(ArcGISDesign.DarkGray, roundTrip(ArcGISMapViewSaver().createSaver(), state).mapDesignType)
}

private fun assertCommon(
restored: com.mapconductor.core.map.MapViewStateInterface<*>,
id: String,
) {
assertEquals(id, restored.id)
assertEquals(false, restored.uiSettings.rotateGesture)
assertEquals(false, restored.uiSettings.tiltGesture)
assertEquals(true, restored.uiSettings.scrollGesture)
assertEquals(12.0, restored.cameraPosition.zoom, 1e-9)
assertEquals(20.0, restored.cameraPosition.bearing, 1e-9)
assertEquals(21.38, restored.cameraPosition.position.latitude, 1e-9)
}

private fun <T : Any> roundTrip(
saver: Saver<T, Bundle>,
value: T,
): T {
val saved = with(saver) { SaverScope { true }.save(value) }!!
// 一度 Parcel に書いて読み戻す(プロセスが落ちたあとの復元と同じ経路)。
val parcel = Parcel.obtain()
try {
parcel.writeBundle(saved)
parcel.setDataPosition(0)
return saver.restore(parcel.readBundle(javaClass.classLoader)!!)!!
} finally {
parcel.recycle()
}
}
}
4 changes: 4 additions & 0 deletions src/main/java/com/mapconductor/arcgis/ArcGISMapView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ fun ArcGISMapView(
controllerRef.value = mapController
mapController.setMapClickListener(onMapClick)
mapController.setMapLongClickListener(onMapLongClick)
// 地図は state のデザインで作ってある。コントローラの既定値(Streets)のままだと、
// 次の行のリスナー登録でそれが state へ返り、アプリが渡した(あるいは
// 回転後に復元した)デザインが Streets に化ける。
mapController.mapDesignType = state.mapDesignType
mapController.setMapDesignTypeChangeListener(state::onMapDesignTypeChange)
cameraRestriction?.let { mapController.setCameraRestriction(it) }
state.setController(mapController)
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/mapconductor/arcgis/ArcGISMapView2D.kt
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ fun ArcGISMapView2D(
controllerRef.value = mapController
mapController.setMapClickListener(onMapClick)
mapController.setMapLongClickListener(onMapLongClick)
// 地図は state のデザインで作ってある。コントローラの既定値(Streets)のままだと、
// 次の行のリスナー登録でそれが state へ返り、アプリが渡した(あるいは
// 回転後に復元した)デザインが Streets に化ける。
mapController.mapDesignType = state.mapDesignType
mapController.setMapDesignTypeChangeListener(state::onMapDesignTypeChange)
state.setController(mapController)
if (state.mapDesignType.getValue() !=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ class ArcGISMapView2DController(
}

override fun setMapDesignType(value: ArcGISDesignTypeInterface) {
mapDesignType = value
val map = holder.map.map ?: return
map.setBasemap(ArcGISDesign.toBasemap(value))
// A map that failed to load -- its basemap was out of reach -- gets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ class ArcGISMapViewController(
internal var mapDesignTypeChangeListener: ArcGISDesignTypeChangeHandler? = null

override fun setMapDesignType(value: ArcGISDesignTypeInterface) {
mapDesignType = value
holder.map.scene?.let { scene ->
val baseMap = ArcGISDesign.toBasemap(value)
defaultCoroutine.launch {
Expand Down
12 changes: 10 additions & 2 deletions src/main/java/com/mapconductor/arcgis/ArcGISMapViewStateImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.mapconductor.core.map.MapCameraPositionInterface
import com.mapconductor.core.map.MapPaddings
import com.mapconductor.core.map.MapPaddingsInterface
import com.mapconductor.core.map.MapViewState
import com.mapconductor.core.map.MapViewStateBundle
import com.mapconductor.core.map.MapViewStateInterface
import java.util.UUID
import android.app.Activity
Expand Down Expand Up @@ -78,7 +79,10 @@ class ArcGISMapViewSaver : BaseMapViewSaver<ArcGISMapViewState>() {
state: ArcGISMapViewState,
bundle: Bundle,
) {
bundle.putString("id", state.mapDesignType.id)
val design = state.mapDesignType
bundle.putString("id", design.id)
bundle.putStringArrayList("elevationSources", ArrayList(design.elevationSources))
MapViewStateBundle.putAttributionRules(bundle, design.attributionRules)
}

override fun createState(
Expand All @@ -88,9 +92,13 @@ class ArcGISMapViewSaver : BaseMapViewSaver<ArcGISMapViewState>() {
): ArcGISMapViewState =
ArcGISMapViewState(
id = stateId,
// ArcGISDesign はデータクラスなので、同じ値で作れば Streets などの定義済みと等しくなる。
// Create(id) を使うと elevationSources と attributionRules が落ちる。
mapDesignType =
ArcGISDesign.Create(
ArcGISDesign(
id = mapDesignBundle?.getString("id") ?: ArcGISDesign.Streets.id,
elevationSources = mapDesignBundle?.getStringArrayList("elevationSources") ?: emptyList(),
attributionRules = MapViewStateBundle.getAttributionRules(mapDesignBundle),
),
cameraPosition = cameraPosition,
)
Expand Down
Loading