diff --git a/build.gradle.kts b/build.gradle.kts index a9fbead..cf5f23c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,6 +29,7 @@ android { defaultConfig { minSdk = project.property("minSdk").toString().toInt() + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") } @@ -77,6 +78,10 @@ dependencies { } testImplementation(libs.junit) + + // Saver の保存 → 復元を実機の Bundle / Parcel で確かめる(SaverRoundTripTest)。 + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) } // Set project version for NMCP plugin diff --git a/src/androidTest/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewSaverTest.kt b/src/androidTest/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewSaverTest.kt new file mode 100644 index 0000000..9a55e89 --- /dev/null +++ b/src/androidTest/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewSaverTest.kt @@ -0,0 +1,85 @@ +package com.mapconductor.openmobilemaps + +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.Assert.assertSame +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import android.os.Bundle +import android.os.Parcel + +/** + * 回転などの構成変更で state が [OpenMobileMapsMapViewSaver] を通って作り直されても、デザイン(id・ + * attributionRules ほか)と uiSettings・カメラが落ちないこと。Bundle は実機の Parcel を一度通す。 + */ +@RunWith(AndroidJUnit4::class) +class OpenMobileMapsMapViewSaverTest { + 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 keepsDesignWithAttributionRules() { + val design = + OpenMobileMapsDesign( + id = "my-tiles", + tileUrlTemplate = "https://tiles.example.com/{z}/{x}/{y}.png", + tileSize = 512, + attributionRules = rules, + ) + val state = OpenMobileMapsViewState(mapDesignType = design, id = "omm-1", cameraPosition = camera) + state.uiSettings = MapUISettings(rotateGesture = false, tiltGesture = false) + + val restored = roundTrip(OpenMobileMapsMapViewSaver().createSaver(), state) + + assertEquals(design, restored.mapDesignType) + assertCommon(restored, "omm-1") + } + + @Test + fun keepsPresetDesignAndItsAttribution() { + val state = OpenMobileMapsViewState(mapDesignType = OpenMobileMapsDesign.OpenTopoMap, id = "omm-2") + val restored = roundTrip(OpenMobileMapsMapViewSaver().createSaver(), state) + assertEquals(OpenMobileMapsDesign.OpenTopoMap, restored.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 roundTrip( + saver: Saver, + 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() + } + } +} diff --git a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt index e347a9d..f2ae8f9 100644 --- a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt +++ b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapView.kt @@ -18,6 +18,7 @@ import com.mapconductor.core.map.CameraRestriction import com.mapconductor.core.map.MapCameraPosition import com.mapconductor.core.map.MapCameraPositionInterface import com.mapconductor.core.map.MapViewState +import com.mapconductor.core.map.MapViewStateBundle import com.mapconductor.core.map.MapViewStateInterface import com.mapconductor.core.map.MapViewStyle import com.mapconductor.core.map.MutableMapServiceRegistry @@ -99,6 +100,7 @@ class OpenMobileMapsMapViewSaver : BaseMapViewSaver() { bundle.putString("id", state.mapDesignType.id) bundle.putString("tileUrlTemplate", state.mapDesignType.tileUrlTemplate) bundle.putInt("tileSize", state.mapDesignType.tileSize) + MapViewStateBundle.putAttributionRules(bundle, state.mapDesignType.attributionRules) } override fun createState( @@ -115,6 +117,7 @@ class OpenMobileMapsMapViewSaver : BaseMapViewSaver() { mapDesignBundle?.getString("tileUrlTemplate") ?: OpenMobileMapsDesign.OpenStreetMap.tileUrlTemplate, tileSize = mapDesignBundle?.getInt("tileSize")?.takeIf { it > 0 } ?: 256, + attributionRules = MapViewStateBundle.getAttributionRules(mapDesignBundle), ), cameraPosition = cameraPosition, )