diff --git a/project/app/src/gms/java/org/owntracks/android/ui/map/MapLayerStyle.kt b/project/app/src/gms/java/org/owntracks/android/ui/map/MapLayerStyle.kt
index 14093f1a50..e1b2c21da5 100644
--- a/project/app/src/gms/java/org/owntracks/android/ui/map/MapLayerStyle.kt
+++ b/project/app/src/gms/java/org/owntracks/android/ui/map/MapLayerStyle.kt
@@ -5,6 +5,10 @@ import kotlinx.serialization.Serializable
import org.owntracks.android.R
import org.owntracks.android.preferences.types.FromConfiguration
import org.owntracks.android.ui.map.osm.OSMMapFragment
+import org.osmdroid.tileprovider.tilesource.ITileSource
+import org.osmdroid.tileprovider.tilesource.TileSourceFactory
+import org.osmdroid.tileprovider.tilesource.XYTileSource
+import org.osmdroid.util.MapTileIndex
@Serializable
enum class MapLayerStyle {
@@ -13,10 +17,12 @@ enum class MapLayerStyle {
GoogleMapSatellite,
GoogleMapTerrain,
OpenStreetMapNormal,
- OpenStreetMapWikimedia;
+ OpenStreetMapWikimedia,
+ AmapVector,
+ AmapSatellite;
fun isSameProviderAs(mapLayerStyle: MapLayerStyle): Boolean {
- return setOf("GoogleMap", "OpenStreetMap").any {
+ return setOf("GoogleMap", "OpenStreetMap", "Amap").any {
name.startsWith(it) && mapLayerStyle.name.startsWith(it)
}
}
@@ -28,10 +34,24 @@ enum class MapLayerStyle {
GoogleMapSatellite,
GoogleMapTerrain -> GoogleMapFragment::class.java
OpenStreetMapNormal,
- OpenStreetMapWikimedia -> OSMMapFragment::class.java
+ OpenStreetMapWikimedia,
+ AmapVector,
+ AmapSatellite -> OSMMapFragment::class.java
}
}
+ fun getTileSource(): ITileSource =
+ when (this) {
+ OpenStreetMapNormal -> TileSourceFactory.MAPNIK
+ OpenStreetMapWikimedia -> TileSourceFactory.WIKIMEDIA
+ AmapVector -> AMAP_VECTOR
+ AmapSatellite -> AMAP_SATELLITE
+ GoogleMapDefault,
+ GoogleMapHybrid,
+ GoogleMapSatellite,
+ GoogleMapTerrain -> TileSourceFactory.MAPNIK
+ }
+
companion object {
@JvmStatic
@FromConfiguration
@@ -40,10 +60,58 @@ enum class MapLayerStyle {
}
}
+private val AMAP_VECTOR: ITileSource =
+ object :
+ XYTileSource(
+ "AmapVector",
+ 1,
+ 18,
+ 256,
+ ".png",
+ arrayOf(
+ "https://webrd01.is.autonavi.com/",
+ "https://webrd02.is.autonavi.com/",
+ "https://webrd03.is.autonavi.com/",
+ "https://webrd04.is.autonavi.com/")) {
+ override fun getTileURLString(pMapTileIndex: Long): String {
+ val z = MapTileIndex.getZoom(pMapTileIndex)
+ val x = MapTileIndex.getX(pMapTileIndex)
+ val y = MapTileIndex.getY(pMapTileIndex)
+ return "${getBaseUrl()}appmaptile?lang=zh_cn&size=1&scale=1&style=8&x=$x&y=$y&z=$z"
+ }
+
+ override fun getCopyrightNotice(): String = "© Amap.com"
+ }
+
+private val AMAP_SATELLITE: ITileSource =
+ object :
+ XYTileSource(
+ "AmapSatellite",
+ 1,
+ 18,
+ 256,
+ ".jpg",
+ arrayOf(
+ "https://webst01.is.autonavi.com/",
+ "https://webst02.is.autonavi.com/",
+ "https://webst03.is.autonavi.com/",
+ "https://webst04.is.autonavi.com/")) {
+ override fun getTileURLString(pMapTileIndex: Long): String {
+ val z = MapTileIndex.getZoom(pMapTileIndex)
+ val x = MapTileIndex.getX(pMapTileIndex)
+ val y = MapTileIndex.getY(pMapTileIndex)
+ return "${getBaseUrl()}appmaptile?style=6&x=$x&y=$y&z=$z"
+ }
+
+ override fun getCopyrightNotice(): String = "© Amap.com"
+ }
+
val mapLayerSelectorButtonsToStyles =
mapOf(
R.id.fabMapLayerGoogleNormal to MapLayerStyle.GoogleMapDefault,
R.id.fabMapLayerGoogleHybrid to MapLayerStyle.GoogleMapHybrid,
R.id.fabMapLayerGoogleTerrain to MapLayerStyle.GoogleMapTerrain,
R.id.fabMapLayerOpenStreetMap to MapLayerStyle.OpenStreetMapNormal,
- R.id.fabMapLayerOpenStreetMapWikimedia to MapLayerStyle.OpenStreetMapWikimedia)
+ R.id.fabMapLayerOpenStreetMapWikimedia to MapLayerStyle.OpenStreetMapWikimedia,
+ R.id.fabMapLayerAmapVector to MapLayerStyle.AmapVector,
+ R.id.fabMapLayerAmapSatellite to MapLayerStyle.AmapSatellite)
\ No newline at end of file
diff --git a/project/app/src/gms/res/layout/map_layer_bottom_sheet_dialog.xml b/project/app/src/gms/res/layout/map_layer_bottom_sheet_dialog.xml
index 6c08a44bc3..08e7f583f6 100644
--- a/project/app/src/gms/res/layout/map_layer_bottom_sheet_dialog.xml
+++ b/project/app/src/gms/res/layout/map_layer_bottom_sheet_dialog.xml
@@ -148,6 +148,51 @@
android:textAlignment="center" />
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/project/app/src/main/java/org/owntracks/android/ui/map/osm/OSMMapFragment.kt b/project/app/src/main/java/org/owntracks/android/ui/map/osm/OSMMapFragment.kt
index 0c81af3b61..c48146820e 100644
--- a/project/app/src/main/java/org/owntracks/android/ui/map/osm/OSMMapFragment.kt
+++ b/project/app/src/main/java/org/owntracks/android/ui/map/osm/OSMMapFragment.kt
@@ -25,7 +25,6 @@ import org.osmdroid.events.DelayedMapListener
import org.osmdroid.events.MapListener
import org.osmdroid.events.ScrollEvent
import org.osmdroid.events.ZoomEvent
-import org.osmdroid.tileprovider.tilesource.TileSourceFactory
import org.osmdroid.util.TileSystemWebMercator
import org.osmdroid.views.CustomZoomButtonsController
import org.osmdroid.views.MapView
@@ -440,13 +439,7 @@ internal constructor(
}
override fun setMapLayerType(mapLayerStyle: MapLayerStyle) {
- when (mapLayerStyle) {
- MapLayerStyle.OpenStreetMapNormal ->
- binding.osmMapView.setTileSource(TileSourceFactory.MAPNIK)
- MapLayerStyle.OpenStreetMapWikimedia ->
- binding.osmMapView.setTileSource(TileSourceFactory.WIKIMEDIA)
- else -> Timber.w("Unsupported map layer type $mapLayerStyle")
- }
+ binding.osmMapView.setTileSource(mapLayerStyle.getTileSource())
}
fun createPolygon(mapView: MapView, waypoint: WaypointModel): Polygon {
diff --git a/project/app/src/main/res/drawable/ic_amap_logo.xml b/project/app/src/main/res/drawable/ic_amap_logo.xml
new file mode 100644
index 0000000000..cdc762084e
--- /dev/null
+++ b/project/app/src/main/res/drawable/ic_amap_logo.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/project/app/src/main/res/values-zh/strings.xml b/project/app/src/main/res/values-zh/strings.xml
index dd4fd557d4..6faae36d23 100644
--- a/project/app/src/main/res/values-zh/strings.xml
+++ b/project/app/src/main/res/values-zh/strings.xml
@@ -108,6 +108,8 @@
"Google 地形"
"OpenStreetMap"
"维基媒体"
+ "高德地图"
+ "高德卫星图"
"清除"
"导航"
"模式"
diff --git a/project/app/src/main/res/values/strings.xml b/project/app/src/main/res/values/strings.xml
index d182ffc3b9..54e5659d98 100644
--- a/project/app/src/main/res/values/strings.xml
+++ b/project/app/src/main/res/values/strings.xml
@@ -114,6 +114,8 @@ To allow this, please enable Location in the device settings."
"Google Terrain"
"OpenStreetMap"
"Wikimedia"
+ "Amap"
+ "Amap Satellite"
"Clear"
"Navigate"
"Request Location"
diff --git a/project/app/src/oss/java/org/owntracks/android/ui/map/MapLayerStyle.kt b/project/app/src/oss/java/org/owntracks/android/ui/map/MapLayerStyle.kt
index af2096acde..4211d406c9 100644
--- a/project/app/src/oss/java/org/owntracks/android/ui/map/MapLayerStyle.kt
+++ b/project/app/src/oss/java/org/owntracks/android/ui/map/MapLayerStyle.kt
@@ -3,23 +3,104 @@ package org.owntracks.android.ui.map
import kotlinx.serialization.Serializable
import org.owntracks.android.R
import org.owntracks.android.preferences.types.FromConfiguration
+import org.osmdroid.tileprovider.tilesource.ITileSource
+import org.osmdroid.tileprovider.tilesource.TileSourceFactory
+import org.osmdroid.tileprovider.tilesource.XYTileSource
+import org.osmdroid.util.MapTileIndex
@Serializable
enum class MapLayerStyle {
OpenStreetMapNormal,
- OpenStreetMapWikimedia;
+ OpenStreetMapWikimedia,
+ AmapVector,
+ AmapSatellite;
- fun isSameProviderAs(@Suppress("UNUSED_PARAMETER") mapLayerStyle: MapLayerStyle): Boolean = true
+ fun isSameProviderAs(mapLayerStyle: MapLayerStyle): Boolean {
+ return providerGroup() == mapLayerStyle.providerGroup()
+ }
+
+ private fun providerGroup(): String =
+ when (this) {
+ OpenStreetMapNormal,
+ OpenStreetMapWikimedia -> "OpenStreetMap"
+ AmapVector,
+ AmapSatellite -> "Amap"
+ }
+
+ fun getTileSource(): ITileSource =
+ when (this) {
+ OpenStreetMapNormal -> TileSourceFactory.MAPNIK
+ OpenStreetMapWikimedia -> TileSourceFactory.WIKIMEDIA
+ AmapVector -> AMAP_VECTOR
+ AmapSatellite -> AMAP_SATELLITE
+ }
companion object {
@JvmStatic
@FromConfiguration
fun getByValue(value: String): MapLayerStyle =
- MapLayerStyle.values().firstOrNull { it.name.equals(value, true) } ?: OpenStreetMapNormal
+ entries.firstOrNull { it.name.equals(value, true) } ?: OpenStreetMapNormal
}
}
+/**
+ * Amap (高德) vector tiles served over HTTPS without an API key. The URL pattern uses query
+ * string parameters rather than the standard `{z}/{x}/{y}.png` slippy map convention, so we
+ * subclass XYTileSource to override the URL builder.
+ */
+private val AMAP_VECTOR: ITileSource =
+ object :
+ XYTileSource(
+ "AmapVector",
+ 1,
+ 18,
+ 256,
+ ".png",
+ arrayOf(
+ "https://webrd01.is.autonavi.com/",
+ "https://webrd02.is.autonavi.com/",
+ "https://webrd03.is.autonavi.com/",
+ "https://webrd04.is.autonavi.com/")) {
+ override fun getTileURLString(pMapTileIndex: Long): String {
+ val z = MapTileIndex.getZoom(pMapTileIndex)
+ val x = MapTileIndex.getX(pMapTileIndex)
+ val y = MapTileIndex.getY(pMapTileIndex)
+ return "${getBaseUrl()}appmaptile?lang=zh_cn&size=1&scale=1&style=8&x=$x&y=$y&z=$z"
+ }
+
+ override fun getCopyrightNotice(): String = "© Amap.com"
+ }
+
+/**
+ * Amap satellite imagery tiles (no API key required). Uses the `webst0X` subdomain (different
+ * from the vector layer's `webrd0X`) and the `style=6` parameter for raster imagery.
+ */
+private val AMAP_SATELLITE: ITileSource =
+ object :
+ XYTileSource(
+ "AmapSatellite",
+ 1,
+ 18,
+ 256,
+ ".jpg",
+ arrayOf(
+ "https://webst01.is.autonavi.com/",
+ "https://webst02.is.autonavi.com/",
+ "https://webst03.is.autonavi.com/",
+ "https://webst04.is.autonavi.com/")) {
+ override fun getTileURLString(pMapTileIndex: Long): String {
+ val z = MapTileIndex.getZoom(pMapTileIndex)
+ val x = MapTileIndex.getX(pMapTileIndex)
+ val y = MapTileIndex.getY(pMapTileIndex)
+ return "${getBaseUrl()}appmaptile?style=6&x=$x&y=$y&z=$z"
+ }
+
+ override fun getCopyrightNotice(): String = "© Amap.com"
+ }
+
val mapLayerSelectorButtonsToStyles =
mapOf(
R.id.fabMapLayerOpenStreetMap to MapLayerStyle.OpenStreetMapNormal,
- R.id.fabMapLayerOpenStreetMapWikimedia to MapLayerStyle.OpenStreetMapWikimedia)
+ R.id.fabMapLayerOpenStreetMapWikimedia to MapLayerStyle.OpenStreetMapWikimedia,
+ R.id.fabMapLayerAmapVector to MapLayerStyle.AmapVector,
+ R.id.fabMapLayerAmapSatellite to MapLayerStyle.AmapSatellite)
\ No newline at end of file
diff --git a/project/app/src/oss/res/layout/map_layer_bottom_sheet_dialog.xml b/project/app/src/oss/res/layout/map_layer_bottom_sheet_dialog.xml
index bb4b7405c4..dc96bcf039 100644
--- a/project/app/src/oss/res/layout/map_layer_bottom_sheet_dialog.xml
+++ b/project/app/src/oss/res/layout/map_layer_bottom_sheet_dialog.xml
@@ -15,17 +15,18 @@
android:text="@string/mapLayerDialogTitle"
android:textStyle="bold" />
-
-
+ android:columnCount="2"
+ android:rowCount="2">
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
\ No newline at end of file