diff --git a/android-auto-app/build.gradle.kts b/android-auto-app/build.gradle.kts index 67e82ef36f..be41284166 100644 --- a/android-auto-app/build.gradle.kts +++ b/android-auto-app/build.gradle.kts @@ -45,12 +45,16 @@ androidExtensions { dependencies { implementation(project(":extension-androidauto")) - implementation(Dependencies.googleCarAppLibrary) - + // Please review the compatibility guide. This app is showcasing the latest features. // https://github.com/mapbox/mapbox-maps-android/tree/main/extension-androidauto#compatibility-with-maps-sdk-v10 implementation("com.mapbox.maps:android:10.9.0-beta.2") + // Upgrade the google car library to demonstrate adopting new apis. + // https://developer.android.com/jetpack/androidx/releases/car-app + implementation("androidx.car.app:app:1.3.0-beta01") + // implementation(Dependencies.googleCarAppLibrary) + implementation(Dependencies.kotlin) implementation(Dependencies.androidxAppCompat) implementation(Dependencies.androidxCoreKtx) diff --git a/android-auto-app/src/main/AndroidManifest.xml b/android-auto-app/src/main/AndroidManifest.xml index 050e93ee3e..aa12635c96 100644 --- a/android-auto-app/src/main/AndroidManifest.xml +++ b/android-auto-app/src/main/AndroidManifest.xml @@ -35,7 +35,7 @@ tools:ignore="MetadataTagInsideApplicationTag" /> + if (carAppPreferences.isOnClickEnabled() != isChecked) { + Toast.makeText( + this, + "Custom setting changed, reconnect Android Auto to ensure a restart", + Toast.LENGTH_LONG + ).show() + carAppPreferences.enableOnClick(isChecked) + } + } } } \ No newline at end of file diff --git a/android-auto-app/src/main/java/com/mapbox/maps/testapp/auto/car/CarMapOnClickEnabler.kt b/android-auto-app/src/main/java/com/mapbox/maps/testapp/auto/car/CarMapOnClickEnabler.kt new file mode 100644 index 0000000000..88a70499c7 --- /dev/null +++ b/android-auto-app/src/main/java/com/mapbox/maps/testapp/auto/car/CarMapOnClickEnabler.kt @@ -0,0 +1,70 @@ +package com.mapbox.maps.testapp.auto.car + +import android.content.SharedPreferences +import androidx.car.app.AppManager +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner +import com.mapbox.maps.MapboxExperimental +import com.mapbox.maps.extension.androidauto.MapboxCarMap +import com.mapbox.maps.extension.androidauto.MapboxCarMapInitializer +import com.mapbox.maps.logI +import com.mapbox.maps.testapp.auto.CarAppPreferences +import com.mapbox.maps.testapp.auto.custom.SurfaceCallbackInterceptor + +/** + * In order to enable onClick, you need to override the mapboxCarMap.prepareSurfaceCallback + * + * This class allows you to toggle the preference from the app, to show that you can change this + * setting at runtime. In real scenarios, it may be initialize the map with onClick enabled. + */ +@OptIn(MapboxExperimental::class) +class CarMapOnClickEnabler( + private val mapboxCarMap: MapboxCarMap, + private val initializer: MapboxCarMapInitializer +) : DefaultLifecycleObserver { + + private var carAppPreferences: CarAppPreferences? = null + + private val listener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key -> + if (key == CarAppPreferences.BOOLEAN_KEY_ENABLE_ON_CLICK) { + val customCallbackEnabled = sharedPreferences.getBoolean(key, false) + onEnableOnClickPreferenceChanged(customCallbackEnabled) + } + } + + override fun onResume(owner: LifecycleOwner) { + super.onResume(owner) + carAppPreferences = CarAppPreferences(mapboxCarMap.carContext).apply { + sharedPreferences.registerOnSharedPreferenceChangeListener(listener) + onEnableOnClickPreferenceChanged(isOnClickEnabled()) + } + } + + override fun onPause(owner: LifecycleOwner) { + super.onPause(owner) + carAppPreferences?.sharedPreferences?.unregisterOnSharedPreferenceChangeListener(listener) + carAppPreferences = null + } + + private fun onEnableOnClickPreferenceChanged(customCallbackEnabled: Boolean) { + val carContext = mapboxCarMap.carContext + if (customCallbackEnabled) { + val surfaceCallback = mapboxCarMap.prepareSurfaceCallback( + carContext, initializer.onCreate(carContext) + ) + carContext.getCarService(AppManager::class.java) + .setSurfaceCallback(object : SurfaceCallbackInterceptor(surfaceCallback) { + override fun onClick(x: Float, y: Float) { + super.onClick(x, y) + onMapSurfaceClick(x, y) + } + }) + } else { + mapboxCarMap.setup(carContext, initializer.onCreate(carContext)) + } + } + + private fun onMapSurfaceClick(x: Float, y: Float) { + logI("CarMapOnClickEnabler", "onMapSurfaceClick $x $y") + } +} \ No newline at end of file diff --git a/android-auto-app/src/main/java/com/mapbox/maps/testapp/auto/car/MapSession.kt b/android-auto-app/src/main/java/com/mapbox/maps/testapp/auto/car/MapSession.kt index dc8428b15f..24fe04ff59 100644 --- a/android-auto-app/src/main/java/com/mapbox/maps/testapp/auto/car/MapSession.kt +++ b/android-auto-app/src/main/java/com/mapbox/maps/testapp/auto/car/MapSession.kt @@ -9,6 +9,7 @@ import androidx.car.app.ScreenManager import androidx.car.app.Session import com.mapbox.maps.MapInitOptions import com.mapbox.maps.MapboxExperimental +import com.mapbox.maps.extension.androidauto.MapboxCarMapInitializer import com.mapbox.maps.extension.androidauto.mapboxMapInstaller /** @@ -18,14 +19,20 @@ import com.mapbox.maps.extension.androidauto.mapboxMapInstaller class MapSession : Session() { private val carMapShowcase = CarMapShowcase() + private val initializer = MapboxCarMapInitializer { carContext -> MapInitOptions(carContext) } private val mapboxCarMap = mapboxMapInstaller() - .onCreated(CarAnimationThreadController(), CarMapWidgets(), carMapShowcase) + .onCreated(CarAnimationThreadController(), CarMapWidgets(), carMapShowcase,) .install { carContext -> // Callback is triggered when the Session calls onCreate. This allows you to specify // custom MapInitOptions. - MapInitOptions(carContext) + initializer.onCreate(carContext) } + init { + // Override the SurfaceCallback to capture onClick events + lifecycle.addObserver(CarMapOnClickEnabler(mapboxCarMap, initializer)) + } + override fun onCreateScreen(intent: Intent): Screen { // The onCreate is guaranteed to be called before onCreateScreen. You can pass the // mapboxCarMap to other screens. Each screen can register and unregister observers. diff --git a/android-auto-app/src/main/java/com/mapbox/maps/testapp/auto/custom/SurfaceCallbackInterceptor.kt b/android-auto-app/src/main/java/com/mapbox/maps/testapp/auto/custom/SurfaceCallbackInterceptor.kt new file mode 100644 index 0000000000..98e7fc8bfa --- /dev/null +++ b/android-auto-app/src/main/java/com/mapbox/maps/testapp/auto/custom/SurfaceCallbackInterceptor.kt @@ -0,0 +1,34 @@ +package com.mapbox.maps.testapp.auto.custom + +import android.graphics.Rect +import androidx.car.app.SurfaceCallback +import androidx.car.app.SurfaceContainer + +abstract class SurfaceCallbackInterceptor constructor( + private val surfaceCallback: SurfaceCallback +) : SurfaceCallback { + + override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) = + surfaceCallback.onSurfaceAvailable(surfaceContainer) + + override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) = + surfaceCallback.onSurfaceDestroyed(surfaceContainer) + + override fun onVisibleAreaChanged(visibleArea: Rect) = + surfaceCallback.onVisibleAreaChanged(visibleArea) + + override fun onStableAreaChanged(stableArea: Rect) = + surfaceCallback.onStableAreaChanged(stableArea) + + override fun onScale(focusX: Float, focusY: Float, scaleFactor: Float) = + surfaceCallback.onScale(focusX, focusY, scaleFactor) + + override fun onScroll(distanceX: Float, distanceY: Float) = + surfaceCallback.onScroll(distanceX, distanceY) + + override fun onFling(velocityX: Float, velocityY: Float) = + surfaceCallback.onFling(velocityX, velocityY) + + override fun onClick(x: Float, y: Float) = + surfaceCallback.onClick(x, y) +} \ No newline at end of file diff --git a/android-auto-app/src/main/res/layout/activity_main.xml b/android-auto-app/src/main/res/layout/activity_main.xml index 14e372440e..fb82985f5d 100644 --- a/android-auto-app/src/main/res/layout/activity_main.xml +++ b/android-auto-app/src/main/res/layout/activity_main.xml @@ -7,13 +7,25 @@ tools:context=".app.MainActivity"> + + \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Project.kt b/buildSrc/src/main/kotlin/Project.kt index f77313d695..6cd6c787c8 100644 --- a/buildSrc/src/main/kotlin/Project.kt +++ b/buildSrc/src/main/kotlin/Project.kt @@ -5,7 +5,7 @@ object AndroidVersions { object AndroidAuto { const val minSdkVersion = 23 const val targetSdkVersion = 30 - const val compileSdkVersion = 31 + const val compileSdkVersion = 33 } object Compose { const val minSdkVersion = 23 @@ -98,7 +98,7 @@ object Dependencies { object Versions { const val pluginAndroidGradle = "7.0.4" - const val pluginKotlin = "1.5.31" + const val pluginKotlin = "1.7.10" const val pluginLicense = "0.8.80" const val pluginDokka = "1.5.31" const val pluginJacoco = "0.2"