Skip to content

Commit 9071521

Browse files
added layers demo and associated files
1 parent 7e367ef commit 9071521

File tree

6 files changed

+322
-2
lines changed

6 files changed

+322
-2
lines changed

ApiDemos/kotlin/app/build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ android {
2222
}
2323
}
2424

25-
2625
dependencies {
2726
implementation fileTree(dir: 'libs', include: ['*.jar'])
2827
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
@@ -33,5 +32,7 @@ dependencies {
3332
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
3433
// Below is the Google Play Services dependency required for using the Google Maps Android API
3534
implementation 'com.google.android.gms:play-services-maps:11.8.0'
36-
35+
// Below is used to run the easypermissions library to manage location permissions
36+
// EasyPermissions is needed to help us request for permission to access location
37+
implementation 'pub.devrel:easypermissions:1.1.1'
3738
}

ApiDemos/kotlin/app/src/main/AndroidManifest.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
1717
package="com.example.kotlindemos">
1818

19+
<!-- This app requires location permissions for the layers demo.
20+
The user's current location is displayed using the 'My Location' layer. -->
21+
<!-- Access to location is needed for the UI Settings Demo -->
22+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
23+
1924
<application
2025
android:allowBackup="true"
2126
android:icon="@mipmap/ic_launcher"
@@ -34,6 +39,7 @@
3439
</intent-filter>
3540
</activity>
3641
<activity android:name=".MarkerDemoActivity"/>
42+
<activity android:name=".LayersDemoActivity"/>
3743
<activity android:name=".PolygonDemoActivity"/>
3844
<activity android:name=".CameraDemoActivity"/>
3945
<activity android:name=".PolylineDemoActivity"/>

ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/DemoDetailsList.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class DemoDetailsList {
2828
CameraDemoActivity::class.java),
2929
DemoDetails(R.string.markers_demo_label, R.string.markers_demo_description,
3030
MarkerDemoActivity::class.java),
31+
DemoDetails(R.string.layers_demo_label, R.string.layers_demo_description,
32+
LayersDemoActivity::class.java),
3133
DemoDetails(R.string.polyline_demo_label, R.string.polyline_demo_description,
3234
PolylineDemoActivity::class.java),
3335
DemoDetails(R.string.tags_demo_label, R.string.tags_demo_details,
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/*
2+
* Copyright 2018 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.kotlindemos
18+
19+
import android.Manifest
20+
import android.annotation.SuppressLint
21+
import android.app.AlertDialog
22+
import android.os.Bundle
23+
import android.support.v7.app.AppCompatActivity
24+
import android.util.Log
25+
import android.view.View
26+
import android.widget.AdapterView
27+
import android.widget.ArrayAdapter
28+
import android.widget.CheckBox
29+
import android.widget.Spinner
30+
import com.google.android.gms.maps.GoogleMap
31+
import com.google.android.gms.maps.GoogleMap.MAP_TYPE_HYBRID
32+
import com.google.android.gms.maps.GoogleMap.MAP_TYPE_NONE
33+
import com.google.android.gms.maps.GoogleMap.MAP_TYPE_NORMAL
34+
import com.google.android.gms.maps.GoogleMap.MAP_TYPE_SATELLITE
35+
import com.google.android.gms.maps.GoogleMap.MAP_TYPE_TERRAIN
36+
import com.google.android.gms.maps.OnMapReadyCallback
37+
import com.google.android.gms.maps.SupportMapFragment
38+
import pub.devrel.easypermissions.AfterPermissionGranted
39+
import pub.devrel.easypermissions.EasyPermissions
40+
41+
private const val LOCATION_PERMISSION_REQUEST_CODE = 1
42+
43+
/**
44+
* Demonstrates the different base layers of a map.
45+
*/
46+
class LayersDemoActivity :
47+
AppCompatActivity(),
48+
OnMapReadyCallback,
49+
AdapterView.OnItemSelectedListener,
50+
EasyPermissions.PermissionCallbacks {
51+
52+
private val TAG = MarkerDemoActivity::class.java.name
53+
54+
private lateinit var map: GoogleMap
55+
56+
private lateinit var trafficCheckbox: CheckBox
57+
private lateinit var myLocationCheckbox: CheckBox
58+
private lateinit var buildingsCheckbox: CheckBox
59+
private lateinit var indoorCheckbox: CheckBox
60+
private lateinit var spinner: Spinner
61+
62+
/**
63+
* Flag indicating whether a requested permission has been denied after returning in
64+
* [.onRequestPermissionsResult].
65+
*/
66+
private var showPermissionDeniedDialog = false
67+
68+
override fun onCreate(savedInstanceState: Bundle?) {
69+
super.onCreate(savedInstanceState)
70+
setContentView(R.layout.layers_demo)
71+
72+
spinner = findViewById<Spinner>(R.id.layers_spinner).apply {
73+
adapter = ArrayAdapter.createFromResource(this@LayersDemoActivity,
74+
R.array.layers_array, android.R.layout.simple_spinner_item).apply {
75+
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
76+
}
77+
78+
// set a listener for when the spinner to select map type is changed.
79+
onItemSelectedListener = this@LayersDemoActivity
80+
}
81+
82+
myLocationCheckbox = findViewById(R.id.my_location)
83+
buildingsCheckbox = findViewById(R.id.buildings)
84+
indoorCheckbox = findViewById(R.id.indoor)
85+
trafficCheckbox = findViewById(R.id.traffic)
86+
87+
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
88+
mapFragment.getMapAsync(this)
89+
}
90+
91+
/**
92+
* Display a dialog box asking the user to grant permissions if they were denied
93+
*/
94+
override fun onResumeFragments() {
95+
super.onResumeFragments()
96+
if (showPermissionDeniedDialog) {
97+
AlertDialog.Builder(this).apply {
98+
setPositiveButton(R.string.ok, null)
99+
setMessage(R.string.location_permission_denied)
100+
create()
101+
}.show()
102+
showPermissionDeniedDialog = false
103+
}
104+
}
105+
106+
@SuppressLint("MissingPermission")
107+
override fun onMapReady(googleMap: GoogleMap?) {
108+
109+
// exit early if the map was not initialised properly
110+
map = googleMap ?: return
111+
112+
updateMapType()
113+
114+
// check the state of all checkboxes and update the map accordingly
115+
with(map) {
116+
isTrafficEnabled = trafficCheckbox.isChecked
117+
isBuildingsEnabled = buildingsCheckbox.isChecked
118+
isIndoorEnabled = indoorCheckbox.isChecked
119+
}
120+
121+
// Must deal with the location checkbox separately as must check that
122+
// location permission have been granted before enabling the 'My Location' layer.
123+
if (myLocationCheckbox.isChecked) enableMyLocation()
124+
125+
126+
// attach a listener to each checkbox
127+
trafficCheckbox.setOnClickListener { map.isTrafficEnabled = trafficCheckbox.isChecked }
128+
129+
buildingsCheckbox.setOnClickListener {
130+
map.isBuildingsEnabled = buildingsCheckbox.isChecked
131+
}
132+
133+
indoorCheckbox.setOnClickListener { map.isIndoorEnabled = indoorCheckbox.isChecked }
134+
135+
// if this box is checked, must check for permission before enabling the My Location layer
136+
myLocationCheckbox.setOnClickListener {
137+
if (!myLocationCheckbox.isChecked) {
138+
map.isMyLocationEnabled = false
139+
} else {
140+
enableMyLocation()
141+
}
142+
}
143+
}
144+
145+
@SuppressLint("MissingPermission")
146+
@AfterPermissionGranted(LOCATION_PERMISSION_REQUEST_CODE)
147+
private fun enableMyLocation() {
148+
// Enable the location layer. Request the location permission if needed.
149+
val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
150+
151+
if (EasyPermissions.hasPermissions(this, *permissions)) {
152+
map.isMyLocationEnabled = true
153+
154+
} else {
155+
// if permissions are not currently granted, request permissions
156+
EasyPermissions.requestPermissions(this,
157+
getString(R.string.permission_rationale_location),
158+
LOCATION_PERMISSION_REQUEST_CODE, *permissions)
159+
}
160+
}
161+
162+
/**
163+
* Change the type of the map depending on the currently selected item in the spinner
164+
*/
165+
private fun updateMapType() {
166+
// This can also be called by the Android framework in onCreate() at which
167+
// point map may not be ready yet.
168+
if (!::map.isInitialized) return
169+
170+
map.mapType = when (spinner.selectedItem) {
171+
getString(R.string.normal) -> MAP_TYPE_NORMAL
172+
getString(R.string.hybrid) -> MAP_TYPE_HYBRID
173+
getString(R.string.satellite) -> MAP_TYPE_SATELLITE
174+
getString(R.string.terrain) -> MAP_TYPE_TERRAIN
175+
getString(R.string.none_map) -> MAP_TYPE_NONE
176+
else -> {
177+
map.mapType // do not change map type
178+
Log.e(TAG, "Error setting layer with name ${spinner.selectedItem}")
179+
}
180+
}
181+
}
182+
183+
override fun onRequestPermissionsResult(
184+
requestCode: Int,
185+
permissions: Array<String>,
186+
grantResults: IntArray
187+
) {
188+
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
189+
EasyPermissions.onRequestPermissionsResult(requestCode,
190+
permissions, grantResults, this)
191+
}
192+
193+
override fun onPermissionsDenied(requestCode: Int, list: List<String>) {
194+
// Un-check the box until the layer has been enabled
195+
// and show dialog box with permission rationale.
196+
myLocationCheckbox.isChecked = false
197+
showPermissionDeniedDialog = true
198+
}
199+
200+
override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
201+
// do nothing, handled in updateMyLocation
202+
}
203+
204+
/**
205+
* Called as part of the AdapterView.OnItemSelectedListener
206+
*/
207+
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
208+
updateMapType()
209+
}
210+
211+
override fun onNothingSelected(parent: AdapterView<*>) {
212+
// Do nothing.
213+
}
214+
215+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
Copyright (C) 2012 The Android Open Source Project
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
17+
android:layout_width="match_parent"
18+
android:layout_height="match_parent">
19+
20+
<fragment
21+
android:id="@+id/map"
22+
android:layout_width="match_parent"
23+
android:layout_height="match_parent"
24+
class="com.google.android.gms.maps.SupportMapFragment" />
25+
26+
<!-- A set of test checkboxes. -->
27+
<LinearLayout
28+
android:layout_width="wrap_content"
29+
android:layout_height="wrap_content"
30+
android:layout_alignParentLeft="true"
31+
android:layout_alignParentStart="true"
32+
android:layout_alignTop="@id/map"
33+
android:padding="6dp"
34+
android:background="@color/white"
35+
android:orientation="vertical">
36+
37+
<Spinner
38+
android:id="@+id/layers_spinner"
39+
android:layout_width="match_parent"
40+
android:layout_height="wrap_content" />
41+
42+
<CheckBox
43+
android:id="@+id/traffic"
44+
android:layout_width="wrap_content"
45+
android:layout_height="wrap_content"
46+
android:checked="false"
47+
android:text="@string/traffic" />
48+
49+
<CheckBox
50+
android:id="@+id/my_location"
51+
android:layout_width="wrap_content"
52+
android:layout_height="wrap_content"
53+
android:checked="false"
54+
android:text="@string/my_location" />
55+
56+
<CheckBox
57+
android:id="@+id/buildings"
58+
android:layout_width="wrap_content"
59+
android:layout_height="wrap_content"
60+
android:checked="true"
61+
android:text="@string/buildings" />
62+
63+
<CheckBox
64+
android:id="@+id/indoor"
65+
android:layout_width="wrap_content"
66+
android:layout_height="wrap_content"
67+
android:checked="true"
68+
android:text="@string/indoor" />
69+
</LinearLayout>
70+
</RelativeLayout>

ApiDemos/kotlin/app/src/main/res/values/strings.xml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,32 @@
7979
<string name="rotation">Rotation</string>
8080
<string name="state_badge_label">State badge</string>
8181

82+
<!-- Layers Demo -->
83+
<string name="buildings">Buildings</string>
84+
<string name="hybrid">Hybrid</string>
85+
<string name="indoor">Indoor</string>
86+
<string-array name="layers_array">
87+
<item>@string/normal</item>
88+
<item>@string/hybrid</item>
89+
<item>@string/satellite</item>
90+
<item>@string/terrain</item>
91+
<item>@string/none_map</item>
92+
</string-array>
93+
<string name="layers_demo_label">Layers</string>
94+
<string name="layers_demo_description">Demonstrates the different map layers.</string>
95+
<string name="my_location">My Location</string>
96+
<string name="none_map">None</string>
97+
<string name="normal">Normal</string>
98+
<string name="ok">OK</string>
99+
<string name="satellite">Satellite</string>
100+
<string name="terrain">Terrain</string>
101+
<string name="traffic">Traffic</string>
102+
103+
<!-- Permissions -->
104+
<string name="permission_rationale_location">Access to the location service is required to demonstrate the \'my location\' feature, which shows your current location on the map.</string>
105+
<string name="location_permission_denied">This sample requires location permission to enable the \'my location\' layer. Please try again and grant access to use the location.\nIf the permission has been permanently denied, it can be enabled from the System Settings &gt; Apps &gt; \'Google Maps API Demos\'.</string>
106+
<string name="permission_required_toast">Location permission is required for this demo.</string>
107+
82108
<!-- Polylines Demo -->
83109
<string name="alpha">Alpha</string>
84110
<string name="cap_butt">Butt</string>

0 commit comments

Comments
 (0)