(R.id.textViewSecondLocation).text = "Location 2 is supported in StreetView: $response2"
}
diff --git a/demo/src/main/java/com/google/maps/android/utils/demo/StreetViewDemoJavaActivity.java b/demo/src/main/java/com/google/maps/android/utils/demo/StreetViewDemoJavaActivity.java
new file mode 100644
index 000000000..2260dca4f
--- /dev/null
+++ b/demo/src/main/java/com/google/maps/android/utils/demo/StreetViewDemoJavaActivity.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2025 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.utils.demo;
+
+import android.annotation.SuppressLint;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.graphics.Insets;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowCompat;
+import androidx.core.view.WindowInsetsCompat;
+
+import com.google.android.gms.maps.model.LatLng;
+import com.google.maps.android.Status;
+import com.google.maps.android.StreetViewJavaHelper;
+
+/**
+ * An activity that demonstrates how to use the Street View utility in Java to check for Street View
+ * availability at different locations.
+ *
+ * This activity performs the following actions:
+ * 1. Sets up the layout to fit system windows.
+ * 2. Checks if a valid Google Maps API key is present.
+ * 3. Fetches Street View data for two predefined locations using asynchronous callbacks.
+ * 4. Displays the results of the Street View data fetch on the screen.
+ */
+public class StreetViewDemoJavaActivity extends AppCompatActivity {
+
+ @SuppressLint("SetTextI18n")
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // Make the activity content fit behind the system bars.
+ WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
+ setContentView(R.layout.street_view_demo);
+
+ // Apply window insets to the main view to avoid content overlapping with system bars.
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insetsCompat) -> {
+ Insets insets = insetsCompat.getInsets(WindowInsetsCompat.Type.systemBars());
+ v.setPadding(insets.left, insets.top, insets.right, insets.bottom);
+ return insetsCompat;
+ });
+
+ // Check for a valid Maps API key before proceeding.
+ if (!ApiKeyValidator.hasMapsApiKey(this)) {
+ Toast.makeText(this, R.string.bad_maps_api_key, Toast.LENGTH_LONG).show();
+ finish();
+ return; // Return early to prevent further execution
+ }
+
+ // Fetches Street View data for the first location (expected to be supported).
+ StreetViewJavaHelper.fetchStreetViewData(
+ new LatLng(48.1425918, 11.5386121),
+ BuildConfig.MAPS_API_KEY, new StreetViewJavaHelper.StreetViewCallback() {
+ @Override
+ public void onStreetViewResult(@NonNull Status status) {
+ // Updates the UI with the result on the UI thread.
+ runOnUiThread(() -> ((TextView) findViewById(R.id.textViewFirstLocation)).setText("Location 1 is supported in StreetView: " + status));
+ }
+
+ @Override
+ public void onStreetViewError(@NonNull Exception e) {
+ // Handles the error by printing stack trace and showing a toast.
+ Log.w("SVJDemo", "Error fetching Street View data: " + e.getMessage());
+ Toast.makeText(StreetViewDemoJavaActivity.this, "Error fetching Street View data: " + e.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ // Fetches Street View data for the second location (expected to be unsupported).
+ StreetViewJavaHelper.fetchStreetViewData(new LatLng(8.1425918, 11.5386121), BuildConfig.MAPS_API_KEY, new StreetViewJavaHelper.StreetViewCallback() {
+ @Override
+ public void onStreetViewResult(@NonNull Status status) {
+ // Updates the UI with the result on the UI thread.
+ runOnUiThread(() -> ((TextView) findViewById(R.id.textViewSecondLocation)).setText("Location 2 is supported in StreetView: " + status));
+ }
+
+ @Override
+ public void onStreetViewError(@NonNull Exception e) {
+ // Handles the error by printing stack trace and showing a toast.
+ Log.w("SVJDemo", "Error fetching Street View data: " + e.getMessage());
+ Toast.makeText(StreetViewDemoJavaActivity.this, "Error fetching Street View data: " + e.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/demo/src/main/res/layout/street_view_demo.xml b/demo/src/main/res/layout/street_view_demo.xml
index df7b93a39..5a948f6ca 100644
--- a/demo/src/main/res/layout/street_view_demo.xml
+++ b/demo/src/main/res/layout/street_view_demo.xml
@@ -16,6 +16,7 @@
-->
diff --git a/demo/src/main/res/values/strings.xml b/demo/src/main/res/values/strings.xml
index f910616d2..a0c3d7efb 100644
--- a/demo/src/main/res/values/strings.xml
+++ b/demo/src/main/res/values/strings.xml
@@ -33,5 +33,5 @@
Radius
Gradient
Opacity
- Invalid or missing Google Maps API key
+ The Google Maps API key looks invalid or is missing. If you are sure your key is correct, you can remove this check from the demo.
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 376ce95d1..f08d27766 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -35,6 +35,7 @@ lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx
kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
+kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
junit = { module = "junit:junit", version.ref = "junit" }
mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito-core" }
secrets-gradle-plugin = { module = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin", version.ref = "secrets-gradle-plugin" }
diff --git a/library/build.gradle.kts b/library/build.gradle.kts
index 5b1f841a4..dd4edcc74 100644
--- a/library/build.gradle.kts
+++ b/library/build.gradle.kts
@@ -71,6 +71,10 @@ dependencies {
testImplementation(libs.kotlin.test)
testImplementation(libs.truth)
implementation(libs.kotlin.stdlib.jdk8)
+
+ testImplementation(libs.mockk)
+ testImplementation(libs.kotlinx.coroutines.test)
+ testImplementation(libs.robolectric)
}
tasks.register("instrumentTest") {
diff --git a/library/src/main/java/com/google/maps/android/StreetViewJavaHelper.kt b/library/src/main/java/com/google/maps/android/StreetViewJavaHelper.kt
new file mode 100644
index 000000000..0816a6a2e
--- /dev/null
+++ b/library/src/main/java/com/google/maps/android/StreetViewJavaHelper.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2025 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
+
+import com.google.android.gms.maps.model.LatLng
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+/**
+ * A helper object to call the suspend function `fetchStreetViewData` from Java.
+ */
+object StreetViewJavaHelper {
+ /**
+ * A callback interface to receive the result of the Street View data fetch.
+ */
+ interface StreetViewCallback {
+ /**
+ * Called when the Street View data is fetched successfully.
+ *
+ * @param status The status of the Street View data.
+ */
+ fun onStreetViewResult(status: Status)
+
+ /**
+ * Called when there is an error fetching the Street View data.
+ *
+ * @param e The exception that occurred.
+ */
+ fun onStreetViewError(e: Exception)
+ }
+
+ /**
+ * Fetches Street View data for the given location and returns the result via a callback.
+ *
+ * @param latLng The location to fetch Street View data for.
+ * @param apiKey The API key to use for the request.
+ * @param callback The callback to receive the result.
+ */
+ @JvmStatic
+ fun fetchStreetViewData(latLng: LatLng, apiKey: String, callback: StreetViewCallback) {
+ CoroutineScope(Dispatchers.Main).launch {
+ try {
+ val status = StreetViewUtils.fetchStreetViewData(latLng, apiKey)
+ callback.onStreetViewResult(status)
+ } catch (e: Exception) {
+ callback.onStreetViewError(e)
+ }
+ }
+ }
+}
diff --git a/library/src/test/java/com/google/maps/android/StreetViewHelperTest.kt b/library/src/test/java/com/google/maps/android/StreetViewHelperTest.kt
new file mode 100644
index 000000000..9071e7640
--- /dev/null
+++ b/library/src/test/java/com/google/maps/android/StreetViewHelperTest.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2025 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
+
+import com.google.android.gms.maps.model.LatLng
+import io.mockk.coEvery
+import io.mockk.mockk
+import io.mockk.mockkObject
+import io.mockk.verify
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+/**
+ * Tests for [StreetViewJavaHelper].
+ */
+@ExperimentalCoroutinesApi
+@RunWith(RobolectricTestRunner::class)
+class StreetViewHelperTest {
+
+ private val testDispatcher = StandardTestDispatcher()
+
+ @Before
+ fun setUp() {
+ Dispatchers.setMain(testDispatcher)
+ mockkObject(StreetViewUtils)
+ }
+
+ @After
+ fun tearDown() {
+ Dispatchers.resetMain()
+ }
+
+ /**
+ * Tests that [StreetViewJavaHelper.fetchStreetViewData] calls the onStreetViewResult callback with the OK status when the call is successful.
+ */
+ @Test
+ fun `fetchStreetViewData should call onStreetViewResult with OK status`() = runTest {
+ // Arrange
+ val latLng = LatLng(1.0, 2.0)
+ val apiKey = "some_api_key"
+ val callback = mockk(relaxed = true)
+ coEvery { StreetViewUtils.fetchStreetViewData(latLng, apiKey) } returns Status.OK
+
+ // Act
+ StreetViewJavaHelper.fetchStreetViewData(latLng, apiKey, callback)
+ testDispatcher.scheduler.advanceUntilIdle()
+
+ // Assert
+ verify { callback.onStreetViewResult(Status.OK) }
+ }
+
+ /**
+ * Tests that [StreetViewJavaHelper.fetchStreetViewData] calls the onStreetViewError callback when an exception occurs.
+ */
+ @Test
+ fun `fetchStreetViewData should call onStreetViewError when an exception occurs`() = runTest {
+ // Arrange
+ val latLng = LatLng(1.0, 2.0)
+ val apiKey = "some_api_key"
+ val callback = mockk(relaxed = true)
+ val exception = Exception("some_error")
+ coEvery { StreetViewUtils.fetchStreetViewData(latLng, apiKey) } throws exception
+
+ // Act
+ StreetViewJavaHelper.fetchStreetViewData(latLng, apiKey, callback)
+ testDispatcher.scheduler.advanceUntilIdle()
+
+ // Assert
+ verify { callback.onStreetViewError(exception) }
+ }
+}
\ No newline at end of file
From 49c06c7a219e6665a6bd53bed85ae02a7e3c0e15 Mon Sep 17 00:00:00 2001
From: semantic-release-bot
Date: Wed, 10 Sep 2025 17:34:46 +0000
Subject: [PATCH 3/3] chore(release): 3.17.0 [skip ci]
# [3.17.0](https://github.com/googlemaps/android-maps-utils/compare/v3.16.2...v3.17.0) (2025-09-10)
### Features
* **demo:** Add StreetViewJavaHelper and demo and enable edge-to-edge ([#1595](https://github.com/googlemaps/android-maps-utils/issues/1595)) ([23a4bb5](https://github.com/googlemaps/android-maps-utils/commit/23a4bb58229d0f81733afc1a42377e9d60f29f16))
---
README.md | 2 +-
build.gradle.kts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 5a9afab6f..a66e9537f 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ dependencies {
// Utilities for Maps SDK for Android (requires Google Play Services)
// You do not need to add a separate dependency for the Maps SDK for Android
// since this library builds in the compatible version of the Maps SDK.
- implementation 'com.google.maps.android:android-maps-utils:3.16.2'
+ implementation 'com.google.maps.android:android-maps-utils:3.17.0'
// Optionally add the Kotlin Extensions (KTX) for full Kotlin language support
// See latest version at https://github.com/googlemaps/android-maps-ktx
diff --git a/build.gradle.kts b/build.gradle.kts
index 85a3ddc19..640f47758 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -37,5 +37,5 @@ tasks.register("clean") {
allprojects {
group = "com.google.maps.android"
- version = "3.16.2"
+ version = "3.17.0"
}
\ No newline at end of file