Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added StreetViewUtil #1200

Merged
merged 4 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ range of applications using the [Google Maps SDK for Android][android-site].
computeArea
- **KML** — displays KML data
- **GeoJSON** — displays and styles GeoJSON data
- **StreetView Utility** — checks if a given StreetView location exists

<p align="center"><img width="90%" vspace="20" src="https://cloud.githubusercontent.com/assets/1950036/6629704/f57bc6d8-c908-11e4-815a-0d909fe02f99.gif"></p>

Expand Down Expand Up @@ -289,6 +290,20 @@ _Old_

</details>

## Usage guide

The full documentation can be found here [Google Maps Platform documentation][devsite-guide].

For a quick snippet on the StreetViewUtil class, keep reading.

The StreetViewUtil class provides functionality to check whether a location is supported in StreetView. To call it, use the following snippet:

```kotlin
StreetViewUtils.fetchStreetViewData(LatLng(8.1425918, 11.5386121), BuildConfig.MAPS_API_KEY)
```

`fetchStreetViewData` will return `NOT_FOUND`, `OK` or `ZERO_RESULTS`, depending on the response.

## Support

Encounter an issue while using this library?
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ buildscript {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath 'com.hiya:jacoco-android:0.2'
classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0"
}
}

Expand Down
6 changes: 5 additions & 1 deletion demo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0-alpha01'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.0'

// [END_EXCLUDE]
}
// [END maps_android_utils_install_snippet]
Expand Down
1 change: 1 addition & 0 deletions demo/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
<activity android:name=".KmlDemoActivity" />
<activity android:name=".MultiLayerDemoActivity" />
<activity android:name=".AnimationUtilDemoActivity" />
<activity android:name=".StreetViewDemoActivity" />

</application>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2013 Google Inc.
* Copyright 2023 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -57,6 +57,7 @@ protected void onCreate(Bundle savedInstanceState) {
addDemo("KML Layer Overlay", KmlDemoActivity.class);
addDemo("Multi Layer", MultiLayerDemoActivity.class);
addDemo("AnimationUtil sample", AnimationUtilDemoActivity.class);
addDemo("Street View Demo", StreetViewDemoActivity.class);
}

private void addDemo(String demoName, Class<? extends Activity> activityClass) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.google.maps.android.utils.demo

import android.app.Activity
import android.os.Bundle
import android.widget.TextView
import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.StreetViewUtils
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

class StreetViewDemoActivity : Activity() {

@OptIn(DelicateCoroutinesApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.street_view_demo)

GlobalScope.launch(Dispatchers.Main) {
val response1 =
StreetViewUtils.fetchStreetViewData(LatLng(48.1425918, 11.5386121), BuildConfig.MAPS_API_KEY)
val response2 = StreetViewUtils.fetchStreetViewData(LatLng(8.1425918, 11.5386121), BuildConfig.MAPS_API_KEY)

findViewById<TextView>(R.id.textViewFirstLocation).text = "Location 1 is supported in StreetView: $response1"
findViewById<TextView>(R.id.textViewSecondLocation).text = "Location 2 is supported in StreetView: $response2"
}
}
}

15 changes: 15 additions & 0 deletions demo/src/main/res/layout/street_view_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/textViewFirstLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textViewSecondLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
6 changes: 5 additions & 1 deletion library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
plugins {
id 'kotlin-android'
id 'org.jetbrains.kotlin.android'
}

android {
Expand Down Expand Up @@ -56,11 +57,14 @@ android {

dependencies {
implementation 'com.google.android.gms:play-services-maps:18.1.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.core:core-ktx:1.10.1'
lintPublish project(':lint-checks')
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.7.3'
testImplementation 'org.robolectric:robolectric:4.10.3'
testImplementation 'net.sf.kxml:kxml2:2.3.0'
testImplementation "io.mockk:mockk:1.13.4"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}

Expand Down
86 changes: 86 additions & 0 deletions library/src/main/java/com/google/maps/android/StreetViewUtil.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright 2023 Google Inc.
*
* 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 kotlinx.coroutines.withContext
import java.io.IOException
import java.net.HttpURLConnection
import java.net.URL
import com.google.android.gms.maps.model.LatLng
import kotlinx.coroutines.Dispatchers
import org.json.JSONObject
import java.io.BufferedReader
import java.io.InputStreamReader


/**
* Utility functions for StreetView
*/
class StreetViewUtils {
companion object {

/**
* This function will check whether a location is available on StreetView or not.
*
* @param latLng Location to check
* @param apiKey Maps API Key
* @return A boolean value specifying if the location is available on Street View or not.
*/
suspend fun fetchStreetViewData(latLng: LatLng, apiKey: String): Status {
val urlString =
"https://maps.googleapis.com/maps/api/streetview/metadata?location=${latLng.latitude},${latLng.longitude}&key=$apiKey"

return withContext(Dispatchers.IO) {
try {
val url = URL(urlString)
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "GET"

val responseCode = connection.responseCode
if (responseCode == HttpURLConnection.HTTP_OK) {
val inputStream = connection.inputStream
val bufferedReader = BufferedReader(InputStreamReader(inputStream))
val responseString = bufferedReader.use { it.readText() }
bufferedReader.close()
inputStream.close()
deserializeResponse(responseString).status
} else {
throw IOException("HTTP Error: $responseCode")
}
} catch (e: IOException) {
e.printStackTrace()
throw IOException("Network error: ${e.message}")
}
}
}

private fun deserializeResponse(responseString: String): ResponseStreetView {
val jsonObject = JSONObject(responseString)
val statusString = jsonObject.optString("status")
val status = Status.valueOf(statusString)

return ResponseStreetView(status)
}
}
}

data class ResponseStreetView(val status: Status)

enum class Status {
OK,
ZERO_RESULTS,
NOT_FOUND
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.google.maps.android

import com.google.android.gms.maps.model.LatLng
import io.mockk.coEvery
import io.mockk.mockkObject
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test

class StreetViewUtilsTest {

lateinit var latLng : LatLng

val apiKey = "AN_API_KEY"

@Before
fun setUp() {
latLng = LatLng(37.7749, -122.4194) // San Francisco coordinates

// Mock the network behavior using MockK
mockkObject(StreetViewUtils)
coEvery { StreetViewUtils.fetchStreetViewData(any(), any()) } returns Status.NOT_FOUND
coEvery { StreetViewUtils.fetchStreetViewData(latLng, apiKey) } returns Status.OK
}

@Test
fun testLocationFoundOnStreetView() = runBlocking {
val status = StreetViewUtils.fetchStreetViewData(latLng, apiKey)
assertEquals(Status.OK, status)
}

@Test
fun testLocationNotFoundOnStreetView() = runBlocking {
val status = StreetViewUtils.fetchStreetViewData(LatLng(10.0, 20.0), apiKey)
assertEquals(Status.NOT_FOUND, status)
}
}

2 changes: 1 addition & 1 deletion local.defaults.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
MAPS_API_KEY="YOUR_API_KEY"
MAPS_API_KEY="AIzaSyA4SCF8hbjd5M3pq-FncAtSu1uTe_yaQBg"
Loading