Skip to content

Commit

Permalink
support Google Maps as map provider on Android Auto
Browse files Browse the repository at this point in the history
  • Loading branch information
johan12345 committed Aug 11, 2024
1 parent ca0e8ca commit 5808198
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 26 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ dependencies {
automotiveImplementation("androidx.car.app:app-automotive:$carAppVersion")

// AnyMaps
val anyMapsVersion = "cf24eb00fa"
val anyMapsVersion = "010de4e275"
implementation("com.github.ev-map.AnyMaps:anymaps-base:$anyMapsVersion")
googleImplementation("com.github.ev-map.AnyMaps:anymaps-google:$anyMapsVersion")
googleImplementation("com.google.android.gms:play-services-maps:19.0.0")
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/net/vonforst/evmap/auto/CarAppService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import androidx.core.location.LocationListenerCompat
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.car2go.maps.model.LatLng
import net.vonforst.evmap.BuildConfig
import net.vonforst.evmap.R
import net.vonforst.evmap.autocomplete.PlaceWithBounds
import net.vonforst.evmap.location.FusionEngine
Expand Down Expand Up @@ -126,8 +127,7 @@ class EVMapSession(val cas: CarAppService) : Session(), DefaultLifecycleObserver
}

override fun onCreateScreen(intent: Intent): Screen {
val mapScreen =
if (carContext.carAppApiLevel >= 7 && carContext.isAppDrivenRefreshSupported) {
val mapScreen = if (supportsNewMapScreen(carContext)) {
MapScreen(carContext, this)
} else {
LegacyMapScreen(carContext, this)
Expand Down
38 changes: 29 additions & 9 deletions app/src/main/java/net/vonforst/evmap/auto/MapSurfaceCallback.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ import com.car2go.maps.AnyMap
import com.car2go.maps.AnyMap.CancelableCallback
import com.car2go.maps.CameraUpdate
import com.car2go.maps.MapContainerView
import com.car2go.maps.MapFactory
import com.car2go.maps.OnMapReadyCallback
import com.car2go.maps.maplibre.MapView
import com.car2go.maps.maplibre.MapsConfiguration
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.vonforst.evmap.BuildConfig
import net.vonforst.evmap.R
import net.vonforst.evmap.storage.PreferenceDataSource
import kotlin.math.hypot
import kotlin.math.roundToInt
import kotlin.math.roundToLong
Expand All @@ -43,6 +44,8 @@ class MapSurfaceCallback(val ctx: CarContext, val lifecycleScope: LifecycleCorou
"Google/sdk_gcar_x86_64/generic_64bitonly_x86_64:11"
)

private val prefs = PreferenceDataSource(ctx)

private lateinit var virtualDisplay: VirtualDisplay
lateinit var presentation: Presentation
private lateinit var mapView: MapContainerView
Expand Down Expand Up @@ -77,7 +80,11 @@ class MapSurfaceCallback(val ctx: CarContext, val lifecycleScope: LifecycleCorou
VIRTUAL_DISPLAY_NAME,
width,
height,
(surfaceContainer.dpi * 1.5).roundToInt(),
(surfaceContainer.dpi * when (getMapProvider()) {
"mapbox" -> 1.6
"google" -> 1.0
else -> 1.0
}).roundToInt(),
surfaceContainer.surface,
DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
)
Expand All @@ -93,6 +100,11 @@ class MapSurfaceCallback(val ctx: CarContext, val lifecycleScope: LifecycleCorou
mapView.getMapAsync(this)
}

private fun getMapProvider(): String = if (BuildConfig.FLAVOR_automotive == "automotive") {
// Google Maps SDK is not available on AAOS (not even AAOS with GAS, so far)
"mapbox"
} else prefs.mapProvider

override fun onVisibleAreaChanged(visibleArea: Rect) {
Log.d("MapSurfaceCallback", "visible area: $visibleArea")
this.visibleArea = visibleArea
Expand All @@ -117,7 +129,7 @@ class MapSurfaceCallback(val ctx: CarContext, val lifecycleScope: LifecycleCorou
override fun onScroll(distanceX: Float, distanceY: Float) {
flingAnimator?.cancel()
val map = map ?: return
map.moveCamera(map.cameraUpdateFactory.scrollBy(-distanceX, -distanceY))
map.moveCamera(map.cameraUpdateFactory.scrollBy(distanceX, distanceY))
dispatchCameraMoveStarted()
}

Expand Down Expand Up @@ -147,7 +159,7 @@ class MapSurfaceCallback(val ctx: CarContext, val lifecycleScope: LifecycleCorou
var last = 0f
addUpdateListener {
val current = it.animatedFraction
val diff = current - last
val diff = last - current
map.moveCamera(map.cameraUpdateFactory.scrollBy(diff * offsetX, diff * offsetY))
last = current
}
Expand All @@ -163,8 +175,8 @@ class MapSurfaceCallback(val ctx: CarContext, val lifecycleScope: LifecycleCorou
val map = map ?: return
if (scaleFactor == 2f) return

val offsetX = (focusX - mapView.width / 2) * (1f - scaleFactor)
val offsetY = (offsetY(focusY) - mapView.height / 2) * (1f - scaleFactor)
val offsetX = (focusX - mapView.width / 2) * (scaleFactor - 1f)
val offsetY = (offsetY(focusY) - mapView.height / 2) * (scaleFactor - 1f)

Log.i("MapSurfaceCallback", "focus: $focusX, $focusY, scaleFactor: $scaleFactor")
map.moveCamera(map.cameraUpdateFactory.zoomBy(scaleFactor - 1))
Expand Down Expand Up @@ -241,8 +253,16 @@ class MapSurfaceCallback(val ctx: CarContext, val lifecycleScope: LifecycleCorou
}

private fun createMap(ctx: Context): MapContainerView {
MapsConfiguration.getInstance().initialize(ctx)
return MapView(ctx)
val priority = arrayOf(
when (getMapProvider()) {
"mapbox" -> MapFactory.MAPLIBRE
"google" -> MapFactory.GOOGLE
else -> null
},
MapFactory.GOOGLE,
MapFactory.MAPLIBRE
)
return MapFactory.createMap(ctx, priority).view
}

override fun onMapReady(anyMap: AnyMap) {
Expand Down
53 changes: 44 additions & 9 deletions app/src/main/java/net/vonforst/evmap/auto/SettingsScreens.kt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ class DataSettingsScreen(ctx: CarContext) : Screen(ctx) {
carContext.resources.getStringArray(R.array.pref_search_provider_names)
val searchProviderValues =
carContext.resources.getStringArray(R.array.pref_search_provider_values)
val mapProviderNames =
carContext.resources.getStringArray(R.array.pref_map_provider_names)
val mapProviderValues =
carContext.resources.getStringArray(R.array.pref_map_provider_values)

var teslaLoggingIn = false

Expand Down Expand Up @@ -206,6 +210,25 @@ class DataSettingsScreen(ctx: CarContext) : Screen(ctx) {
)
}
}.build())
if (supportsNewMapScreen(carContext) && BuildConfig.FLAVOR_automotive != "automotive") {
// Google Maps SDK is not available on AAOS (not even AAOS with GAS, so far)
addItem(Row.Builder().apply {
setTitle(carContext.getString(R.string.pref_map_provider))
setBrowsable(true)
val mapProviderId = prefs.mapProvider
val mapProviderDesc =
mapProviderNames[mapProviderValues.indexOf(mapProviderId)]
addText(mapProviderDesc)
setOnClickListener {
screenManager.push(
ChooseDataSourceScreen(
carContext,
ChooseDataSourceScreen.Type.MAP_PROVIDER
)
)
}
}.build())
}
addItem(Row.Builder().apply {
setTitle(carContext.getString(R.string.pref_search_delete_recent))
setOnClickListener {
Expand Down Expand Up @@ -344,32 +367,41 @@ class ChooseDataSourceScreen(
@StringRes val extraDesc: Int? = null
) : Screen(ctx) {
enum class Type {
CHARGER_DATA_SOURCE, SEARCH_PROVIDER
CHARGER_DATA_SOURCE, SEARCH_PROVIDER, MAP_PROVIDER
}

val prefs = PreferenceDataSource(carContext)
val title = when (type) {
Type.CHARGER_DATA_SOURCE -> R.string.pref_data_source
Type.SEARCH_PROVIDER -> R.string.pref_search_provider
Type.MAP_PROVIDER -> R.string.pref_map_provider
}
val names = when (type) {
Type.CHARGER_DATA_SOURCE -> carContext.resources.getStringArray(R.array.pref_data_source_names)
Type.SEARCH_PROVIDER -> carContext.resources.getStringArray(R.array.pref_search_provider_names)
}
val values = when (type) {
Type.CHARGER_DATA_SOURCE -> carContext.resources.getStringArray(R.array.pref_data_source_values)
Type.SEARCH_PROVIDER -> carContext.resources.getStringArray(R.array.pref_search_provider_values)
}
val names = carContext.resources.getStringArray(
when (type) {
Type.CHARGER_DATA_SOURCE -> R.array.pref_data_source_names
Type.SEARCH_PROVIDER -> R.array.pref_search_provider_names
Type.MAP_PROVIDER -> R.array.pref_map_provider_names
}
)
val values = carContext.resources.getStringArray(
when (type) {
Type.CHARGER_DATA_SOURCE -> R.array.pref_data_source_values
Type.SEARCH_PROVIDER -> R.array.pref_search_provider_values
Type.MAP_PROVIDER -> R.array.pref_map_provider_values
}
)
val currentValue: String = when (type) {
Type.CHARGER_DATA_SOURCE -> prefs.dataSource
Type.SEARCH_PROVIDER -> prefs.searchProvider
Type.MAP_PROVIDER -> prefs.mapProvider
}
val descriptions = when (type) {
Type.CHARGER_DATA_SOURCE -> listOf(
carContext.getString(R.string.data_source_goingelectric_desc),
carContext.getString(R.string.data_source_openchargemap_desc)
)
Type.SEARCH_PROVIDER -> null
Type.MAP_PROVIDER -> null
}
val callback: (String) -> Unit = when (type) {
Type.CHARGER_DATA_SOURCE -> { it ->
Expand All @@ -379,6 +411,9 @@ class ChooseDataSourceScreen(
Type.SEARCH_PROVIDER -> { it ->
prefs.searchProvider = it
}
Type.MAP_PROVIDER -> { it ->
prefs.mapProvider = it
}
}

override fun onGetTemplate(): Template {
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/net/vonforst/evmap/auto/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ fun supportsCarApiLevel3(ctx: CarContext): Boolean {
return true
}

fun supportsNewMapScreen(ctx: CarContext) =
ctx.carAppApiLevel >= 7 && ctx.isAppDrivenRefreshSupported

fun openUrl(carContext: CarContext, url: String) {
val intent = CustomTabsIntent.Builder()
.setDefaultColorSchemeParams(
Expand Down
9 changes: 5 additions & 4 deletions app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import androidx.transition.TransitionManager
import coil.load
import coil.memory.MemoryCache
import com.car2go.maps.AnyMap
import com.car2go.maps.MapFactory
import com.car2go.maps.MapFragment
import com.car2go.maps.OnMapReadyCallback
import com.car2go.maps.model.LatLng
Expand Down Expand Up @@ -200,12 +201,12 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
mapFragment = MapFragment()
mapFragment!!.priority = arrayOf(
when (provider) {
"mapbox" -> MapFragment.MAPLIBRE
"google" -> MapFragment.GOOGLE
"mapbox" -> MapFactory.MAPLIBRE
"google" -> MapFactory.GOOGLE
else -> null
},
MapFragment.GOOGLE,
MapFragment.MAPLIBRE
MapFactory.GOOGLE,
MapFactory.MAPLIBRE
)
childFragmentManager
.beginTransaction()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,14 @@ class PreferenceDataSource(val context: Context) {
val darkmode: String
get() = sp.getString("darkmode", "default")!!

val mapProvider: String
var mapProvider: String
get() = sp.getString(
"map_provider",
context.getString(R.string.pref_map_provider_default)
)!!
set(value) {
sp.edit().putString("map_provider", value).apply()
}

var searchProvider: String
get() = sp.getString(
Expand Down

0 comments on commit 5808198

Please sign in to comment.