From 090100951a3ce5f63ae794da0883776fe453f686 Mon Sep 17 00:00:00 2001 From: Kyle Madsen Date: Thu, 8 Sep 2022 15:29:45 -0700 Subject: [PATCH] Start declaring apis with java interop --- libnavigation-core/api/current.txt | 24 +++--- .../core/lifecycle/MapboxNavigationApp.kt | 32 +++++++ libnavui-androidauto/api/current.txt | 2 +- .../androidauto/MapboxCarNavigationManager.kt | 1 - .../testing/CarJavaInterfaceChecker.java | 83 +++++++++++++++++++ .../qa_test_app/testing/JavaFlow.kt | 28 +++++++ 6 files changed, 157 insertions(+), 13 deletions(-) create mode 100644 qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/testing/CarJavaInterfaceChecker.java create mode 100644 qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/testing/JavaFlow.kt diff --git a/libnavigation-core/api/current.txt b/libnavigation-core/api/current.txt index ef6b71499d3..bb6737df65b 100644 --- a/libnavigation-core/api/current.txt +++ b/libnavigation-core/api/current.txt @@ -311,19 +311,21 @@ package com.mapbox.navigation.core.history.model { package com.mapbox.navigation.core.lifecycle { public final class MapboxNavigationApp { - method @UiThread public com.mapbox.navigation.core.lifecycle.MapboxNavigationApp attach(androidx.lifecycle.LifecycleOwner lifecycleOwner); + method @UiThread public static com.mapbox.navigation.core.lifecycle.MapboxNavigationApp attach(androidx.lifecycle.LifecycleOwner lifecycleOwner); method public com.mapbox.navigation.core.lifecycle.MapboxNavigationApp attachAllActivities(android.app.Application application); - method public com.mapbox.navigation.core.MapboxNavigation? current(); - method @UiThread public com.mapbox.navigation.core.lifecycle.MapboxNavigationApp detach(androidx.lifecycle.LifecycleOwner lifecycleOwner); - method @UiThread public com.mapbox.navigation.core.lifecycle.MapboxNavigationApp disable(); + method public static com.mapbox.navigation.core.MapboxNavigation? current(); + method @UiThread public static com.mapbox.navigation.core.lifecycle.MapboxNavigationApp detach(androidx.lifecycle.LifecycleOwner lifecycleOwner); + method @UiThread public static com.mapbox.navigation.core.lifecycle.MapboxNavigationApp disable(); method public androidx.lifecycle.LifecycleOwner getLifecycleOwner(); - method public T getObserver(kotlin.reflect.KClass kClass); - method public java.util.List getObservers(kotlin.reflect.KClass kClass); - method @UiThread public boolean isSetup(); - method @UiThread public com.mapbox.navigation.core.lifecycle.MapboxNavigationApp registerObserver(com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver mapboxNavigationObserver); - method @UiThread public com.mapbox.navigation.core.lifecycle.MapboxNavigationApp setup(com.mapbox.navigation.base.options.NavigationOptions navigationOptions); - method @UiThread public com.mapbox.navigation.core.lifecycle.MapboxNavigationApp setup(com.mapbox.navigation.core.lifecycle.NavigationOptionsProvider navigationOptionsProvider); - method @UiThread public com.mapbox.navigation.core.lifecycle.MapboxNavigationApp unregisterObserver(com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver mapboxNavigationObserver); + method public static T getObserver(kotlin.reflect.KClass kClass); + method public static T getObserver(Class clazz); + method public static java.util.List getObservers(kotlin.reflect.KClass kClass); + method public static java.util.List getObservers(Class clazz); + method @UiThread public static boolean isSetup(); + method @UiThread public static com.mapbox.navigation.core.lifecycle.MapboxNavigationApp registerObserver(com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver mapboxNavigationObserver); + method @UiThread public static com.mapbox.navigation.core.lifecycle.MapboxNavigationApp setup(com.mapbox.navigation.base.options.NavigationOptions navigationOptions); + method @UiThread public static com.mapbox.navigation.core.lifecycle.MapboxNavigationApp setup(com.mapbox.navigation.core.lifecycle.NavigationOptionsProvider navigationOptionsProvider); + method @UiThread public static com.mapbox.navigation.core.lifecycle.MapboxNavigationApp unregisterObserver(com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver mapboxNavigationObserver); property public final androidx.lifecycle.LifecycleOwner lifecycleOwner; field public static final com.mapbox.navigation.core.lifecycle.MapboxNavigationApp INSTANCE; } diff --git a/libnavigation-core/src/main/java/com/mapbox/navigation/core/lifecycle/MapboxNavigationApp.kt b/libnavigation-core/src/main/java/com/mapbox/navigation/core/lifecycle/MapboxNavigationApp.kt index ef8ff367480..6fefe2d07d9 100644 --- a/libnavigation-core/src/main/java/com/mapbox/navigation/core/lifecycle/MapboxNavigationApp.kt +++ b/libnavigation-core/src/main/java/com/mapbox/navigation/core/lifecycle/MapboxNavigationApp.kt @@ -72,6 +72,7 @@ object MapboxNavigationApp { * Returns true after [setup] has been called and false after [disable] is called. */ @UiThread + @JvmStatic fun isSetup(): Boolean = mapboxNavigationAppDelegate.isSetup /** @@ -81,6 +82,7 @@ object MapboxNavigationApp { * [Activity.isChangingConfigurations]. */ @UiThread + @JvmStatic fun setup(navigationOptions: NavigationOptions) = apply { mapboxNavigationAppDelegate.setup { navigationOptions } } @@ -93,6 +95,7 @@ object MapboxNavigationApp { * [Activity.isChangingConfigurations]. */ @UiThread + @JvmStatic fun setup(navigationOptionsProvider: NavigationOptionsProvider) = apply { mapboxNavigationAppDelegate.setup(navigationOptionsProvider) } @@ -110,6 +113,7 @@ object MapboxNavigationApp { * You can re-enable [MapboxNavigation] by calling [MapboxNavigationApp.setup]. */ @UiThread + @JvmStatic fun disable() = apply { mapboxNavigationAppDelegate.disable() } @@ -124,6 +128,7 @@ object MapboxNavigationApp { * it will be removed from the observers automatically. */ @UiThread + @JvmStatic fun attach(lifecycleOwner: LifecycleOwner) = apply { mapboxNavigationAppDelegate.attach(lifecycleOwner) } @@ -138,6 +143,7 @@ object MapboxNavigationApp { * and will potentially cause [MapboxNavigation] to never be created. */ @UiThread + @JvmStatic fun detach(lifecycleOwner: LifecycleOwner) = apply { mapboxNavigationAppDelegate.detach(lifecycleOwner) } @@ -146,6 +152,7 @@ object MapboxNavigationApp { * Register an observer to receive the [MapboxNavigation] instance. */ @UiThread + @JvmStatic fun registerObserver(mapboxNavigationObserver: MapboxNavigationObserver) = apply { mapboxNavigationAppDelegate.registerObserver(mapboxNavigationObserver) } @@ -154,6 +161,7 @@ object MapboxNavigationApp { * Unregister the observer that was registered through [registerObserver]. */ @UiThread + @JvmStatic fun unregisterObserver(mapboxNavigationObserver: MapboxNavigationObserver) = apply { mapboxNavigationAppDelegate.unregisterObserver(mapboxNavigationObserver) } @@ -164,6 +172,7 @@ object MapboxNavigationApp { * * @throws IllegalStateException when the class has not been registered. */ + @JvmStatic fun getObserver(kClass: KClass): T { return mapboxNavigationAppDelegate.getObserver(kClass) } @@ -172,10 +181,32 @@ object MapboxNavigationApp { * Provides access to any registered observer instance. If no observers have been registered * with this class type, an empty list is returned. */ + @JvmStatic fun getObservers(kClass: KClass): List { return mapboxNavigationAppDelegate.getObservers(kClass) } + /** + * Java interoperability. Provides access to any registered observer instance. If multiple + * instances of the same class have been registered, the first observer will be returned. + * + * @throws IllegalStateException when the class has not been registered. + */ + @JvmStatic + fun getObserver(clazz: Class): T { + return mapboxNavigationAppDelegate.getObserver(clazz) + } + + /** + * Java interoperability. Provides access to any registered observer instance. If no observers + * have been registered with this class type, an empty list is returned. + */ + @JvmStatic + fun getObservers(clazz: Class): List { + return mapboxNavigationAppDelegate.getObservers(clazz) + } + + /** * [MapboxNavigation] has functions that do not require observation streams. This function * allows you to get the current instance to call those functions. @@ -183,5 +214,6 @@ object MapboxNavigationApp { * For example, you do not need to [registerObserver] in order to call * [MapboxNavigation.postUserFeedback] or [MapboxNavigation.setRoutes]. */ + @JvmStatic fun current(): MapboxNavigation? = mapboxNavigationAppDelegate.current() } diff --git a/libnavui-androidauto/api/current.txt b/libnavui-androidauto/api/current.txt index 53441f5f46d..eff7355c0f7 100644 --- a/libnavui-androidauto/api/current.txt +++ b/libnavui-androidauto/api/current.txt @@ -26,7 +26,7 @@ package com.mapbox.androidauto { field public static final com.mapbox.androidauto.MapboxCarApp INSTANCE; } - @com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI public final class MapboxCarNavigationManager implements com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver { + public final class MapboxCarNavigationManager implements com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver { ctor public MapboxCarNavigationManager(androidx.car.app.CarContext carContext); method public kotlinx.coroutines.flow.StateFlow getAutoDriveEnabledFlow(); method public void onAttached(com.mapbox.navigation.core.MapboxNavigation mapboxNavigation); diff --git a/libnavui-androidauto/src/main/java/com/mapbox/androidauto/MapboxCarNavigationManager.kt b/libnavui-androidauto/src/main/java/com/mapbox/androidauto/MapboxCarNavigationManager.kt index e388b003163..7416b1eb166 100644 --- a/libnavui-androidauto/src/main/java/com/mapbox/androidauto/MapboxCarNavigationManager.kt +++ b/libnavui-androidauto/src/main/java/com/mapbox/androidauto/MapboxCarNavigationManager.kt @@ -24,7 +24,6 @@ import kotlinx.coroutines.flow.StateFlow * registered, the trip status of [MapboxNavigation] will be sent to the [NavigationManager]. * This is needed to keep the vehicle cluster display updated. */ -@ExperimentalPreviewMapboxNavigationAPI class MapboxCarNavigationManager( carContext: CarContext ) : MapboxNavigationObserver { diff --git a/qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/testing/CarJavaInterfaceChecker.java b/qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/testing/CarJavaInterfaceChecker.java new file mode 100644 index 00000000000..13f6b116da8 --- /dev/null +++ b/qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/testing/CarJavaInterfaceChecker.java @@ -0,0 +1,83 @@ +package com.mapbox.navigation.qa_test_app.testing; + +import androidx.annotation.NonNull; +import androidx.car.app.CarContext; +import androidx.lifecycle.LifecycleOwner; + +import com.mapbox.androidauto.MapboxCarNavigationManager; +import com.mapbox.androidauto.internal.car.search.CarPlaceSearch; +import com.mapbox.maps.extension.androidauto.MapboxCarMap; +import com.mapbox.navigation.base.options.NavigationOptions; +import com.mapbox.navigation.core.MapboxNavigation; +import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp; +import com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver; + +import java.util.List; + +import kotlinx.coroutines.CoroutineScope; + +class CarJavaInterfaceChecker { + + void MapboxNavigationApp( + LifecycleOwner lifecycleOwner, + NavigationOptions navigationOptions, + MapboxNavigationObserver observer + ) { + // Set up now + MapboxNavigationApp.setup(navigationOptions); + + // Set up provider + MapboxNavigationApp.setup(() -> navigationOptions); + + // Control lifecycles + MapboxNavigationApp.attach(lifecycleOwner); + MapboxNavigationApp.disable(); + MapboxNavigationApp.detach(lifecycleOwner); + + // Get current instance + MapboxNavigation mapboxNavigation = MapboxNavigationApp.current(); + + // Register and unregister observer + MapboxNavigationApp.registerObserver(observer); + MapboxNavigationApp.unregisterObserver(observer); + + MapboxNavigationObserver otherObserver = MapboxNavigationApp.getObserver(CarPlaceSearch.class); + List otherObservers = MapboxNavigationApp.getObservers(CarPlaceSearch.class); + } + + void MapboxNavigationObserver() { + MapboxNavigationObserver observer = new MapboxNavigationObserver() { + @Override + public void onAttached(@NonNull MapboxNavigation mapboxNavigation) { + + } + + @Override + public void onDetached(@NonNull MapboxNavigation mapboxNavigation) { + + } + }; + } + + void MapboxCarNavigationManager( + CarContext carContext, + LifecycleOwner lifecycleOwner, + MapboxCarMap mapboxCarMap + ) { + // Constructor + MapboxCarNavigationManager sut = new MapboxCarNavigationManager(carContext); + + // Observing auto drive + CoroutineScope scope = JavaFlow.lifecycleScope(lifecycleOwner); + JavaFlow.collect(sut.getAutoDriveEnabledFlow(), scope, (enabled) -> { + // check enabled + }); + + // Get auto drive value + boolean isEnabled = sut.getAutoDriveEnabledFlow().getValue(); + + // Register onto MapboxNavigationAPp + MapboxNavigationApp.registerObserver(sut); + MapboxNavigationApp.unregisterObserver(sut); + } +} diff --git a/qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/testing/JavaFlow.kt b/qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/testing/JavaFlow.kt new file mode 100644 index 00000000000..d28ad0a6488 --- /dev/null +++ b/qa-test-app/src/main/java/com/mapbox/navigation/qa_test_app/testing/JavaFlow.kt @@ -0,0 +1,28 @@ +package com.mapbox.navigation.qa_test_app.testing + +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch + +/** + * This is not production tested. It is used to showcase java interoperability. + */ +object JavaFlow { + + @JvmStatic + fun lifecycleScope(owner: LifecycleOwner): CoroutineScope = owner.lifecycleScope + + @JvmStatic + fun collect(flow: Flow, scope: CoroutineScope, consumer: Consumer) { + scope.launch { + flow.collect { value -> consumer.accept(value) } + } + } +} + +interface Consumer { + fun accept(value: T) +}