diff --git a/README.md b/README.md index e31848ce6..2109f442d 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,9 @@ You no longer need to specify the Maps SDK for Android or its Utility Library as ```groovy dependencies { implementation 'com.google.maps.android:maps-compose:3.1.1' - - // Optionally, you can include the Compose utils library for Clustering, etc. + + // Optionally, you can include the Compose utils library for Clustering, + // Street View metadata checks, etc. implementation 'com.google.maps.android:maps-compose-utils:3.1.1' // Optionally, you can include the widgets library for ScaleBar, etc. @@ -230,7 +231,16 @@ MarkerInfoWindow( ### Street View You can add a Street View given a location using the `StreetView` composable. -To use it, provide a `StreetViewPanoramaOptions` object as follows: + +1. Test whether a Street View location is valid with the the +`fetchStreetViewData` utility from the [`maps-compose-utils` library](#maps-compose-utility-library). + +```kotlin + streetViewResult = + fetchStreetViewData(singapore, BuildConfig.MAPS_API_KEY) +``` + +2. Once the location is confirmed valid, add a Street View composable by providing a `StreetViewPanoramaOptions` object. ```kotlin val singapore = LatLng(1.3588227, 103.8742114) @@ -264,9 +274,9 @@ GoogleMap( -## Utility Library +## Maps Compose Utility Library -This library also provides optional utilities in the `maps-compose-utils` library. +This library provides optional utilities in the `maps-compose-utils` library from the [Maps SDK for Android Utility Library](https://github.com/googlemaps/android-maps-utils). ### Clustering @@ -289,7 +299,22 @@ Clustering( ) ``` -## Widgets +### Street View metadata utility + +The `fetchStreetViewData` method provides functionality to check whether a location is supported in StreetView. You can avoid errors when adding a Street View panorama to an Android app by calling this metadata utility and only adding a Street View panorama if the response is OK. + +> [!IMPORTANT] +> Be sure to [enable Street View Static API](https://goo.gle/enable-sv-static-api) on the project associated with your API key. + +You can see example usage +in the [`StreetViewActivity`](https://github.com/googlemaps/android-maps-compose/blob/main/app/src/main/java/com/google/maps/android/compose/StreetViewActivity.kt) of the demo app: + +```kotlin + streetViewResult = + fetchStreetViewData(singapore, BuildConfig.MAPS_API_KEY) +``` + +## Maps Compose Widgets This library also provides optional composable widgets in the `maps-compose-widgets` library that you can use alongside the `GoogleMap` composable. @@ -304,8 +329,8 @@ The [ScaleBarActivity](app/src/main/java/com/google/maps/android/compose/ScaleBa Both versions of this widget leverage the `CameraPositionState` in `maps-compose` and therefore are very simple to configure with their defaults: ```kotlin -Box(Modifier.fillMaxSize()) { - +Box(Modifier.fillMaxSize()) { + GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState @@ -328,7 +353,7 @@ Box(Modifier.fillMaxSize()) { .align(Alignment.TopStart), cameraPositionState = cameraPositionState ) -} +} ``` The colors of the text, line, and shadow are also all configurable (e.g., based on `isSystemInDarkTheme()` on a dark map). Similarly, the `DisappearingScaleBar` animations can be configured. diff --git a/app/src/main/java/com/google/maps/android/compose/StreetViewActivity.kt b/app/src/main/java/com/google/maps/android/compose/StreetViewActivity.kt index d344318e8..f190b2070 100644 --- a/app/src/main/java/com/google/maps/android/compose/StreetViewActivity.kt +++ b/app/src/main/java/com/google/maps/android/compose/StreetViewActivity.kt @@ -40,21 +40,31 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.google.android.gms.maps.StreetViewPanoramaOptions +import com.google.android.gms.maps.model.LatLng +import com.google.maps.android.Status import com.google.maps.android.compose.streetview.StreetView import com.google.maps.android.compose.streetview.rememberStreetViewCameraPositionState import com.google.maps.android.ktx.MapsExperimentalFeature import kotlinx.coroutines.launch +import com.google.maps.android.StreetViewUtils.Companion.fetchStreetViewData class StreetViewActivity : ComponentActivity() { private val TAG = StreetViewActivity::class.java.simpleName + // This is an invalid location. If you use it instead of Singapore, the StreetViewUtils + // will return NOT_FOUND. + val invalidLocation = LatLng(32.429634, -96.828891) + @OptIn(MapsExperimentalFeature::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setContent { var isPanningEnabled by remember { mutableStateOf(false) } var isZoomEnabled by remember { mutableStateOf(false) } + var streetViewResult by remember { mutableStateOf(Status.NOT_FOUND) } + val camera = rememberStreetViewCameraPositionState() LaunchedEffect(camera) { launch { @@ -69,41 +79,52 @@ class StreetViewActivity : ComponentActivity() { Log.d(TAG, "Location at: $it") } } + launch { + // Be sure to enable the Street View Static API on the project associated with + // this API key using the instructions at https://goo.gle/enable-sv-static-api + streetViewResult = + fetchStreetViewData(singapore, BuildConfig.MAPS_API_KEY) + } } Box(Modifier.fillMaxSize(), Alignment.BottomStart) { - StreetView( - Modifier.matchParentSize(), - cameraPositionState = camera, - streetViewPanoramaOptionsFactory = { - StreetViewPanoramaOptions().position(singapore) - }, - isPanningGesturesEnabled = isPanningEnabled, - isZoomGesturesEnabled = isZoomEnabled, - onClick = { - Log.d(TAG, "Street view clicked") - }, - onLongClick = { - Log.d(TAG, "Street view long clicked") - } - ) - Column( - Modifier - .fillMaxWidth() - .background(Color.White) - .padding(8.dp) - ) { - StreetViewSwitch(title = "Panning", checked = isPanningEnabled) { - isPanningEnabled = it - } - StreetViewSwitch(title = "Zooming", checked = isZoomEnabled) { - isZoomEnabled = it + if (streetViewResult == Status.OK) { + StreetView( + Modifier.matchParentSize(), + cameraPositionState = camera, + streetViewPanoramaOptionsFactory = { + StreetViewPanoramaOptions().position(singapore) + }, + isPanningGesturesEnabled = isPanningEnabled, + isZoomGesturesEnabled = isZoomEnabled, + onClick = { + Log.d(TAG, "Street view clicked") + }, + onLongClick = { + Log.d(TAG, "Street view long clicked") + } + ) + Column( + Modifier + .fillMaxWidth() + .background(Color.White) + .padding(8.dp) + ) { + StreetViewSwitch(title = "Panning", checked = isPanningEnabled) { + isPanningEnabled = it + } + StreetViewSwitch(title = "Zooming", checked = isZoomEnabled) { + isZoomEnabled = it + } } + } else { + Text("Location not available.") } } } } } + @Composable fun StreetViewSwitch(title: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit) { Row(Modifier.padding(4.dp)) { diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/streetview/StreetView.kt b/maps-compose/src/main/java/com/google/maps/android/compose/streetview/StreetView.kt index cc774f4c0..e73c7d53f 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/streetview/StreetView.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/streetview/StreetView.kt @@ -1,3 +1,17 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package com.google.maps.android.compose.streetview import android.content.ComponentCallbacks @@ -23,14 +37,17 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import com.google.android.gms.maps.StreetViewPanoramaOptions import com.google.android.gms.maps.StreetViewPanoramaView -import com.google.android.gms.maps.model.StreetViewPanoramaCamera import com.google.android.gms.maps.model.StreetViewPanoramaOrientation import com.google.maps.android.compose.disposingComposition import com.google.maps.android.ktx.MapsExperimentalFeature import com.google.maps.android.ktx.awaitStreetViewPanorama /** - * A composable for displaying a Street View for a given location. + * A composable for displaying a Street View for a given location. A location might not be available for a given + * set of coordinates. We recommend you to check our sample on [StreetViewActivity] using our utility function + * in [StreetViewUtils] to manage non-existing locations. + * + * * * @param modifier Modifier to be applied to the StreetView * @param cameraPositionState the [StreetViewCameraPositionState] to be used to control or observe