Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7bb43c2e authored by Fynn Godau's avatar Fynn Godau
Browse files

Merge branch '910-early-callback' into epic67-maps

parents 3a38d22b 074fb360
Loading
Loading
Loading
Loading
+73 −46
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package org.microg.gms.maps.mapbox

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Point
import android.location.Location
import android.os.*
import androidx.annotation.IdRes
@@ -30,6 +31,7 @@ import android.widget.FrameLayout
import android.widget.RelativeLayout
import androidx.collection.LongSparseArray
import com.google.android.gms.dynamic.IObjectWrapper
import com.google.android.gms.dynamic.ObjectWrapper
import com.google.android.gms.maps.GoogleMapOptions
import com.google.android.gms.maps.internal.*
import com.google.android.gms.maps.model.*
@@ -53,6 +55,7 @@ import com.mapbox.mapboxsdk.style.layers.Property.LINE_CAP_ROUND
import com.google.android.gms.dynamic.unwrap
import com.mapbox.mapboxsdk.WellKnownTileServer
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
import org.microg.gms.maps.MapsConstants.*
import org.microg.gms.maps.mapbox.model.*
import org.microg.gms.maps.mapbox.utils.MapContext
@@ -86,7 +89,7 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
    private var loaded = false
    private val mapLock = Object()

    private val initializedCallbackList = mutableListOf<IOnMapReadyCallback>()
    private val initializedCallbackList = mutableListOf<OnMapReadyCallback>()
    private var loadedCallback: IOnMapLoadedCallback? = null
    private var cameraChangeListener: IOnCameraChangeListener? = null
    private var cameraMoveListener: IOnCameraMoveListener? = null
@@ -168,7 +171,9 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
        }
    }

    override fun getCameraPosition(): CameraPosition? = map?.cameraPosition?.toGms()
    override fun getCameraPosition(): CameraPosition =
        map?.cameraPosition?.toGms() ?: CameraPosition(LatLng(0.0, 0.0), 0f, 0f, 0f)

    override fun getMaxZoomLevel(): Float = (map?.maxZoomLevel?.toFloat() ?: 20f) + 1f
    override fun getMinZoomLevel(): Float = (map?.minZoomLevel?.toFloat() ?: 0f) + 1f

@@ -194,15 +199,17 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
        }
    }

    fun afterInitialized(runnable: () -> Unit) {
        initializedCallbackList.add(object : IOnMapReadyCallback {
            override fun onMapReady(map: IGoogleMapDelegate?) {
                runnable()
            }

            override fun asBinder(): IBinder? = null
    fun afterInitialize(runnable: (MapboxMap) -> Unit) {
        synchronized(mapLock) {
            if (initialized) {
                runnable(map!!)
            } else {
                initializedCallbackList.add(OnMapReadyCallback {
                    runnable(it)
                })
            }
        }
    }

    override fun animateCameraWithCallback(cameraUpdate: IObjectWrapper?, callback: ICancelableCallback?) {
        val update = cameraUpdate.unwrap<CameraUpdate>() ?: return
@@ -211,7 +218,7 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
                this.map?.animateCamera(update, callback?.toMapbox())
            } else {
                waitingCameraUpdates.add(update)
                afterInitialized { callback?.onFinish() }
                afterInitialize { callback?.onFinish() }
            }
        }
    }
@@ -223,7 +230,7 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
                this.map?.animateCamera(update, duration, callback?.toMapbox())
            } else {
                waitingCameraUpdates.add(update)
                afterInitialized { callback?.onFinish() }
                afterInitialize { callback?.onFinish() }
            }
        }
    }
@@ -235,21 +242,21 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
        return true
    }

    override fun setMinZoomPreference(minZoom: Float) {
        map?.setMinZoomPreference(minZoom.toDouble() - 1)
    override fun setMinZoomPreference(minZoom: Float) = afterInitialize {
        it.setMinZoomPreference(minZoom.toDouble() - 1)
    }

    override fun setMaxZoomPreference(maxZoom: Float) {
        map?.setMaxZoomPreference(maxZoom.toDouble() - 1)
    override fun setMaxZoomPreference(maxZoom: Float) = afterInitialize {
        it.setMaxZoomPreference(maxZoom.toDouble() - 1)
    }

    override fun resetMinMaxZoomPreference() {
        map?.setMinZoomPreference(MapboxConstants.MINIMUM_ZOOM.toDouble())
        map?.setMaxZoomPreference(MapboxConstants.MAXIMUM_ZOOM.toDouble())
    override fun resetMinMaxZoomPreference() = afterInitialize {
        it.setMinZoomPreference(MapboxConstants.MINIMUM_ZOOM.toDouble())
        it.setMaxZoomPreference(MapboxConstants.MAXIMUM_ZOOM.toDouble())
    }

    override fun setLatLngBoundsForCameraTarget(bounds: LatLngBounds?) {
        map?.setLatLngBoundsForCameraTarget(bounds?.toMapbox())
    override fun setLatLngBoundsForCameraTarget(bounds: LatLngBounds?) = afterInitialize {
        it.setLatLngBoundsForCameraTarget(bounds?.toMapbox())
    }

    override fun addPolyline(options: PolylineOptions): IPolylineDelegate? {
@@ -367,8 +374,8 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)

    }

    override fun setWatermarkEnabled(watermark: Boolean) {
        map?.uiSettings?.isLogoEnabled = watermark
    override fun setWatermarkEnabled(watermark: Boolean) = afterInitialize {
        it.uiSettings.isLogoEnabled = watermark
    }

    override fun isTrafficEnabled(): Boolean {
@@ -425,7 +432,11 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
        mapView?.contentDescription = desc
    }

    override fun getUiSettings(): IUiSettingsDelegate? = map?.uiSettings?.let { UiSettingsImpl(it) }
    override fun getUiSettings(): IUiSettingsDelegate =
        map?.uiSettings?.let { UiSettingsImpl(it) } ?: UiSettingsCache().also {
            // Apply cached UI settings after map is initialized
            initializedCallbackList.add(it.getMapReadyCallback())
        }

    override fun getProjection(): IProjectionDelegate? = map?.projection?.let {
        val experiment = try {
@@ -434,6 +445,21 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
            Log.w(TAG, e); false
        }
        ProjectionImpl(it, experiment)
    } ?: object : IProjectionDelegate.Stub() { // dummy projection if map not initialized
        override fun fromScreenLocation(obj: IObjectWrapper?): LatLng {
            Log.d(TAG, "Map not initialized when calling getProjection(). Cannot calculate fromScreenLocation")
            return LatLng(0.0, 0.0)
        }

        override fun toScreenLocation(latLng: LatLng?): IObjectWrapper {
            Log.d(TAG, "Map not initialized when calling getProjection(). Cannot calculate toScreenLocation")
            return ObjectWrapper.wrap(Point(0, 0))
        }

        override fun getVisibleRegion(): VisibleRegion {
            Log.d(TAG, "Map not initialized when calling getProjection(). Cannot calculate getVisibleRegion")
            return VisibleRegion(LatLngBounds(LatLng(0.0, 0.0), LatLng(0.0, 0.0)))
        }
    }

    override fun setOnCameraChangeListener(listener: IOnCameraChangeListener?) {
@@ -486,9 +512,8 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)

    }

    override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
    override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) = afterInitialize { map ->
        Log.d(TAG, "setPadding: $left $top $right $bottom")
        map?.let { map ->
        CameraUpdateFactory.paddingTo(left.toDouble(), top.toDouble(), right.toDouble(), bottom.toDouble())
            .let { map.moveCamera(it) }

@@ -500,7 +525,6 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
        map.uiSettings.setCompassMargins(left + fourDp, top + fourDp, right + fourDp, bottom + fourDp)
        map.uiSettings.setAttributionMargins(left + ninetyTwoDp, top + fourDp, right + fourDp, bottom + fourDp)
    }
    }

    override fun isBuildingsEnabled(): Boolean {
        Log.d(TAG, "unimplemented Method: isBuildingsEnabled")
@@ -509,7 +533,6 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)

    override fun setBuildingsEnabled(buildings: Boolean) {
        Log.d(TAG, "unimplemented Method: setBuildingsEnabled")

    }

    override fun setOnMapLoadedCallback(callback: IOnMapLoadedCallback?) {
@@ -639,11 +662,7 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
            val initializedCallbackList = ArrayList(initializedCallbackList)
            Log.d(TAG, "Invoking ${initializedCallbackList.size} callbacks delayed, as map is initialized")
            for (callback in initializedCallbackList) {
                try {
                    callback.onMapReady(this)
                } catch (e: Exception) {
                    Log.w(TAG, e)
                }
                callback.onMapReady(map)
            }
        }

@@ -769,8 +788,7 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
        mapView?.onDestroy()
        mapView = null

        // Don't make it null; this object is not deleted immediately, and it may want to access map.* stuff
        //map = null
        map = null

        created = false
        initialized = false
@@ -802,16 +820,25 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)

    fun getMapAsync(callback: IOnMapReadyCallback) {
        synchronized(mapLock) {
            if (initialized) {
                Log.d(TAG, "Invoking callback instantly, as map is initialized")

            val runCallback = {
                try {
                    callback.onMapReady(this)
                } catch (e: Exception) {
                    Log.w(TAG, e)
                }
            }

            if (initialized) {
                Log.d(TAG, "Invoking callback instantly, as map is initialized")
                runCallback()
            } else if (mapView?.isShown != true) {
                // If map is not shown, an app (e.g. Dott) may expect it to initialize anyway – before showing it
                Log.d(TAG, "Invoking callback instantly: map cannot be initialized because it is not shown (yet)")
                runCallback()
            } else {
                Log.d(TAG, "Delay callback invocation, as map is not yet initialized")
                initializedCallbackList.add(callback)
                initializedCallbackList.add { runCallback() }
            }
        }
    }
+122 −39
Original line number Diff line number Diff line
@@ -17,45 +17,22 @@
package org.microg.gms.maps.mapbox

import android.os.Parcel
import android.os.RemoteException
import android.util.Log

import com.google.android.gms.maps.internal.IUiSettingsDelegate
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
import com.mapbox.mapboxsdk.maps.UiSettings

class UiSettingsImpl(private val uiSettings: UiSettings) : IUiSettingsDelegate.Stub() {

/**
 * This class "implements" unimplemented methods to avoid duplication in subclasses
 */
abstract class AbstractUiSettings : IUiSettingsDelegate.Stub() {
    override fun setZoomControlsEnabled(zoom: Boolean) {
        Log.d(TAG, "unimplemented Method: setZoomControlsEnabled")
    }

    override fun setCompassEnabled(compass: Boolean) {
        uiSettings.isCompassEnabled = compass
    }

    override fun setMyLocationButtonEnabled(locationButton: Boolean) {
        Log.d(TAG, "unimplemented Method: setMyLocationButtonEnabled")

    }

    override fun setScrollGesturesEnabled(scrollGestures: Boolean) {
        uiSettings.isScrollGesturesEnabled = scrollGestures
    }

    override fun setZoomGesturesEnabled(zoomGestures: Boolean) {
        uiSettings.isZoomGesturesEnabled = zoomGestures
    }

    override fun setTiltGesturesEnabled(tiltGestures: Boolean) {
        uiSettings.isTiltGesturesEnabled = tiltGestures
    }

    override fun setRotateGesturesEnabled(rotateGestures: Boolean) {
        uiSettings.isRotateGesturesEnabled = rotateGestures
    }

    override fun setAllGesturesEnabled(gestures: Boolean) {
        uiSettings.setAllGesturesEnabled(gestures)
    }

    override fun isZoomControlsEnabled(): Boolean {
@@ -63,21 +40,11 @@ class UiSettingsImpl(private val uiSettings: UiSettings) : IUiSettingsDelegate.S
        return false
    }

    override fun isCompassEnabled(): Boolean = uiSettings.isCompassEnabled

    override fun isMyLocationButtonEnabled(): Boolean {
        Log.d(TAG, "unimplemented Method: isMyLocationButtonEnabled")
        return false
    }

    override fun isScrollGesturesEnabled(): Boolean = uiSettings.isScrollGesturesEnabled

    override fun isZoomGesturesEnabled(): Boolean = uiSettings.isZoomGesturesEnabled

    override fun isTiltGesturesEnabled(): Boolean = uiSettings.isTiltGesturesEnabled

    override fun isRotateGesturesEnabled(): Boolean = uiSettings.isRotateGesturesEnabled

    override fun setIndoorLevelPickerEnabled(indoorLevelPicker: Boolean) {
        Log.d(TAG, "unimplemented Method: setIndoorLevelPickerEnabled")
    }
@@ -105,6 +72,48 @@ class UiSettingsImpl(private val uiSettings: UiSettings) : IUiSettingsDelegate.S
        return true
    }

    companion object {
        private val TAG = "GmsMapsUi"
    }
}

class UiSettingsImpl(private val uiSettings: UiSettings) : AbstractUiSettings() {


    override fun setCompassEnabled(compass: Boolean) {
        uiSettings.isCompassEnabled = compass
    }

    override fun setScrollGesturesEnabled(scrollGestures: Boolean) {
        uiSettings.isScrollGesturesEnabled = scrollGestures
    }

    override fun setZoomGesturesEnabled(zoomGestures: Boolean) {
        uiSettings.isZoomGesturesEnabled = zoomGestures
    }

    override fun setTiltGesturesEnabled(tiltGestures: Boolean) {
        uiSettings.isTiltGesturesEnabled = tiltGestures
    }

    override fun setRotateGesturesEnabled(rotateGestures: Boolean) {
        uiSettings.isRotateGesturesEnabled = rotateGestures
    }

    override fun setAllGesturesEnabled(gestures: Boolean) {
        uiSettings.setAllGesturesEnabled(gestures)
    }

    override fun isCompassEnabled(): Boolean = uiSettings.isCompassEnabled

    override fun isScrollGesturesEnabled(): Boolean = uiSettings.isScrollGesturesEnabled

    override fun isZoomGesturesEnabled(): Boolean = uiSettings.isZoomGesturesEnabled

    override fun isTiltGesturesEnabled(): Boolean = uiSettings.isTiltGesturesEnabled

    override fun isRotateGesturesEnabled(): Boolean = uiSettings.isRotateGesturesEnabled

    override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean =
            if (super.onTransact(code, data, reply, flags)) {
                true
@@ -113,6 +122,80 @@ class UiSettingsImpl(private val uiSettings: UiSettings) : IUiSettingsDelegate.S
            }

    companion object {
        private val TAG = "GmsMapsUi"
        private val TAG = "GmsMapsUiImpl"
    }
}

class UiSettingsCache : AbstractUiSettings() {

    private var compass: Boolean? = null
    private var scrollGestures: Boolean? = null
    private var zoomGestures: Boolean? = null
    private var tiltGestures: Boolean? = null
    private var rotateGestures: Boolean? = null
    private var otherGestures: Boolean? = null

    override fun setCompassEnabled(compass: Boolean) {
        this.compass = compass
    }

    override fun setScrollGesturesEnabled(scrollGestures: Boolean) {
        this.scrollGestures = scrollGestures
    }

    override fun setZoomGesturesEnabled(zoomGestures: Boolean) {
        this.zoomGestures = zoomGestures
    }

    override fun setTiltGesturesEnabled(tiltGestures: Boolean) {
        this.tiltGestures = tiltGestures
    }

    override fun setRotateGesturesEnabled(rotateGestures: Boolean) {
        this.rotateGestures = rotateGestures
    }

    override fun setAllGesturesEnabled(gestures: Boolean) {
        // Simulate MapLibre's UiSettings behavior
        isScrollGesturesEnabled = gestures
        isRotateGesturesEnabled = gestures
        isTiltGesturesEnabled = gestures
        isZoomGesturesEnabled = gestures

        // Other gestures toggles double tap and quick zoom gestures
        otherGestures = gestures
    }

    override fun isCompassEnabled(): Boolean {
        return compass ?: true
    }

    override fun isScrollGesturesEnabled(): Boolean {
        return scrollGestures ?: true
    }

    override fun isZoomGesturesEnabled(): Boolean {
        return zoomGestures ?: true
    }

    override fun isTiltGesturesEnabled(): Boolean {
        return tiltGestures ?: true
    }

    override fun isRotateGesturesEnabled(): Boolean {
        return rotateGestures ?: true
    }

    fun getMapReadyCallback(): OnMapReadyCallback = OnMapReadyCallback { map ->
        val uiSettings = map.uiSettings
        compass?.let { uiSettings.isCompassEnabled = it }
        scrollGestures?.let { uiSettings.isScrollGesturesEnabled = it }
        zoomGestures?.let { uiSettings.isZoomGesturesEnabled = it }
        tiltGestures?.let { uiSettings.isTiltGesturesEnabled = it }
        rotateGestures?.let { uiSettings.isRotateGesturesEnabled = it }
        otherGestures?.let {
            uiSettings.isDoubleTapGesturesEnabled = it
            uiSettings.isQuickZoomGesturesEnabled = it
        }
    }
}
 No newline at end of file