Skip to content

Commit

Permalink
Allow for downstream upgrades
Browse files Browse the repository at this point in the history
  • Loading branch information
kmadsen committed Sep 22, 2022
1 parent 8d9aace commit 4f1eb41
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.mapbox.maps.MapboxExperimental;
import com.mapbox.maps.ResourceOptions;
import com.mapbox.maps.ScreenCoordinate;
import com.mapbox.maps.extension.androidauto.CarMapSurfaceOwner;
import com.mapbox.maps.extension.androidauto.MapboxCarMap;
import com.mapbox.maps.extension.androidauto.DefaultMapboxCarMapGestureHandler;
import com.mapbox.maps.extension.androidauto.MapboxCarMapEx;
Expand All @@ -24,8 +25,13 @@
@MapboxExperimental
class CarJavaInterfaceChecker {

void constructors(MapInitOptions mapInitOptions) {
MapboxCarMap mapboxCarMap = new MapboxCarMap();
void constructorMapboxCarMap(MapInitOptions mapInitOptions) {
new MapboxCarMap();
}

void constructorsCarMapSurfaceOwner(MapboxCarMapGestureHandler gestures) {
new CarMapSurfaceOwner();
new CarMapSurfaceOwner(gestures);
}

void getters(MapboxCarMap mapboxCarMap) {
Expand Down
1 change: 1 addition & 0 deletions extension-androidauto/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Mapbox welcomes participation and contributions from everyone.
* Change `MapboxCarMapObserver` to an java interface so default methods can be added without breaking java backwards compatibility. ([#1670](https://github.com/mapbox/mapbox-maps-android/pull/1648))
* Change `MapboxCarMap#getEdgeInsets()` to `mapboxCarMap.getVisibleEdgeInsets()` with the addition of `mapboxCarMap.getStableEdgeInsets()`. ([#1670](https://github.com/mapbox/mapbox-maps-android/pull/1648))
* Add `MapboxCarMapObserver#onStableAreaChanged` to support all the available functions from the SurfaceCallback. ([#1670](https://github.com/mapbox/mapbox-maps-android/pull/1648))
* Add support for intercepting the `SurfaceCallback#onClick` when using `MapboxCarMap.prepareSurfaceCallback`. ([#1683](https://github.com/mapbox/mapbox-maps-android/pull/1683)])

## Bug fixes 🐞

Expand Down
7 changes: 4 additions & 3 deletions extension-androidauto/api/extension-androidauto.api
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@ public class com/mapbox/maps/extension/androidauto/DefaultMapboxCarMapGestureHan

public final class com/mapbox/maps/extension/androidauto/MapboxCarMap {
public fun <init> ()V
public final fun clearObservers ()V
public final fun clearObservers ()Lcom/mapbox/maps/extension/androidauto/MapboxCarMap;
public final fun getCarContext ()Landroidx/car/app/CarContext;
public final fun getCarMapSurface ()Lcom/mapbox/maps/extension/androidauto/MapboxCarMapSurface;
public final fun getMapInitOptions ()Lcom/mapbox/maps/MapInitOptions;
public final fun getStableArea ()Landroid/graphics/Rect;
public final fun getStableEdgeInsets ()Lcom/mapbox/maps/EdgeInsets;
public final fun getVisibleArea ()Landroid/graphics/Rect;
public final fun getVisibleEdgeInsets ()Lcom/mapbox/maps/EdgeInsets;
public final fun prepareSurfaceCallback (Landroidx/car/app/CarContext;Lcom/mapbox/maps/MapInitOptions;)Landroidx/car/app/SurfaceCallback;
public final fun registerObserver (Lcom/mapbox/maps/extension/androidauto/MapboxCarMapObserver;)Lcom/mapbox/maps/extension/androidauto/MapboxCarMap;
public final fun setGestureHandler (Lcom/mapbox/maps/extension/androidauto/MapboxCarMapGestureHandler;)V
public final fun setGestureHandler (Lcom/mapbox/maps/extension/androidauto/MapboxCarMapGestureHandler;)Lcom/mapbox/maps/extension/androidauto/MapboxCarMap;
public final fun setup (Landroidx/car/app/CarContext;Lcom/mapbox/maps/MapInitOptions;)Lcom/mapbox/maps/extension/androidauto/MapboxCarMap;
public final fun unregisterObserver (Lcom/mapbox/maps/extension/androidauto/MapboxCarMapObserver;)V
public final fun unregisterObserver (Lcom/mapbox/maps/extension/androidauto/MapboxCarMapObserver;)Lcom/mapbox/maps/extension/androidauto/MapboxCarMap;
}

public final class com/mapbox/maps/extension/androidauto/MapboxCarMapEx {
Expand Down
7 changes: 4 additions & 3 deletions extension-androidauto/api/metalava.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@ package com.mapbox.maps.extension.androidauto {

@com.mapbox.maps.MapboxExperimental public final class MapboxCarMap {
ctor public MapboxCarMap();
method public void clearObservers();
method public com.mapbox.maps.extension.androidauto.MapboxCarMap clearObservers();
method public androidx.car.app.CarContext getCarContext();
method public com.mapbox.maps.extension.androidauto.MapboxCarMapSurface? getCarMapSurface();
method public com.mapbox.maps.MapInitOptions getMapInitOptions();
method public android.graphics.Rect? getStableArea();
method public com.mapbox.maps.EdgeInsets? getStableEdgeInsets();
method public android.graphics.Rect? getVisibleArea();
method public com.mapbox.maps.EdgeInsets? getVisibleEdgeInsets();
method @com.mapbox.maps.MapboxExperimental public androidx.car.app.SurfaceCallback prepareSurfaceCallback(androidx.car.app.CarContext carContext, com.mapbox.maps.MapInitOptions mapInitOptions);
method public com.mapbox.maps.extension.androidauto.MapboxCarMap registerObserver(com.mapbox.maps.extension.androidauto.MapboxCarMapObserver mapboxCarMapObserver);
method public void setGestureHandler(com.mapbox.maps.extension.androidauto.MapboxCarMapGestureHandler? gestureHandler);
method public com.mapbox.maps.extension.androidauto.MapboxCarMap setGestureHandler(com.mapbox.maps.extension.androidauto.MapboxCarMapGestureHandler? gestureHandler);
method public com.mapbox.maps.extension.androidauto.MapboxCarMap setup(androidx.car.app.CarContext carContext, com.mapbox.maps.MapInitOptions mapInitOptions);
method public void unregisterObserver(com.mapbox.maps.extension.androidauto.MapboxCarMapObserver mapboxCarMapObserver);
method public com.mapbox.maps.extension.androidauto.MapboxCarMap unregisterObserver(com.mapbox.maps.extension.androidauto.MapboxCarMapObserver mapboxCarMapObserver);
property public final androidx.car.app.CarContext carContext;
property public final com.mapbox.maps.extension.androidauto.MapboxCarMapSurface? carMapSurface;
property public final com.mapbox.maps.MapInitOptions mapInitOptions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.car.app.SurfaceCallback
import androidx.car.app.SurfaceContainer
import com.mapbox.maps.EdgeInsets
import com.mapbox.maps.MapInitOptions
import com.mapbox.maps.MapSurface
import com.mapbox.maps.MapboxExperimental
import com.mapbox.maps.ScreenCoordinate
import com.mapbox.maps.logI
Expand All @@ -17,8 +18,8 @@ import java.util.concurrent.CopyOnWriteArraySet
* Maintains the surface state for [MapboxCarMap].
*/
@MapboxExperimental
internal class CarMapSurfaceOwner(
var gestureHandler: MapboxCarMapGestureHandler? = DefaultMapboxCarMapGestureHandler()
internal class CarMapSurfaceOwner @JvmOverloads constructor(
internal var gestureHandler: MapboxCarMapGestureHandler? = DefaultMapboxCarMapGestureHandler()
) : SurfaceCallback {

internal var mapboxCarMapSurface: MapboxCarMapSurface? = null
Expand All @@ -38,14 +39,14 @@ internal class CarMapSurfaceOwner(

private val carMapObservers = CopyOnWriteArraySet<MapboxCarMapObserver>()

fun setup(carContext: CarContext, mapInitOptions: MapInitOptions) = apply {
internal fun setup(carContext: CarContext, mapInitOptions: MapInitOptions) = apply {
this.carContext = carContext
this.mapInitOptions = mapInitOptions
}

fun isSetup(): Boolean = this::carContext.isInitialized && this::mapInitOptions.isInitialized
internal fun isSetup(): Boolean = this::carContext.isInitialized && this::mapInitOptions.isInitialized

fun registerObserver(mapboxCarMapObserver: MapboxCarMapObserver) {
internal fun registerObserver(mapboxCarMapObserver: MapboxCarMapObserver) {
carMapObservers.add(mapboxCarMapObserver)
logI(TAG, "registerObserver + 1 = ${carMapObservers.size}")

Expand All @@ -62,17 +63,23 @@ internal class CarMapSurfaceOwner(
}
}

fun unregisterObserver(mapboxCarMapObserver: MapboxCarMapObserver) {
internal fun unregisterObserver(mapboxCarMapObserver: MapboxCarMapObserver) {
carMapObservers.remove(mapboxCarMapObserver)
mapboxCarMapSurface?.let { mapboxCarMapObserver.onDetached(it) }
logI(TAG, "unregisterObserver - 1 = ${carMapObservers.size}")
}

fun clearObservers() {
internal fun clearObservers() {
this.mapboxCarMapSurface?.let { surface -> carMapObservers.forEach { it.onDetached(surface) } }
carMapObservers.clear()
}

/**
* Prepares the [MapSurface] and notifies any registered observers that the map has been attached
* with [MapboxCarMapObserver.onAttached].
*
* @see SurfaceCallback.onSurfaceAvailable
*/
override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) {
logI(TAG, "onSurfaceAvailable $surfaceContainer")
surfaceContainer.surface?.let { surface ->
Expand Down Expand Up @@ -101,6 +108,12 @@ internal class CarMapSurfaceOwner(
}
}

/**
* Destroys the resources used by [MapSurface] and notifies any registered observers that the map
* has been detached with [MapboxCarMapObserver.onDetached].
*
* @see SurfaceCallback.onSurfaceDestroyed
*/
override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) {
logI(TAG, "onSurfaceDestroyed")
val detachSurface = this.mapboxCarMapSurface
Expand All @@ -111,6 +124,12 @@ internal class CarMapSurfaceOwner(
detachSurface?.let { carMapObservers.forEach { it.onDetached(detachSurface) } }
}

/**
* Notifies any registered observers that the visible area has changed with
* [MapboxCarMapObserver.onVisibleAreaChanged].
*
* @see SurfaceCallback.onVisibleAreaChanged
*/
override fun onVisibleAreaChanged(visibleArea: Rect) {
logI(TAG, "onVisibleAreaChanged visibleArea:$visibleArea")
this.visibleArea = visibleArea
Expand All @@ -128,6 +147,12 @@ internal class CarMapSurfaceOwner(
}
}

/**
* Notifies any registered observers that the visible area has changed with
* [MapboxCarMapObserver.onStableAreaChanged].
*
* @see SurfaceCallback.onStableAreaChanged
*/
override fun onStableAreaChanged(stableArea: Rect) {
logI(TAG, "onStableAreaChanged stableArea:$stableArea")
this.stableEdgeInsets = stableArea.edgeInsets()
Expand All @@ -140,18 +165,33 @@ internal class CarMapSurfaceOwner(
}
}

/**
* Forwards the gesture to the [MapboxCarMapGestureHandler.onScroll].
*
* @see SurfaceCallback.onScroll
*/
override fun onScroll(distanceX: Float, distanceY: Float) {
logI(TAG, "onScroll $distanceX, $distanceY")
val carMapSurface = mapboxCarMapSurface ?: return
gestureHandler?.onScroll(carMapSurface, visibleCenter, distanceX, distanceY)
}

/**
* Forwards the gesture to the [MapboxCarMapGestureHandler.onFling].
*
* @see SurfaceCallback.onFling
*/
override fun onFling(velocityX: Float, velocityY: Float) {
logI(TAG, "onFling $velocityX, $velocityY")
val carMapSurface = mapboxCarMapSurface ?: return
gestureHandler?.onFling(carMapSurface, velocityX, velocityY)
}

/**
* Forwards the gesture to the [MapboxCarMapGestureHandler.onScale].
*
* @see SurfaceCallback.onScale
*/
override fun onScale(focusX: Float, focusY: Float, scaleFactor: Float) {
logI(TAG, "onScroll $focusX, $focusY, $scaleFactor")
val carMapSurface = mapboxCarMapSurface ?: return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.graphics.Rect
import androidx.car.app.AppManager
import androidx.car.app.CarContext
import androidx.car.app.Session
import androidx.car.app.SurfaceCallback
import androidx.lifecycle.Lifecycle
import com.mapbox.maps.EdgeInsets
import com.mapbox.maps.MapInitOptions
Expand Down Expand Up @@ -71,11 +72,29 @@ class MapboxCarMap {
carContext: CarContext,
mapInitOptions: MapInitOptions,
) = apply {
val surfaceCallback = prepareSurfaceCallback(carContext, mapInitOptions)
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
}

/**
* Instead of using [setup], this function allows you to create your own [SurfaceCallback] and
* forward the calls to the returned [SurfaceCallback]. This makes it possible for you to adopt
* new api versions or intercept the calls and continue to use the [MapboxCarMap] as designed.
*
* This may be a temporary solution, while androidx.car.app:app:1.3.0 is rolling out
* [SurfaceCallback.onClick]. If there is no use for this function in the future, it will be
* removed.
*/
@MapboxExperimental
fun prepareSurfaceCallback(
carContext: CarContext,
mapInitOptions: MapInitOptions
): SurfaceCallback {
check(mapInitOptions.context is CarContext) {
"You must setup the MapboxCarMap MapInitOptions with a CarContext"
"You must set up the MapboxCarMap MapInitOptions with a CarContext"
}
carMapSurfaceOwner.setup(carContext, mapInitOptions)
carContext.getCarService(AppManager::class.java).setSurfaceCallback(carMapSurfaceOwner)
return carMapSurfaceOwner
}

/**
Expand Down Expand Up @@ -123,14 +142,14 @@ class MapboxCarMap {
/**
* @param mapboxCarMapObserver the instance used in [registerObserver]
*/
fun unregisterObserver(mapboxCarMapObserver: MapboxCarMapObserver) {
fun unregisterObserver(mapboxCarMapObserver: MapboxCarMapObserver) = apply {
carMapSurfaceOwner.unregisterObserver(mapboxCarMapObserver)
}

/**
* Optional function to clear all observers registered through [registerObserver]
*/
fun clearObservers() {
fun clearObservers() = apply {
carMapSurfaceOwner.clearObservers()
}

Expand All @@ -140,7 +159,7 @@ class MapboxCarMap {
* interface, or override the [DefaultMapboxCarMapGestureHandler], or set to null to disable
* gesture handling.
*/
fun setGestureHandler(gestureHandler: MapboxCarMapGestureHandler?) {
fun setGestureHandler(gestureHandler: MapboxCarMapGestureHandler?) = apply {
carMapSurfaceOwner.gestureHandler = gestureHandler
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,26 @@ class MapboxCarMapTest {
assertTrue(surfaceCallbackSlot.isCaptured)
}

@Test
fun `setup will call setSurfaceCallback`() {
MapboxCarMap().setup(carContext, mapInitOptions)

val appManager = carContext.getCarService(AppManager::class.java)
verify(exactly = 1) {
appManager.setSurfaceCallback(any())
}
}

@Test
fun `prepareSurfaceCallback does not call setSurfaceCallback`() {
MapboxCarMap().prepareSurfaceCallback(carContext, mapInitOptions)

val appManager = carContext.getCarService(AppManager::class.java)
verify(exactly = 0) {
appManager.setSurfaceCallback(any())
}
}

@Test
fun `carMapSurface is valid after onSurfaceAvailable`() {
val mapboxCarMap = MapboxCarMap().setup(carContext, mapInitOptions)
Expand Down

0 comments on commit 4f1eb41

Please sign in to comment.