mirror of
https://github.com/TeamVanced/VancedMicroG
synced 2025-02-22 23:41:09 +01:00
Various fixes and improvements to Maps API
This commit is contained in:
parent
73fd85a8c7
commit
73aca6ea10
2
extern/GmsApi
vendored
2
extern/GmsApi
vendored
@ -1 +1 @@
|
||||
Subproject commit 7197b8320b4e6d55d15b76d4faf05adaba36bf72
|
||||
Subproject commit bfe649fc36a40e2498f1ecf123edfb9278fe0a1d
|
@ -16,18 +16,20 @@
|
||||
|
||||
package org.microg.gms.maps.mapbox
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.location.Location
|
||||
import android.os.Bundle
|
||||
import android.os.Parcel
|
||||
import android.os.RemoteException
|
||||
import android.support.annotation.IdRes
|
||||
import android.support.annotation.Keep
|
||||
import android.support.v4.util.LongSparseArray
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Log
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.RelativeLayout
|
||||
import com.google.android.gms.dynamic.IObjectWrapper
|
||||
import com.google.android.gms.maps.GoogleMapOptions
|
||||
import com.google.android.gms.maps.internal.*
|
||||
@ -38,6 +40,7 @@ import com.mapbox.mapboxsdk.LibraryLoader
|
||||
import com.mapbox.mapboxsdk.Mapbox
|
||||
import com.mapbox.mapboxsdk.R
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdate
|
||||
import com.mapbox.mapboxsdk.constants.MapboxConstants
|
||||
import com.mapbox.mapboxsdk.maps.MapView
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
@ -53,9 +56,9 @@ import org.microg.gms.maps.mapbox.utils.MultiArchLoader
|
||||
import org.microg.gms.maps.mapbox.utils.toGms
|
||||
import org.microg.gms.maps.mapbox.utils.toMapbox
|
||||
|
||||
fun <T : Any> LongSparseArray<T>.values() = (0..size()).map { valueAt(it) }.mapNotNull { it }
|
||||
private fun <T : Any> LongSparseArray<T>.values() = (0..size()).map { valueAt(it) }.mapNotNull { it }
|
||||
|
||||
class GoogleMapImpl(private val context: Context, private val options: GoogleMapOptions) : IGoogleMapDelegate.Stub() {
|
||||
class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions) : IGoogleMapDelegate.Stub() {
|
||||
|
||||
val view: FrameLayout
|
||||
var map: MapboxMap? = null
|
||||
@ -64,10 +67,10 @@ class GoogleMapImpl(private val context: Context, private val options: GoogleMap
|
||||
get() = context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT
|
||||
|
||||
private var mapView: MapView?
|
||||
private var created = false
|
||||
private var initialized = false
|
||||
private val initializedCallbackList = mutableListOf<IOnMapReadyCallback>()
|
||||
private val mapLock = Object()
|
||||
val markers = mutableMapOf<Long, MarkerImpl>()
|
||||
|
||||
private var cameraChangeListener: IOnCameraChangeListener? = null
|
||||
private var cameraMoveListener: IOnCameraMoveListener? = null
|
||||
@ -79,47 +82,130 @@ class GoogleMapImpl(private val context: Context, private val options: GoogleMap
|
||||
private var markerClickListener: IOnMarkerClickListener? = null
|
||||
private var markerDragListener: IOnMarkerDragListener? = null
|
||||
|
||||
var circleManager: CircleManager? = null
|
||||
var lineManager: LineManager? = null
|
||||
var fillManager: FillManager? = null
|
||||
|
||||
var circleManager: CircleManager? = null
|
||||
val pendingCircles = mutableSetOf<CircleImpl>()
|
||||
var circleId = 0L
|
||||
|
||||
var symbolManager: SymbolManager? = null
|
||||
var storedMapType: Int = MAP_TYPE_NORMAL
|
||||
val pendingMarkers = mutableSetOf<MarkerImpl>()
|
||||
val markers = mutableMapOf<Long, MarkerImpl>()
|
||||
var markerId = 0L
|
||||
|
||||
var storedMapType: Int = options.mapType
|
||||
val waitingCameraUpdates = mutableListOf<CameraUpdate>()
|
||||
|
||||
init {
|
||||
val mapContext = MapContext(context)
|
||||
LibraryLoader.setLibraryLoader(MultiArchLoader(mapContext, context))
|
||||
Mapbox.getInstance(mapContext, BuildConfig.MAPBOX_KEY)
|
||||
|
||||
val fakeWatermark = View(mapContext)
|
||||
fakeWatermark.layoutParams = object : RelativeLayout.LayoutParams(0, 0) {
|
||||
@SuppressLint("RtlHardcoded")
|
||||
override fun addRule(verb: Int, subject: Int) {
|
||||
super.addRule(verb, subject)
|
||||
val rules = this.rules
|
||||
var gravity = 0
|
||||
if (rules[RelativeLayout.ALIGN_PARENT_BOTTOM] == RelativeLayout.TRUE) gravity = gravity or Gravity.BOTTOM
|
||||
if (rules[RelativeLayout.ALIGN_PARENT_TOP] == RelativeLayout.TRUE) gravity = gravity or Gravity.TOP
|
||||
if (rules[RelativeLayout.ALIGN_PARENT_LEFT] == RelativeLayout.TRUE) gravity = gravity or Gravity.LEFT
|
||||
if (rules[RelativeLayout.ALIGN_PARENT_RIGHT] == RelativeLayout.TRUE) gravity = gravity or Gravity.RIGHT
|
||||
if (rules[RelativeLayout.ALIGN_PARENT_START] == RelativeLayout.TRUE) gravity = gravity or Gravity.START
|
||||
if (rules[RelativeLayout.ALIGN_PARENT_END] == RelativeLayout.TRUE) gravity = gravity or Gravity.END
|
||||
map?.uiSettings?.logoGravity = gravity
|
||||
}
|
||||
}
|
||||
this.view = object : FrameLayout(mapContext) {
|
||||
@Keep
|
||||
fun <T : View> findViewTraversal(@IdRes id: Int): T? {
|
||||
return null
|
||||
}
|
||||
|
||||
@Keep
|
||||
fun <T : View> findViewWithTagTraversal(tag: Any): T? {
|
||||
if ("GoogleWatermark" == tag) {
|
||||
return try {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fakeWatermark as T
|
||||
} catch (e: ClassCastException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
this.mapView = MapView(mapContext)
|
||||
this.view.addView(this.mapView)
|
||||
}
|
||||
|
||||
override fun getCameraPosition(): CameraPosition? = map?.cameraPosition?.toGms()
|
||||
override fun getMaxZoomLevel(): Float = map?.maxZoomLevel?.toFloat() ?: 20f
|
||||
override fun getMinZoomLevel(): Float = map?.minZoomLevel?.toFloat() ?: 1f
|
||||
override fun getMaxZoomLevel(): Float = (map?.maxZoomLevel?.toFloat() ?: 20f) + 1f
|
||||
override fun getMinZoomLevel(): Float = (map?.minZoomLevel?.toFloat() ?: 0f) + 1f
|
||||
|
||||
override fun moveCamera(cameraUpdate: IObjectWrapper?) =
|
||||
cameraUpdate.unwrap<CameraUpdate>()?.let { map?.moveCamera(it) } ?: Unit
|
||||
override fun moveCamera(cameraUpdate: IObjectWrapper?) {
|
||||
val update = cameraUpdate.unwrap<CameraUpdate>() ?: return
|
||||
val map = this.map
|
||||
if (map != null) {
|
||||
map.moveCamera(update)
|
||||
} else {
|
||||
waitingCameraUpdates.add(update)
|
||||
}
|
||||
}
|
||||
|
||||
override fun animateCamera(cameraUpdate: IObjectWrapper?) =
|
||||
cameraUpdate.unwrap<CameraUpdate>()?.let { map?.animateCamera(it) } ?: Unit
|
||||
override fun animateCamera(cameraUpdate: IObjectWrapper?) {
|
||||
val update = cameraUpdate.unwrap<CameraUpdate>() ?: return
|
||||
val map = this.map
|
||||
if (map != null) {
|
||||
map.animateCamera(update)
|
||||
} else {
|
||||
waitingCameraUpdates.add(update)
|
||||
}
|
||||
}
|
||||
|
||||
override fun animateCameraWithCallback(cameraUpdate: IObjectWrapper?, callback: ICancelableCallback?) =
|
||||
cameraUpdate.unwrap<CameraUpdate>()?.let { map?.animateCamera(it, callback?.toMapbox()) }
|
||||
?: Unit
|
||||
override fun animateCameraWithCallback(cameraUpdate: IObjectWrapper?, callback: ICancelableCallback?) {
|
||||
val update = cameraUpdate.unwrap<CameraUpdate>() ?: return
|
||||
val map = this.map
|
||||
if (map != null) {
|
||||
map.animateCamera(update, callback?.toMapbox())
|
||||
} else {
|
||||
waitingCameraUpdates.add(update)
|
||||
callback?.onFinish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun animateCameraWithDurationAndCallback(cameraUpdate: IObjectWrapper?, duration: Int, callback: ICancelableCallback?) =
|
||||
cameraUpdate.unwrap<CameraUpdate>()?.let { map?.animateCamera(it, duration, callback?.toMapbox()) }
|
||||
?: Unit
|
||||
override fun animateCameraWithDurationAndCallback(cameraUpdate: IObjectWrapper?, duration: Int, callback: ICancelableCallback?) {
|
||||
val update = cameraUpdate.unwrap<CameraUpdate>() ?: return
|
||||
val map = this.map
|
||||
if (map != null) {
|
||||
map.animateCamera(update, duration, callback?.toMapbox())
|
||||
} else {
|
||||
waitingCameraUpdates.add(update)
|
||||
callback?.onFinish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun stopAnimation() = map?.cancelTransitions() ?: Unit
|
||||
|
||||
override fun setMinZoomPreference(minZoom: Float) {
|
||||
map?.setMinZoomPreference(minZoom.toDouble() - 1)
|
||||
}
|
||||
|
||||
override fun setMaxZoomPreference(maxZoom: Float) {
|
||||
map?.setMaxZoomPreference(maxZoom.toDouble() - 1)
|
||||
}
|
||||
|
||||
override fun resetMinMaxZoomPreference() {
|
||||
map?.setMinZoomPreference(MapboxConstants.MINIMUM_ZOOM.toDouble())
|
||||
map?.setMaxZoomPreference(MapboxConstants.MAXIMUM_ZOOM.toDouble())
|
||||
}
|
||||
|
||||
override fun setLatLngBoundsForCameraTarget(bounds: LatLngBounds?) {
|
||||
map?.setLatLngBoundsForCameraTarget(bounds?.toMapbox())
|
||||
}
|
||||
|
||||
override fun addPolyline(options: PolylineOptions): IPolylineDelegate? {
|
||||
val lineOptions = LineOptions()
|
||||
.withLatLngs(options.points.map { it.toMapbox() })
|
||||
@ -131,26 +217,23 @@ class GoogleMapImpl(private val context: Context, private val options: GoogleMap
|
||||
|
||||
|
||||
override fun addPolygon(options: PolygonOptions): IPolygonDelegate? {
|
||||
Log.d(TAG, "unimplemented Method: addPolygon")
|
||||
return null
|
||||
val fillOptions = FillOptions()
|
||||
.withLatLngs(listOf(options.points.map { it.toMapbox() }))
|
||||
.withFillColor(ColorUtils.colorToRgbaString(options.fillColor))
|
||||
.withFillOpacity(if (options.isVisible) 1f else 0f)
|
||||
return fillManager?.let { PolygonImpl(this, it.create(fillOptions)) }
|
||||
}
|
||||
|
||||
override fun addMarker(options: MarkerOptions): IMarkerDelegate? {
|
||||
var intBits = java.lang.Float.floatToIntBits(options.zIndex)
|
||||
if (intBits < 0) intBits = intBits xor 0x7fffffff
|
||||
|
||||
val symbolOptions = SymbolOptions()
|
||||
.withIconOpacity(if (options.isVisible) options.alpha else 0f)
|
||||
.withIconRotate(options.rotation)
|
||||
.withZIndex(intBits)
|
||||
.withDraggable(options.isDraggable)
|
||||
|
||||
options.position?.let { symbolOptions.withLatLng(it.toMapbox()) }
|
||||
options.icon?.remoteObject.unwrap<BitmapDescriptorImpl>()?.applyTo(symbolOptions, floatArrayOf(options.anchorU, options.anchorV), dpiFactor)
|
||||
|
||||
val symbol = symbolManager?.create(symbolOptions) ?: return null
|
||||
val marker = MarkerImpl(this, symbol, floatArrayOf(options.anchorU, options.anchorV), options.icon?.remoteObject.unwrap<BitmapDescriptorImpl>(), options.alpha, options.title, options.snippet)
|
||||
markers.put(symbol.id, marker)
|
||||
val marker = MarkerImpl(this, "m${markerId++}", options)
|
||||
synchronized(this) {
|
||||
val symbolManager = symbolManager
|
||||
if (symbolManager == null) {
|
||||
pendingMarkers.add(marker)
|
||||
} else {
|
||||
marker.update(symbolManager)
|
||||
}
|
||||
}
|
||||
return marker
|
||||
}
|
||||
|
||||
@ -165,16 +248,16 @@ class GoogleMapImpl(private val context: Context, private val options: GoogleMap
|
||||
}
|
||||
|
||||
override fun addCircle(options: CircleOptions): ICircleDelegate? {
|
||||
val circleOptions = com.mapbox.mapboxsdk.plugins.annotation.CircleOptions()
|
||||
.withLatLng(options.center.toMapbox())
|
||||
.withCircleColor(ColorUtils.colorToRgbaString(options.fillColor))
|
||||
.withCircleRadius(options.radius.toFloat())
|
||||
.withCircleStrokeColor(ColorUtils.colorToRgbaString(options.strokeColor))
|
||||
.withCircleStrokeWidth(options.strokeWidth / dpiFactor)
|
||||
.withCircleOpacity(if (options.isVisible) 1f else 0f)
|
||||
.withCircleStrokeOpacity(if (options.isVisible) 1f else 0f)
|
||||
|
||||
return circleManager?.let { CircleImpl(this, it.create(circleOptions)) }
|
||||
val circle = CircleImpl(this, "c${circleId++}", options)
|
||||
synchronized(this) {
|
||||
val circleManager = circleManager
|
||||
if (circleManager == null) {
|
||||
pendingCircles.add(circle)
|
||||
} else {
|
||||
circle.update(circleManager)
|
||||
}
|
||||
}
|
||||
return circle
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
@ -208,20 +291,27 @@ class GoogleMapImpl(private val context: Context, private val options: GoogleMap
|
||||
val fills = fillManager?.annotations?.values()
|
||||
val symbols = symbolManager?.annotations?.values()
|
||||
val update: (Style) -> Unit = {
|
||||
circles?.let { circleManager?.update(it) }
|
||||
lines?.let { lineManager?.update(it) }
|
||||
fills?.let { fillManager?.update(it) }
|
||||
symbols?.let { symbolManager?.update(it) }
|
||||
circles?.let { runCatching { circleManager?.update(it) } }
|
||||
lines?.let { runCatching { lineManager?.update(it) } }
|
||||
fills?.let { runCatching { fillManager?.update(it) } }
|
||||
symbols?.let { runCatching { symbolManager?.update(it) } }
|
||||
}
|
||||
|
||||
// TODO: Serve map styles locally
|
||||
when (storedMapType) {
|
||||
MAP_TYPE_NORMAL -> map?.setStyle(Style.Builder().fromUrl("mapbox://styles/microg/cjui4020201oo1fmca7yuwbor"), update)
|
||||
MAP_TYPE_SATELLITE -> map?.setStyle(Style.SATELLITE, update)
|
||||
MAP_TYPE_SATELLITE -> map?.setStyle(Style.Builder().fromUrl("mapbox://styles/microg/cjxgloted25ap1ct4uex7m6hi"), update)
|
||||
MAP_TYPE_TERRAIN -> map?.setStyle(Style.OUTDOORS, update)
|
||||
MAP_TYPE_HYBRID -> map?.setStyle(Style.SATELLITE_STREETS, update)
|
||||
else -> map?.setStyle(Style.LIGHT, update)
|
||||
MAP_TYPE_HYBRID -> map?.setStyle(Style.Builder().fromUrl("mapbox://styles/microg/cjxgloted25ap1ct4uex7m6hi"), update)
|
||||
//MAP_TYPE_NONE, MAP_TYPE_NORMAL,
|
||||
else -> map?.setStyle(Style.Builder().fromUrl("mapbox://styles/microg/cjui4020201oo1fmca7yuwbor"), update)
|
||||
}
|
||||
|
||||
map?.let { BitmapDescriptorFactoryImpl.registerMap(it) }
|
||||
|
||||
}
|
||||
|
||||
override fun setWatermarkEnabled(watermark: Boolean) {
|
||||
map?.uiSettings?.isLogoEnabled = watermark
|
||||
}
|
||||
|
||||
override fun isTrafficEnabled(): Boolean {
|
||||
@ -261,7 +351,10 @@ class GoogleMapImpl(private val context: Context, private val options: GoogleMap
|
||||
|
||||
override fun setLocationSource(locationSource: ILocationSourceDelegate) {
|
||||
Log.d(TAG, "unimplemented Method: setLocationSource")
|
||||
}
|
||||
|
||||
override fun setContentDescription(desc: String?) {
|
||||
mapView?.contentDescription = desc
|
||||
}
|
||||
|
||||
override fun getUiSettings(): IUiSettingsDelegate? = map?.uiSettings?.let { UiSettingsImpl(it) }
|
||||
@ -360,80 +453,159 @@ class GoogleMapImpl(private val context: Context, private val options: GoogleMap
|
||||
cameraIdleListener = listener
|
||||
}
|
||||
|
||||
fun onCreate(savedInstanceState: Bundle?) {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
if (!created) {
|
||||
mapView?.onCreate(savedInstanceState?.toMapbox())
|
||||
mapView?.getMapAsync(this::initMap)
|
||||
created = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasSymbolAt(latlng: com.mapbox.mapboxsdk.geometry.LatLng): Boolean {
|
||||
val point = map?.projection?.toScreenLocation(latlng) ?: return false
|
||||
val features = map?.queryRenderedFeatures(point, SymbolManager.ID_GEOJSON_LAYER)
|
||||
?: return false
|
||||
return !features.isEmpty()
|
||||
return features.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun initMap(map: MapboxMap) {
|
||||
if (this.map != null) return
|
||||
this.map = map
|
||||
|
||||
applyMapType()
|
||||
map.getStyle {
|
||||
mapView?.let { view ->
|
||||
BitmapDescriptorFactoryImpl.registerMap(map)
|
||||
circleManager = CircleManager(view, map, it)
|
||||
lineManager = LineManager(view, map, it)
|
||||
lineManager?.lineCap = LINE_CAP_ROUND
|
||||
fillManager = FillManager(view, map, it)
|
||||
symbolManager = SymbolManager(view, map, it)
|
||||
symbolManager?.iconAllowOverlap = true
|
||||
symbolManager?.addClickListener { markers[it.id]?.let { markerClickListener?.onMarkerClick(it) } }
|
||||
symbolManager?.addDragListener(object : OnSymbolDragListener {
|
||||
override fun onAnnotationDragStarted(annotation: Symbol?) {
|
||||
markers[annotation?.id]?.let { markerDragListener?.onMarkerDragStart(it) }
|
||||
map.addOnCameraIdleListener {
|
||||
try {
|
||||
cameraChangeListener?.onCameraChange(map.cameraPosition.toGms())
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
|
||||
override fun onAnnotationDrag(annotation: Symbol?) {
|
||||
markers[annotation?.id]?.let { markerDragListener?.onMarkerDrag(it) }
|
||||
}
|
||||
|
||||
override fun onAnnotationDragFinished(annotation: Symbol?) {
|
||||
markers[annotation?.id]?.let { markerDragListener?.onMarkerDragEnd(it) }
|
||||
map.addOnCameraIdleListener {
|
||||
try {
|
||||
cameraIdleListener?.onCameraIdle()
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
|
||||
})
|
||||
map.addOnCameraIdleListener { cameraChangeListener?.onCameraChange(map.cameraPosition.toGms()) }
|
||||
map.addOnCameraIdleListener { cameraIdleListener?.onCameraIdle() }
|
||||
map.addOnCameraMoveListener { cameraMoveListener?.onCameraMove() }
|
||||
map.addOnCameraMoveStartedListener { cameraMoveStartedListener?.onCameraMoveStarted(it) }
|
||||
map.addOnCameraMoveCancelListener { cameraMoveCanceledListener?.onCameraMoveCanceled() }
|
||||
map.addOnMapClickListener {
|
||||
val latlng = it
|
||||
}
|
||||
map.addOnCameraMoveListener {
|
||||
try {
|
||||
cameraMoveListener?.onCameraMove()
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
}
|
||||
map.addOnCameraMoveStartedListener {
|
||||
try {
|
||||
cameraMoveStartedListener?.onCameraMoveStarted(it)
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
}
|
||||
map.addOnCameraMoveCancelListener {
|
||||
try {
|
||||
cameraMoveCanceledListener?.onCameraMoveCanceled()
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
}
|
||||
map.addOnMapClickListener { latlng ->
|
||||
try {
|
||||
mapClickListener?.let { if (!hasSymbolAt(latlng)) it.onMapClick(latlng.toGms()); }
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
false
|
||||
}
|
||||
map.addOnMapLongClickListener {
|
||||
val latlng = it
|
||||
map.addOnMapLongClickListener { latlng ->
|
||||
try {
|
||||
mapLongClickListener?.let { if (!hasSymbolAt(latlng)) it.onMapLongClick(latlng.toGms()); }
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
applyMapType()
|
||||
options.minZoomPreference?.let { if (it != 0f) map.setMinZoomPreference(it.toDouble()) }
|
||||
options.maxZoomPreference?.let { if (it != 0f) map.setMaxZoomPreference(it.toDouble()) }
|
||||
options.latLngBoundsForCameraTarget?.let { map.setLatLngBoundsForCameraTarget(it.toMapbox()) }
|
||||
options.compassEnabled?.let { map.uiSettings.isCompassEnabled = it }
|
||||
options.rotateGesturesEnabled?.let { map.uiSettings.isRotateGesturesEnabled = it }
|
||||
options.scrollGesturesEnabled?.let { map.uiSettings.isScrollGesturesEnabled = it }
|
||||
options.tiltGesturesEnabled?.let { map.uiSettings.isTiltGesturesEnabled = it }
|
||||
options.camera?.let { map.cameraPosition = it.toMapbox() }
|
||||
waitingCameraUpdates.forEach { map.moveCamera(it) }
|
||||
|
||||
synchronized(mapLock) {
|
||||
Log.d(TAG, "Invoking ${initializedCallbackList.size} callbacks delayed, as map is initialized")
|
||||
for (callback in initializedCallbackList) {
|
||||
try {
|
||||
callback.onMapReady(this)
|
||||
} catch (e: RemoteException) {
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
}
|
||||
initialized = true
|
||||
}
|
||||
|
||||
map.getStyle {
|
||||
mapView?.let { view ->
|
||||
circleManager = CircleManager(view, map, it)
|
||||
lineManager = LineManager(view, map, it)
|
||||
fillManager = FillManager(view, map, it)
|
||||
lineManager?.lineCap = LINE_CAP_ROUND
|
||||
synchronized(this) {
|
||||
val symbolManager = SymbolManager(view, map, it)
|
||||
pendingMarkers.forEach { it.update(symbolManager) }
|
||||
pendingMarkers.clear()
|
||||
this.symbolManager = symbolManager
|
||||
}
|
||||
symbolManager?.iconAllowOverlap = true
|
||||
symbolManager?.addClickListener {
|
||||
try {
|
||||
markers[it.id]?.let { markerClickListener?.onMarkerClick(it) }
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
}
|
||||
symbolManager?.addDragListener(object : OnSymbolDragListener {
|
||||
override fun onAnnotationDragStarted(annotation: Symbol?) {
|
||||
try {
|
||||
markers[annotation?.id]?.let { markerDragListener?.onMarkerDragStart(it) }
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAnnotationDrag(annotation: Symbol?) {
|
||||
try {
|
||||
markers[annotation?.id]?.let { markerDragListener?.onMarkerDrag(it) }
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAnnotationDragFinished(annotation: Symbol?) {
|
||||
try {
|
||||
markers[annotation?.id]?.let { markerDragListener?.onMarkerDragEnd(it) }
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onResume() = mapView?.onResume()
|
||||
fun onPause() = mapView?.onPause()
|
||||
fun onDestroy() {
|
||||
override fun useViewLifecycleWhenInFragment(): Boolean {
|
||||
Log.d(TAG, "unimplemented Method: useViewLifecycleWhenInFragment")
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onResume() = mapView?.onResume() ?: Unit
|
||||
override fun onPause() = mapView?.onPause() ?: Unit
|
||||
override fun onDestroy() {
|
||||
circleManager?.onDestroy()
|
||||
circleManager = null
|
||||
lineManager?.onDestroy()
|
||||
@ -442,6 +614,8 @@ class GoogleMapImpl(private val context: Context, private val options: GoogleMap
|
||||
fillManager = null
|
||||
symbolManager?.onDestroy()
|
||||
symbolManager = null
|
||||
pendingMarkers.clear()
|
||||
markers.clear()
|
||||
BitmapDescriptorFactoryImpl.unregisterMap(map)
|
||||
view.removeView(mapView)
|
||||
// TODO can crash?
|
||||
@ -449,8 +623,24 @@ class GoogleMapImpl(private val context: Context, private val options: GoogleMap
|
||||
mapView = null
|
||||
}
|
||||
|
||||
fun onLowMemory() = mapView?.onLowMemory()
|
||||
fun onSaveInstanceState(outState: Bundle) {
|
||||
override fun onStart() {
|
||||
Log.d(TAG, "unimplemented Method: onStart")
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
Log.d(TAG, "unimplemented Method: onStop")
|
||||
}
|
||||
|
||||
override fun onEnterAmbient(bundle: Bundle?) {
|
||||
Log.d(TAG, "unimplemented Method: onEnterAmbient")
|
||||
}
|
||||
|
||||
override fun onExitAmbient() {
|
||||
Log.d(TAG, "unimplemented Method: onExitAmbient")
|
||||
}
|
||||
|
||||
override fun onLowMemory() = mapView?.onLowMemory() ?: Unit
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
val newBundle = Bundle()
|
||||
mapView?.onSaveInstanceState(newBundle)
|
||||
outState.putAll(newBundle.toGms())
|
||||
@ -459,8 +649,14 @@ class GoogleMapImpl(private val context: Context, private val options: GoogleMap
|
||||
fun getMapAsync(callback: IOnMapReadyCallback) {
|
||||
synchronized(mapLock) {
|
||||
if (initialized) {
|
||||
Log.d(TAG, "Invoking callback instantly, as map is initialized")
|
||||
try {
|
||||
callback.onMapReady(this)
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "Delay callback invocation, as map is not yet initialized")
|
||||
initializedCallbackList.add(callback)
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,9 @@ package org.microg.gms.maps.mapbox
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.os.Parcel
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.android.gms.dynamic.IObjectWrapper
|
||||
import com.google.android.gms.dynamic.ObjectWrapper
|
||||
@ -34,32 +36,42 @@ class MapFragmentImpl(private val activity: Activity) : IMapFragmentDelegate.Stu
|
||||
private var options: GoogleMapOptions? = null
|
||||
|
||||
override fun onInflate(activity: IObjectWrapper, options: GoogleMapOptions, savedInstanceState: Bundle) {
|
||||
Log.d(TAG, "onInflate: ${options.camera.target}")
|
||||
this.options = options
|
||||
map?.options = options
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle) {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
if (options == null) {
|
||||
options = savedInstanceState.getParcelable("MapOptions")
|
||||
options = savedInstanceState?.getParcelable("MapOptions")
|
||||
}
|
||||
if (options == null) {
|
||||
options = GoogleMapOptions()
|
||||
}
|
||||
Log.d(TAG, "onCreate: ${options?.camera?.target}")
|
||||
map = GoogleMapImpl(activity, options ?: GoogleMapOptions())
|
||||
}
|
||||
|
||||
override fun onCreateView(layoutInflater: IObjectWrapper, container: IObjectWrapper, savedInstanceState: Bundle?): IObjectWrapper {
|
||||
if (options == null) {
|
||||
options = savedInstanceState?.getParcelable("MapOptions")
|
||||
}
|
||||
Log.d(TAG, "onCreateView: ${options?.camera?.target}")
|
||||
if (map == null) {
|
||||
map = GoogleMapImpl(activity, options ?: GoogleMapOptions())
|
||||
map!!.onCreate(savedInstanceState)
|
||||
return ObjectWrapper.wrap(map!!.view)
|
||||
} else {
|
||||
val view = map!!.view
|
||||
val parent = view.parent as ViewGroup
|
||||
parent.removeView(view)
|
||||
return ObjectWrapper.wrap(view)
|
||||
}
|
||||
map!!.onCreate(savedInstanceState)
|
||||
val view = map!!.view
|
||||
val parent = view.parent as ViewGroup?
|
||||
parent?.removeView(view)
|
||||
return ObjectWrapper.wrap(view)
|
||||
}
|
||||
|
||||
override fun getMap(): IGoogleMapDelegate? = map
|
||||
override fun onEnterAmbient(bundle: Bundle?) = map?.onEnterAmbient(bundle) ?: Unit
|
||||
override fun onExitAmbient() = map?.onExitAmbient() ?: Unit
|
||||
override fun onStart() = map?.onStart() ?: Unit
|
||||
override fun onStop() = map?.onStop() ?: Unit
|
||||
override fun onResume() = map?.onResume() ?: Unit
|
||||
override fun onPause() = map?.onPause() ?: Unit
|
||||
override fun onLowMemory() = map?.onLowMemory() ?: Unit
|
||||
@ -84,11 +96,13 @@ class MapFragmentImpl(private val activity: Activity) : IMapFragmentDelegate.Stu
|
||||
map?.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onTransact(code: Int, data: Parcel?, reply: Parcel?, flags: Int): Boolean =
|
||||
override fun onTransact(code: Int, data: Parcel?, reply: Parcel?, flags: Int): Boolean {
|
||||
if (super.onTransact(code, data, reply, flags)) {
|
||||
true
|
||||
return true
|
||||
} else {
|
||||
Log.d(TAG, "onTransact [unknown]: $code, $data, $flags"); false
|
||||
Log.d(TAG, "onTransact [unknown]: $code, $data, $flags")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -28,25 +28,28 @@ import com.google.android.gms.maps.internal.IMapViewDelegate
|
||||
import com.google.android.gms.maps.internal.IOnMapReadyCallback
|
||||
|
||||
class MapViewImpl(private val context: Context, options: GoogleMapOptions?) : IMapViewDelegate.Stub() {
|
||||
private val options: GoogleMapOptions
|
||||
|
||||
private val options: GoogleMapOptions = options ?: GoogleMapOptions()
|
||||
private var map: GoogleMapImpl? = null
|
||||
|
||||
init {
|
||||
this.options = options ?: GoogleMapOptions()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Log.d(TAG, "onCreate: ${options?.camera?.target}")
|
||||
map = GoogleMapImpl(context, options)
|
||||
map?.onCreate(savedInstanceState)
|
||||
map!!.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun getMap(): IGoogleMapDelegate? = map
|
||||
override fun onEnterAmbient(bundle: Bundle?) = map?.onEnterAmbient(bundle) ?: Unit
|
||||
override fun onExitAmbient() = map?.onExitAmbient() ?: Unit
|
||||
override fun onStart() = map?.onStart() ?: Unit
|
||||
override fun onStop() = map?.onStop() ?: Unit
|
||||
override fun onResume() = map?.onResume() ?: Unit
|
||||
override fun onPause() = map?.onPause() ?: Unit
|
||||
override fun onDestroy() {
|
||||
map?.onDestroy()
|
||||
map = null
|
||||
}
|
||||
|
||||
override fun onLowMemory() = map?.onLowMemory() ?: Unit
|
||||
override fun onSaveInstanceState(outState: Bundle) = map?.onSaveInstanceState(outState) ?: Unit
|
||||
override fun getView(): IObjectWrapper = ObjectWrapper.wrap(map?.view)
|
||||
|
@ -30,16 +30,21 @@ import org.microg.gms.maps.mapbox.utils.toGms
|
||||
import org.microg.gms.maps.mapbox.utils.toMapbox
|
||||
|
||||
class ProjectionImpl(private val projection: Projection) : IProjectionDelegate.Stub() {
|
||||
private val visibleRegion = projection.visibleRegion
|
||||
private val farLeft = projection.toScreenLocation(visibleRegion.farLeft)
|
||||
private val farRight = projection.toScreenLocation(visibleRegion.farRight)
|
||||
private val nearLeft = projection.toScreenLocation(visibleRegion.nearLeft)
|
||||
private val nearRight = projection.toScreenLocation(visibleRegion.nearRight)
|
||||
|
||||
override fun fromScreenLocation(obj: IObjectWrapper?): LatLng? =
|
||||
obj.unwrap<Point>()?.let { projection.fromScreenLocation(PointF(it)) }?.toGms()
|
||||
|
||||
override fun toScreenLocation(latLng: LatLng?): IObjectWrapper =
|
||||
override fun toScreenLocation(latLng: LatLng?): IObjectWrapper = try {
|
||||
ObjectWrapper.wrap(latLng?.toMapbox()?.let { projection.toScreenLocation(it) }?.let { Point(it.x.toInt(), it.y.toInt()) })
|
||||
|
||||
override fun getVisibleRegion(): VisibleRegion = try {
|
||||
projection.visibleRegion.toGms()
|
||||
} catch (e: Exception) {
|
||||
VisibleRegion(LatLngBounds(LatLng(0.0, 0.0), LatLng(0.0, 0.0)))
|
||||
ObjectWrapper.wrap(Point(0, 0))
|
||||
}
|
||||
|
||||
override fun getVisibleRegion(): VisibleRegion = visibleRegion.toGms()
|
||||
|
||||
}
|
@ -78,6 +78,33 @@ class UiSettingsImpl(private val uiSettings: UiSettings) : IUiSettingsDelegate.S
|
||||
|
||||
override fun isRotateGesturesEnabled(): Boolean = uiSettings.isRotateGesturesEnabled
|
||||
|
||||
override fun setIndoorLevelPickerEnabled(indoorLevelPicker: Boolean) {
|
||||
Log.d(TAG, "unimplemented Method: setIndoorLevelPickerEnabled")
|
||||
}
|
||||
|
||||
override fun isIndoorLevelPickerEnabled(): Boolean {
|
||||
Log.d(TAG, "unimplemented Method: isIndoorLevelPickerEnabled")
|
||||
return false
|
||||
}
|
||||
|
||||
override fun setMapToolbarEnabled(mapToolbar: Boolean) {
|
||||
Log.d(TAG, "unimplemented Method: setMapToolbarEnabled")
|
||||
}
|
||||
|
||||
override fun isMapToolbarEnabled(): Boolean {
|
||||
Log.d(TAG, "unimplemented Method: isMapToolbarEnabled")
|
||||
return false
|
||||
}
|
||||
|
||||
override fun setScrollGesturesEnabledDuringRotateOrZoom(scrollDuringZoom: Boolean) {
|
||||
Log.d(TAG, "unimplemented Method: setScrollGesturesEnabledDuringRotateOrZoom")
|
||||
}
|
||||
|
||||
override fun isScrollGesturesEnabledDuringRotateOrZoom(): Boolean {
|
||||
Log.d(TAG, "unimplemented Method: isScrollGesturesEnabledDuringRotateOrZoom")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onTransact(code: Int, data: Parcel?, reply: Parcel?, flags: Int): Boolean =
|
||||
if (super.onTransact(code, data, reply, flags)) {
|
||||
true
|
||||
|
@ -37,11 +37,14 @@ object BitmapDescriptorFactoryImpl : IBitmapDescriptorFactoryDelegate.Stub() {
|
||||
}
|
||||
|
||||
fun registerMap(map: MapboxMap) {
|
||||
Log.d(TAG, "registerMap")
|
||||
map.getStyle {
|
||||
synchronized(bitmaps) {
|
||||
it.addImages(bitmaps)
|
||||
maps.add(map)
|
||||
}
|
||||
}
|
||||
maps.add(map)
|
||||
}
|
||||
|
||||
fun unregisterMap(map: MapboxMap?) {
|
||||
maps.remove(map)
|
||||
@ -53,9 +56,12 @@ object BitmapDescriptorFactoryImpl : IBitmapDescriptorFactoryDelegate.Stub() {
|
||||
?: floatArrayOf(0f, 0f)
|
||||
|
||||
private fun registerBitmap(id: String, bitmapCreator: () -> Bitmap?) {
|
||||
val bitmap = synchronized(bitmaps) {
|
||||
if (bitmaps.contains(id)) return
|
||||
val bitmap = bitmapCreator() ?: return
|
||||
bitmaps[id] = bitmap
|
||||
bitmap
|
||||
}
|
||||
for (map in maps) {
|
||||
map.getStyle { it.addImage(id, bitmap) }
|
||||
}
|
||||
|
@ -21,51 +21,78 @@ import android.util.Log
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
import com.google.android.gms.maps.model.internal.ICircleDelegate
|
||||
import com.mapbox.mapboxsdk.plugins.annotation.Circle
|
||||
import com.mapbox.mapboxsdk.plugins.annotation.CircleOptions
|
||||
import com.mapbox.mapboxsdk.utils.ColorUtils
|
||||
import org.microg.gms.maps.mapbox.GoogleMapImpl
|
||||
import org.microg.gms.maps.mapbox.utils.toGms
|
||||
import org.microg.gms.maps.mapbox.utils.toMapbox
|
||||
import com.google.android.gms.maps.model.CircleOptions as GmsCircleOptions
|
||||
|
||||
class CircleImpl(private val map: GoogleMapImpl, private val id: String, options: GmsCircleOptions) : ICircleDelegate.Stub(), Markup<Circle, CircleOptions> {
|
||||
private var center: LatLng = options.center
|
||||
private var radius: Double = options.radius
|
||||
private var strokeWidth: Float = options.strokeWidth
|
||||
private var strokeColor: Int = options.strokeColor
|
||||
private var fillColor: Int = options.fillColor
|
||||
private var visible: Boolean = options.isVisible
|
||||
|
||||
override var annotation: Circle? = null
|
||||
override var removed: Boolean = false
|
||||
override val annotationOptions: CircleOptions
|
||||
get() = CircleOptions()
|
||||
.withLatLng(center.toMapbox())
|
||||
.withCircleColor(ColorUtils.colorToRgbaString(fillColor))
|
||||
.withCircleRadius(radius.toFloat())
|
||||
.withCircleStrokeColor(ColorUtils.colorToRgbaString(strokeColor))
|
||||
.withCircleStrokeWidth(strokeWidth / map.dpiFactor)
|
||||
.withCircleOpacity(if (visible) 1f else 0f)
|
||||
.withCircleStrokeOpacity(if (visible) 1f else 0f)
|
||||
|
||||
class CircleImpl(private val map: GoogleMapImpl, private val circle: Circle) : ICircleDelegate.Stub() {
|
||||
override fun remove() {
|
||||
map.circleManager?.delete(circle)
|
||||
removed = true
|
||||
map.circleManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun getId(): String = "c" + circle.id.toString()
|
||||
override fun getId(): String = id
|
||||
|
||||
override fun setCenter(center: LatLng) {
|
||||
circle.latLng = center.toMapbox()
|
||||
map.circleManager?.update(circle)
|
||||
this.center = center
|
||||
annotation?.latLng = center.toMapbox()
|
||||
map.circleManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun getCenter(): LatLng = circle.latLng.toGms()
|
||||
override fun getCenter(): LatLng = center
|
||||
|
||||
override fun setRadius(radius: Double) {
|
||||
circle.circleRadius = radius.toFloat()
|
||||
map.circleManager?.update(circle)
|
||||
this.radius = radius
|
||||
annotation?.circleRadius = radius.toFloat()
|
||||
map.circleManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun getRadius(): Double = circle.circleRadius.toDouble()
|
||||
override fun getRadius(): Double = radius
|
||||
|
||||
override fun setStrokeWidth(width: Float) {
|
||||
circle.circleStrokeWidth = width / map.dpiFactor
|
||||
map.circleManager?.update(circle)
|
||||
this.strokeWidth = width
|
||||
annotation?.circleStrokeWidth = width / map.dpiFactor
|
||||
map.circleManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun getStrokeWidth(): Float = circle.circleStrokeWidth * map.dpiFactor
|
||||
override fun getStrokeWidth(): Float = strokeWidth
|
||||
|
||||
override fun setStrokeColor(color: Int) {
|
||||
circle.setCircleStrokeColor(color)
|
||||
map.circleManager?.update(circle)
|
||||
this.strokeColor = color
|
||||
annotation?.setCircleStrokeColor(color)
|
||||
map.circleManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun getStrokeColor(): Int = circle.circleStrokeColorAsInt
|
||||
override fun getStrokeColor(): Int = strokeColor
|
||||
|
||||
override fun setFillColor(color: Int) {
|
||||
circle.setCircleColor(color)
|
||||
map.circleManager?.update(circle)
|
||||
this.fillColor = color
|
||||
annotation?.setCircleColor(color)
|
||||
map.circleManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun getFillColor(): Int = circle.circleColorAsInt
|
||||
override fun getFillColor(): Int = fillColor
|
||||
|
||||
override fun setZIndex(zIndex: Float) {
|
||||
Log.d(TAG, "unimplemented Method: setZIndex")
|
||||
@ -77,12 +104,13 @@ class CircleImpl(private val map: GoogleMapImpl, private val circle: Circle) : I
|
||||
}
|
||||
|
||||
override fun setVisible(visible: Boolean) {
|
||||
circle.circleOpacity = if (visible) 1f else 0f
|
||||
circle.circleStrokeOpacity = if (visible) 1f else 0f
|
||||
map.circleManager?.update(circle)
|
||||
this.visible = visible
|
||||
annotation?.circleOpacity = if (visible) 1f else 0f
|
||||
annotation?.circleStrokeOpacity = if (visible) 1f else 0f
|
||||
map.circleManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun isVisible(): Boolean = circle.circleOpacity != 0f || circle.circleStrokeOpacity != 0f
|
||||
override fun isVisible(): Boolean = visible
|
||||
|
||||
override fun equalsRemote(other: ICircleDelegate?): Boolean = equals(other)
|
||||
|
||||
@ -90,7 +118,7 @@ class CircleImpl(private val map: GoogleMapImpl, private val circle: Circle) : I
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other is CircleImpl) {
|
||||
return other.circle == circle
|
||||
return other.id == id
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -19,35 +19,74 @@ package org.microg.gms.maps.mapbox.model
|
||||
import android.util.Log
|
||||
import com.google.android.gms.dynamic.IObjectWrapper
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
import com.google.android.gms.maps.model.MarkerOptions
|
||||
import com.google.android.gms.maps.model.internal.IMarkerDelegate
|
||||
import com.mapbox.mapboxsdk.plugins.annotation.AnnotationManager
|
||||
import com.mapbox.mapboxsdk.plugins.annotation.Symbol
|
||||
import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions
|
||||
import org.microg.gms.kotlin.unwrap
|
||||
import org.microg.gms.maps.mapbox.GoogleMapImpl
|
||||
import org.microg.gms.maps.mapbox.utils.toGms
|
||||
import org.microg.gms.maps.mapbox.utils.toMapbox
|
||||
|
||||
class MarkerImpl(private val map: GoogleMapImpl,
|
||||
private val symbol: Symbol,
|
||||
private var anchor: FloatArray,
|
||||
private var icon: BitmapDescriptorImpl?,
|
||||
private var alpha: Float = symbol.iconOpacity,
|
||||
private var title: String? = null,
|
||||
private var snippet: String? = null) : IMarkerDelegate.Stub() {
|
||||
class MarkerImpl(private val map: GoogleMapImpl, private val id: String, options: MarkerOptions) : IMarkerDelegate.Stub(), Markup<Symbol, SymbolOptions> {
|
||||
private var position: LatLng = options.position
|
||||
private var visible: Boolean = options.isVisible
|
||||
private var rotation: Float = options.rotation
|
||||
private var anchor: FloatArray = floatArrayOf(options.anchorU, options.anchorV)
|
||||
private var icon: BitmapDescriptorImpl? = options.icon?.remoteObject.unwrap()
|
||||
private var alpha: Float = options.alpha
|
||||
private var title: String? = options.title
|
||||
private var snippet: String? = options.snippet
|
||||
private var zIndex: Float = options.zIndex
|
||||
private var draggable: Boolean = options.isDraggable
|
||||
private var tag: IObjectWrapper? = null
|
||||
|
||||
override var annotation: Symbol? = null
|
||||
override var removed: Boolean = false
|
||||
override val annotationOptions: SymbolOptions
|
||||
get() {
|
||||
var intBits = java.lang.Float.floatToIntBits(zIndex)
|
||||
if (intBits < 0) intBits = intBits xor 0x7fffffff
|
||||
|
||||
val symbolOptions = SymbolOptions()
|
||||
.withIconOpacity(if (visible) alpha else 0f)
|
||||
.withIconRotate(rotation)
|
||||
.withZIndex(intBits)
|
||||
.withDraggable(draggable)
|
||||
|
||||
position.let { symbolOptions.withLatLng(it.toMapbox()) }
|
||||
icon?.applyTo(symbolOptions, anchor, map.dpiFactor)
|
||||
return symbolOptions
|
||||
}
|
||||
|
||||
override fun remove() {
|
||||
map.symbolManager?.delete(symbol)
|
||||
map.markers.remove(symbol.id)
|
||||
removed = true
|
||||
map.symbolManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun getId(): String = "m" + symbol.id.toString()
|
||||
|
||||
override fun setPosition(pos: LatLng?) {
|
||||
pos?.let { symbol.latLng = it.toMapbox() }
|
||||
map.symbolManager?.update(symbol)
|
||||
override fun update(manager: AnnotationManager<*, Symbol, SymbolOptions, *, *, *>) {
|
||||
synchronized(this) {
|
||||
val id = annotation?.id
|
||||
if (removed && id != null) {
|
||||
map.markers.remove(id)
|
||||
}
|
||||
super.update(manager)
|
||||
val annotation = annotation
|
||||
if (annotation != null && id == null) {
|
||||
map.markers[annotation.id] = this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPosition(): LatLng = symbol.latLng.toGms()
|
||||
override fun getId(): String = id
|
||||
|
||||
override fun setPosition(position: LatLng?) {
|
||||
this.position = position ?: return
|
||||
annotation?.latLng = position.toMapbox()
|
||||
map.symbolManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun getPosition(): LatLng = position
|
||||
|
||||
override fun setTitle(title: String?) {
|
||||
this.title = title
|
||||
@ -61,12 +100,13 @@ class MarkerImpl(private val map: GoogleMapImpl,
|
||||
|
||||
override fun getSnippet(): String? = snippet
|
||||
|
||||
override fun setDraggable(drag: Boolean) {
|
||||
symbol.isDraggable = drag
|
||||
map.symbolManager?.update(symbol)
|
||||
override fun setDraggable(draggable: Boolean) {
|
||||
this.draggable = draggable
|
||||
annotation?.isDraggable = draggable
|
||||
map.symbolManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun isDraggable(): Boolean = symbol.isDraggable
|
||||
override fun isDraggable(): Boolean = draggable
|
||||
|
||||
override fun showInfoWindow() {
|
||||
Log.d(TAG, "unimplemented Method: showInfoWindow")
|
||||
@ -82,11 +122,12 @@ class MarkerImpl(private val map: GoogleMapImpl,
|
||||
}
|
||||
|
||||
override fun setVisible(visible: Boolean) {
|
||||
symbol.iconOpacity = if (visible) 0f else alpha
|
||||
map.symbolManager?.update(symbol)
|
||||
this.visible = visible
|
||||
annotation?.iconOpacity = if (visible) alpha else 0f
|
||||
map.symbolManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun isVisible(): Boolean = symbol.iconOpacity != 0f
|
||||
override fun isVisible(): Boolean = visible
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
@ -107,15 +148,17 @@ class MarkerImpl(private val map: GoogleMapImpl,
|
||||
override fun hashCodeRemote(): Int = hashCode()
|
||||
|
||||
override fun setIcon(obj: IObjectWrapper?) {
|
||||
obj.unwrap<BitmapDescriptorImpl>()?.let { icon = it }
|
||||
icon?.applyTo(symbol, anchor, map.dpiFactor)
|
||||
map.symbolManager?.update(symbol)
|
||||
obj.unwrap<BitmapDescriptorImpl>()?.let { icon ->
|
||||
this.icon = icon
|
||||
annotation?.let { icon.applyTo(it, anchor, map.dpiFactor) }
|
||||
}
|
||||
map.symbolManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun setAnchor(x: Float, y: Float) {
|
||||
anchor = floatArrayOf(x, y)
|
||||
icon?.applyTo(symbol, anchor, map.dpiFactor)
|
||||
map.symbolManager?.update(symbol)
|
||||
annotation?.let { icon?.applyTo(it, anchor, map.dpiFactor) }
|
||||
map.symbolManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun setFlat(flat: Boolean) {
|
||||
@ -128,11 +171,12 @@ class MarkerImpl(private val map: GoogleMapImpl,
|
||||
}
|
||||
|
||||
override fun setRotation(rotation: Float) {
|
||||
symbol.iconRotate = rotation
|
||||
map.symbolManager?.update(symbol)
|
||||
this.rotation = rotation
|
||||
annotation?.iconRotate = rotation
|
||||
map.symbolManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun getRotation(): Float = symbol.iconRotate
|
||||
override fun getRotation(): Float = rotation
|
||||
|
||||
override fun setInfoWindowAnchor(x: Float, y: Float) {
|
||||
Log.d(TAG, "unimplemented Method: setInfoWindowAnchor")
|
||||
@ -140,24 +184,21 @@ class MarkerImpl(private val map: GoogleMapImpl,
|
||||
|
||||
override fun setAlpha(alpha: Float) {
|
||||
this.alpha = alpha
|
||||
symbol.iconOpacity = alpha
|
||||
map.symbolManager?.update(symbol)
|
||||
annotation?.iconOpacity = if (visible) alpha else 0f
|
||||
map.symbolManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun getAlpha(): Float = alpha
|
||||
|
||||
override fun setZIndex(zIndex: Float) {
|
||||
this.zIndex = zIndex
|
||||
var intBits = java.lang.Float.floatToIntBits(zIndex)
|
||||
if (intBits < 0) intBits = intBits xor 0x7fffffff
|
||||
symbol.zIndex = intBits
|
||||
map.symbolManager?.update(symbol)
|
||||
annotation?.zIndex = intBits
|
||||
map.symbolManager?.let { update(it) }
|
||||
}
|
||||
|
||||
override fun getZIndex(): Float {
|
||||
var intBits = symbol.zIndex
|
||||
if (intBits < 0) intBits = intBits xor 0x7fffffff
|
||||
return java.lang.Float.intBitsToFloat(intBits)
|
||||
}
|
||||
override fun getZIndex(): Float = zIndex
|
||||
|
||||
override fun setTag(obj: IObjectWrapper?) {
|
||||
this.tag = obj
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2019 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.microg.gms.maps.mapbox.model
|
||||
|
||||
import com.mapbox.mapboxsdk.plugins.annotation.Annotation
|
||||
import com.mapbox.mapboxsdk.plugins.annotation.AnnotationManager
|
||||
import com.mapbox.mapboxsdk.plugins.annotation.Options
|
||||
|
||||
interface Markup<T : Annotation<*>, S : Options<T>> {
|
||||
var annotation: T?
|
||||
val annotationOptions: S
|
||||
val removed: Boolean
|
||||
|
||||
fun update(manager: AnnotationManager<*, T, S, *, *, *>) {
|
||||
synchronized(this) {
|
||||
if (removed && annotation != null) {
|
||||
manager.delete(annotation)
|
||||
annotation = null
|
||||
} else if (annotation != null) {
|
||||
manager.update(annotation)
|
||||
} else if (!removed) {
|
||||
annotation = manager.create(annotationOptions)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2019 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.microg.gms.maps.mapbox.model
|
||||
|
||||
import android.os.Parcel
|
||||
import android.util.Log
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
import com.google.android.gms.maps.model.internal.IPolygonDelegate
|
||||
import com.mapbox.mapboxsdk.plugins.annotation.Fill
|
||||
import org.microg.gms.maps.mapbox.GoogleMapImpl
|
||||
import org.microg.gms.maps.mapbox.utils.toGms
|
||||
import org.microg.gms.maps.mapbox.utils.toMapbox
|
||||
|
||||
class PolygonImpl(private val map: GoogleMapImpl, private val fill: Fill) : IPolygonDelegate.Stub() {
|
||||
override fun remove() {
|
||||
map.fillManager?.delete(fill)
|
||||
}
|
||||
|
||||
override fun getId(): String = "p" + fill.id.toString()
|
||||
|
||||
override fun setPoints(points: List<LatLng>) {
|
||||
fill.latLngs = listOf(points.map { it.toMapbox() })
|
||||
map.fillManager?.update(fill)
|
||||
}
|
||||
|
||||
override fun getPoints(): List<LatLng> = fill.latLngs[0]?.map { it.toGms() } ?: emptyList()
|
||||
|
||||
override fun setHoles(holes: List<Any?>?) {
|
||||
Log.d(TAG, "unimplemented Method: setHoles")
|
||||
}
|
||||
|
||||
override fun getHoles(): List<Any?> {
|
||||
Log.d(TAG, "unimplemented Method: getHoles")
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
override fun setStrokeWidth(width: Float) {
|
||||
Log.d(TAG, "unimplemented Method: setStrokeWidth")
|
||||
}
|
||||
|
||||
override fun getStrokeWidth(): Float {
|
||||
Log.d(TAG, "unimplemented Method: getStrokeWidth")
|
||||
return 0f
|
||||
}
|
||||
|
||||
override fun setStrokeColor(color: Int) {
|
||||
fill.setFillOutlineColor(color)
|
||||
map.fillManager?.update(fill)
|
||||
}
|
||||
|
||||
override fun getStrokeColor(): Int = fill.fillOutlineColorAsInt
|
||||
|
||||
override fun setFillColor(color: Int) {
|
||||
fill.setFillColor(color)
|
||||
map.fillManager?.update(fill)
|
||||
}
|
||||
|
||||
override fun getFillColor(): Int = fill.fillColorAsInt
|
||||
|
||||
override fun setZIndex(zIndex: Float) {
|
||||
Log.d(TAG, "unimplemented Method: setZIndex")
|
||||
}
|
||||
|
||||
override fun getZIndex(): Float {
|
||||
Log.d(TAG, "unimplemented Method: getZIndex")
|
||||
return 0f
|
||||
}
|
||||
|
||||
override fun setVisible(visible: Boolean) {
|
||||
fill.fillOpacity = if (visible) 1f else 0f
|
||||
map.fillManager?.update(fill)
|
||||
}
|
||||
|
||||
override fun isVisible(): Boolean = fill.fillOpacity != 0f
|
||||
|
||||
override fun setGeodesic(geod: Boolean) {
|
||||
Log.d(TAG, "unimplemented Method: setGeodesic")
|
||||
}
|
||||
|
||||
override fun isGeodesic(): Boolean {
|
||||
Log.d(TAG, "unimplemented Method: isGeodesic")
|
||||
return false
|
||||
}
|
||||
|
||||
override fun equalsRemote(other: IPolygonDelegate?): Boolean = equals(other)
|
||||
|
||||
override fun hashCodeRemote(): Int = hashCode()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other is PolygonImpl) {
|
||||
return other.fill == fill
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onTransact(code: Int, data: Parcel?, reply: Parcel?, flags: Int): Boolean =
|
||||
if (super.onTransact(code, data, reply, flags)) {
|
||||
true
|
||||
} else {
|
||||
Log.d(TAG, "onTransact [unknown]: $code, $data, $flags"); false
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = "GmsMapPolygon"
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ class PolylineImpl(private val map: GoogleMapImpl, private val line: Line) : IPo
|
||||
|
||||
override fun getId(): String = "l" + line.id.toString()
|
||||
|
||||
override fun setPoints(points: MutableList<LatLng>) {
|
||||
override fun setPoints(points: List<LatLng>) {
|
||||
line.latLngs = points.map { it.toMapbox() }
|
||||
map.lineManager?.update(line)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package org.microg.gms.maps.mapbox.utils
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import com.google.android.gms.maps.internal.ICancelableCallback
|
||||
import com.google.android.gms.maps.model.CircleOptions
|
||||
import com.google.android.gms.maps.model.MarkerOptions
|
||||
|
@ -57,6 +57,7 @@ import com.google.android.gms.maps.internal.IUiSettingsDelegate;
|
||||
import com.google.android.gms.maps.model.CameraPosition;
|
||||
import com.google.android.gms.maps.model.CircleOptions;
|
||||
import com.google.android.gms.maps.model.GroundOverlayOptions;
|
||||
import com.google.android.gms.maps.model.LatLngBounds;
|
||||
import com.google.android.gms.maps.model.MarkerOptions;
|
||||
import com.google.android.gms.maps.model.PolygonOptions;
|
||||
import com.google.android.gms.maps.model.PolylineOptions;
|
||||
@ -155,7 +156,7 @@ public class GoogleMapImpl extends IGoogleMapDelegate.Stub
|
||||
|
||||
private void initFromOptions() {
|
||||
try {
|
||||
uiSettings.setCompassEnabled(options.isCompassEnabled());
|
||||
uiSettings.setCompassEnabled(options.getCompassEnabled());
|
||||
uiSettings.setRotateGesturesEnabled(options.isRotateGesturesEnabled());
|
||||
uiSettings.setTiltGesturesEnabled(options.isTiltGesturesEnabled());
|
||||
uiSettings.setScrollGesturesEnabled(options.isScrollGesturesEnabled());
|
||||
@ -173,6 +174,66 @@ public class GoogleMapImpl extends IGoogleMapDelegate.Stub
|
||||
backendMap.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: onLowMemory");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useViewLifecycleWhenInFragment() throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: useViewLifecycleWhenInFragment");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: onSaveInstanceState");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentDescription(String desc) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: setContentDescription");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterAmbient(Bundle bundle) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: onEnterAmbient");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExitAmbient() throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: onExitAmbient");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMinZoomPreference(float minZoom) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: setMinZoomPreference");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxZoomPreference(float maxZoom) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: setMaxZoomPreference");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetMinMaxZoomPreference() throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: resetMinMaxZoomPreference");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLatLngBoundsForCameraTarget(LatLngBounds bounds) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: setLatLngBoundsForCameraTarget");
|
||||
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
backendMap.onResume();
|
||||
}
|
||||
@ -556,6 +617,18 @@ public class GoogleMapImpl extends IGoogleMapDelegate.Stub
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWatermarkEnabled(boolean watermark) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: setWatermarkEnabled");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: onCreate");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCameraMoveStartedListener(IOnCameraMoveStartedListener listener) throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: setCameraMoveStartedListener");
|
||||
@ -580,6 +653,18 @@ public class GoogleMapImpl extends IGoogleMapDelegate.Stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: onStart");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() throws RemoteException {
|
||||
Log.d(TAG, "unimplemented Method: onStop");
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Misc
|
||||
*/
|
||||
|
@ -125,6 +125,26 @@ public class MapFragmentImpl extends IMapFragmentDelegate.Stub {
|
||||
Log.d(TAG, "onLowMemory");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterAmbient(Bundle bundle) throws RemoteException {
|
||||
map.onEnterAmbient(bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExitAmbient() throws RemoteException {
|
||||
map.onExitAmbient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() throws RemoteException {
|
||||
map.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() throws RemoteException {
|
||||
map.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) throws RemoteException {
|
||||
Log.d(TAG, "onSaveInstanceState: " + outState);
|
||||
|
@ -122,6 +122,26 @@ public class MapViewImpl extends IMapViewDelegate.Stub {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterAmbient(Bundle bundle) throws RemoteException {
|
||||
map.onEnterAmbient(bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExitAmbient() throws RemoteException {
|
||||
map.onExitAmbient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() throws RemoteException {
|
||||
map.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() throws RemoteException {
|
||||
map.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
|
||||
if (super.onTransact(code, data, reply, flags)) return true;
|
||||
|
@ -28,6 +28,9 @@ public class UiSettingsImpl extends IUiSettingsDelegate.Stub {
|
||||
private boolean tiltGesturesEnabled = true;
|
||||
private boolean rotateGesturesEnabled = true;
|
||||
private boolean allGesturesEnabled = true;
|
||||
private boolean indoorLevelPickerEnabled = false;
|
||||
private boolean mapToolbarEnabled = false;
|
||||
private boolean scrollGesturesEnabledDuringRotateOrZoom = true;
|
||||
|
||||
private UiSettingsListener listener;
|
||||
|
||||
@ -128,6 +131,39 @@ public class UiSettingsImpl extends IUiSettingsDelegate.Stub {
|
||||
return rotateGesturesEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIndoorLevelPickerEnabled(boolean indoorLevelPicker) throws RemoteException {
|
||||
this.indoorLevelPickerEnabled = indoorLevelPicker;
|
||||
listener.onUiSettingsChanged(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIndoorLevelPickerEnabled() throws RemoteException {
|
||||
return indoorLevelPickerEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMapToolbarEnabled(boolean mapToolbar) throws RemoteException {
|
||||
this.mapToolbarEnabled = mapToolbar;
|
||||
listener.onUiSettingsChanged(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMapToolbarEnabled() throws RemoteException {
|
||||
return mapToolbarEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScrollGesturesEnabledDuringRotateOrZoom(boolean scrollDuringZoom) throws RemoteException {
|
||||
this.scrollGesturesEnabledDuringRotateOrZoom = scrollDuringZoom;
|
||||
listener.onUiSettingsChanged(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScrollGesturesEnabledDuringRotateOrZoom() throws RemoteException {
|
||||
return scrollGesturesEnabledDuringRotateOrZoom;
|
||||
}
|
||||
|
||||
public static interface UiSettingsListener {
|
||||
void onUiSettingsChanged(UiSettingsImpl settings) throws RemoteException;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user