From 90715219bf8604a5bebec4fc594c9af76c84651e Mon Sep 17 00:00:00 2001 From: Katherine Allen Date: Wed, 17 Jan 2018 11:25:30 +1100 Subject: [PATCH] added layers demo and associated files --- ApiDemos/kotlin/app/build.gradle | 5 +- .../kotlin/app/src/main/AndroidManifest.xml | 6 + .../example/kotlindemos/DemoDetailsList.kt | 2 + .../example/kotlindemos/LayersDemoActivity.kt | 215 ++++++++++++++++++ .../app/src/main/res/layout/layers_demo.xml | 70 ++++++ .../app/src/main/res/values/strings.xml | 26 +++ 6 files changed, 322 insertions(+), 2 deletions(-) create mode 100644 ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/LayersDemoActivity.kt create mode 100755 ApiDemos/kotlin/app/src/main/res/layout/layers_demo.xml diff --git a/ApiDemos/kotlin/app/build.gradle b/ApiDemos/kotlin/app/build.gradle index 5599302a..da49aef1 100644 --- a/ApiDemos/kotlin/app/build.gradle +++ b/ApiDemos/kotlin/app/build.gradle @@ -22,7 +22,6 @@ android { } } - dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" @@ -33,5 +32,7 @@ dependencies { androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' // Below is the Google Play Services dependency required for using the Google Maps Android API implementation 'com.google.android.gms:play-services-maps:11.8.0' - + // Below is used to run the easypermissions library to manage location permissions + // EasyPermissions is needed to help us request for permission to access location + implementation 'pub.devrel:easypermissions:1.1.1' } \ No newline at end of file diff --git a/ApiDemos/kotlin/app/src/main/AndroidManifest.xml b/ApiDemos/kotlin/app/src/main/AndroidManifest.xml index 8aee3f02..980b5815 100644 --- a/ApiDemos/kotlin/app/src/main/AndroidManifest.xml +++ b/ApiDemos/kotlin/app/src/main/AndroidManifest.xml @@ -16,6 +16,11 @@ + + + + + diff --git a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/DemoDetailsList.kt b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/DemoDetailsList.kt index 622099f9..123ad938 100644 --- a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/DemoDetailsList.kt +++ b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/DemoDetailsList.kt @@ -28,6 +28,8 @@ class DemoDetailsList { CameraDemoActivity::class.java), DemoDetails(R.string.markers_demo_label, R.string.markers_demo_description, MarkerDemoActivity::class.java), + DemoDetails(R.string.layers_demo_label, R.string.layers_demo_description, + LayersDemoActivity::class.java), DemoDetails(R.string.polyline_demo_label, R.string.polyline_demo_description, PolylineDemoActivity::class.java), DemoDetails(R.string.tags_demo_label, R.string.tags_demo_details, diff --git a/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/LayersDemoActivity.kt b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/LayersDemoActivity.kt new file mode 100644 index 00000000..58e667f8 --- /dev/null +++ b/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/LayersDemoActivity.kt @@ -0,0 +1,215 @@ +/* + * Copyright 2018 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 + * + * https://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.example.kotlindemos + +import android.Manifest +import android.annotation.SuppressLint +import android.app.AlertDialog +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.util.Log +import android.view.View +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.CheckBox +import android.widget.Spinner +import com.google.android.gms.maps.GoogleMap +import com.google.android.gms.maps.GoogleMap.MAP_TYPE_HYBRID +import com.google.android.gms.maps.GoogleMap.MAP_TYPE_NONE +import com.google.android.gms.maps.GoogleMap.MAP_TYPE_NORMAL +import com.google.android.gms.maps.GoogleMap.MAP_TYPE_SATELLITE +import com.google.android.gms.maps.GoogleMap.MAP_TYPE_TERRAIN +import com.google.android.gms.maps.OnMapReadyCallback +import com.google.android.gms.maps.SupportMapFragment +import pub.devrel.easypermissions.AfterPermissionGranted +import pub.devrel.easypermissions.EasyPermissions + +private const val LOCATION_PERMISSION_REQUEST_CODE = 1 + +/** + * Demonstrates the different base layers of a map. + */ +class LayersDemoActivity : + AppCompatActivity(), + OnMapReadyCallback, + AdapterView.OnItemSelectedListener, + EasyPermissions.PermissionCallbacks { + + private val TAG = MarkerDemoActivity::class.java.name + + private lateinit var map: GoogleMap + + private lateinit var trafficCheckbox: CheckBox + private lateinit var myLocationCheckbox: CheckBox + private lateinit var buildingsCheckbox: CheckBox + private lateinit var indoorCheckbox: CheckBox + private lateinit var spinner: Spinner + + /** + * Flag indicating whether a requested permission has been denied after returning in + * [.onRequestPermissionsResult]. + */ + private var showPermissionDeniedDialog = false + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.layers_demo) + + spinner = findViewById(R.id.layers_spinner).apply { + adapter = ArrayAdapter.createFromResource(this@LayersDemoActivity, + R.array.layers_array, android.R.layout.simple_spinner_item).apply { + setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + } + + // set a listener for when the spinner to select map type is changed. + onItemSelectedListener = this@LayersDemoActivity + } + + myLocationCheckbox = findViewById(R.id.my_location) + buildingsCheckbox = findViewById(R.id.buildings) + indoorCheckbox = findViewById(R.id.indoor) + trafficCheckbox = findViewById(R.id.traffic) + + val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment + mapFragment.getMapAsync(this) + } + + /** + * Display a dialog box asking the user to grant permissions if they were denied + */ + override fun onResumeFragments() { + super.onResumeFragments() + if (showPermissionDeniedDialog) { + AlertDialog.Builder(this).apply { + setPositiveButton(R.string.ok, null) + setMessage(R.string.location_permission_denied) + create() + }.show() + showPermissionDeniedDialog = false + } + } + + @SuppressLint("MissingPermission") + override fun onMapReady(googleMap: GoogleMap?) { + + // exit early if the map was not initialised properly + map = googleMap ?: return + + updateMapType() + + // check the state of all checkboxes and update the map accordingly + with(map) { + isTrafficEnabled = trafficCheckbox.isChecked + isBuildingsEnabled = buildingsCheckbox.isChecked + isIndoorEnabled = indoorCheckbox.isChecked + } + + // Must deal with the location checkbox separately as must check that + // location permission have been granted before enabling the 'My Location' layer. + if (myLocationCheckbox.isChecked) enableMyLocation() + + + // attach a listener to each checkbox + trafficCheckbox.setOnClickListener { map.isTrafficEnabled = trafficCheckbox.isChecked } + + buildingsCheckbox.setOnClickListener { + map.isBuildingsEnabled = buildingsCheckbox.isChecked + } + + indoorCheckbox.setOnClickListener { map.isIndoorEnabled = indoorCheckbox.isChecked } + + // if this box is checked, must check for permission before enabling the My Location layer + myLocationCheckbox.setOnClickListener { + if (!myLocationCheckbox.isChecked) { + map.isMyLocationEnabled = false + } else { + enableMyLocation() + } + } + } + + @SuppressLint("MissingPermission") + @AfterPermissionGranted(LOCATION_PERMISSION_REQUEST_CODE) + private fun enableMyLocation() { + // Enable the location layer. Request the location permission if needed. + val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION) + + if (EasyPermissions.hasPermissions(this, *permissions)) { + map.isMyLocationEnabled = true + + } else { + // if permissions are not currently granted, request permissions + EasyPermissions.requestPermissions(this, + getString(R.string.permission_rationale_location), + LOCATION_PERMISSION_REQUEST_CODE, *permissions) + } + } + + /** + * Change the type of the map depending on the currently selected item in the spinner + */ + private fun updateMapType() { + // This can also be called by the Android framework in onCreate() at which + // point map may not be ready yet. + if (!::map.isInitialized) return + + map.mapType = when (spinner.selectedItem) { + getString(R.string.normal) -> MAP_TYPE_NORMAL + getString(R.string.hybrid) -> MAP_TYPE_HYBRID + getString(R.string.satellite) -> MAP_TYPE_SATELLITE + getString(R.string.terrain) -> MAP_TYPE_TERRAIN + getString(R.string.none_map) -> MAP_TYPE_NONE + else -> { + map.mapType // do not change map type + Log.e(TAG, "Error setting layer with name ${spinner.selectedItem}") + } + } + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, + permissions, grantResults, this) + } + + override fun onPermissionsDenied(requestCode: Int, list: List) { + // Un-check the box until the layer has been enabled + // and show dialog box with permission rationale. + myLocationCheckbox.isChecked = false + showPermissionDeniedDialog = true + } + + override fun onPermissionsGranted(requestCode: Int, perms: MutableList) { + // do nothing, handled in updateMyLocation + } + + /** + * Called as part of the AdapterView.OnItemSelectedListener + */ + override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { + updateMapType() + } + + override fun onNothingSelected(parent: AdapterView<*>) { + // Do nothing. + } + +} \ No newline at end of file diff --git a/ApiDemos/kotlin/app/src/main/res/layout/layers_demo.xml b/ApiDemos/kotlin/app/src/main/res/layout/layers_demo.xml new file mode 100755 index 00000000..b2a79924 --- /dev/null +++ b/ApiDemos/kotlin/app/src/main/res/layout/layers_demo.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + diff --git a/ApiDemos/kotlin/app/src/main/res/values/strings.xml b/ApiDemos/kotlin/app/src/main/res/values/strings.xml index bf72f464..053076be 100644 --- a/ApiDemos/kotlin/app/src/main/res/values/strings.xml +++ b/ApiDemos/kotlin/app/src/main/res/values/strings.xml @@ -79,6 +79,32 @@ Rotation State badge + + Buildings + Hybrid + Indoor + + @string/normal + @string/hybrid + @string/satellite + @string/terrain + @string/none_map + + Layers + Demonstrates the different map layers. + My Location + None + Normal + OK + Satellite + Terrain + Traffic + + + Access to the location service is required to demonstrate the \'my location\' feature, which shows your current location on the map. + 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 > Apps > \'Google Maps API Demos\'. + Location permission is required for this demo. + Alpha Butt