Skip to content

Commit

Permalink
Add example for onClick
Browse files Browse the repository at this point in the history
  • Loading branch information
kmadsen committed Oct 7, 2022
1 parent d9b9ea7 commit 2f0dc6f
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 8 deletions.
8 changes: 6 additions & 2 deletions android-auto-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion android-auto-app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
tools:ignore="MetadataTagInsideApplicationTag" />
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="1"
android:value="5"
tools:ignore="MetadataTagInsideApplicationTag" />

<service
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.mapbox.maps.testapp.auto

import android.content.Context
import android.content.SharedPreferences

/**
* Class gives you the ability to modify preferences that can be used by the car and app.
*/
class CarAppPreferences(context: Context) {

val sharedPreferences: SharedPreferences by lazy {
context.getSharedPreferences(SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
}

fun enableOnClick(enable: Boolean) {
sharedPreferences.edit().putBoolean(BOOLEAN_KEY_ENABLE_ON_CLICK, enable).apply()
}

fun isOnClickEnabled() = sharedPreferences
.getBoolean(BOOLEAN_KEY_ENABLE_ON_CLICK, false)

companion object {
private const val SHARED_PREFERENCES_KEY = "mapbox_maps_android_auto_app"

const val BOOLEAN_KEY_ENABLE_ON_CLICK = "enable_onclick"
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
package com.mapbox.maps.testapp.auto.app

import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SwitchCompat
import com.mapbox.maps.testapp.auto.CarAppPreferences
import com.mapbox.maps.testapp.auto.R

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val switchButton: SwitchCompat = findViewById(R.id.switchButton)

val carAppPreferences = CarAppPreferences(applicationContext)
switchButton.isChecked = carAppPreferences.isOnClickEnabled()
switchButton.setOnCheckedChangeListener { _, isChecked ->
if (carAppPreferences.isOnClickEnabled() != isChecked) {
Toast.makeText(
this,
"Custom setting changed, reconnect Android Auto to ensure a restart",
Toast.LENGTH_LONG
).show()
carAppPreferences.enableOnClick(isChecked)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
14 changes: 13 additions & 1 deletion android-auto-app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,25 @@
tools:context=".app.MainActivity">

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Android Auto testing activity"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="Android Auto testing activity"
tools:ignore="HardcodedText" />

<androidx.appcompat.widget.SwitchCompat
android:id="@+id/switchButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enable onClick"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:ignore="HardcodedText"/>

</androidx.constraintlayout.widget.ConstraintLayout>
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/Project.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit 2f0dc6f

Please sign in to comment.