
Introduction to Google Maps API for Android with Kotlin
Introduction to Google Maps API for Android with Kotlin êŽë š
Update Note
This tutorial is now up to date with the latest version of the Google Maps API, the latest version of Android Studio version 3.0.1, and uses Kotlin for app development. Update by Joe Howard. Original tutorial by Eunice Obugyei.
From fitness apps such as Runkeeper to games such as Pokemon Go, location services are an increasingly important part of modern apps.
In this Google Maps API tutorial, you will create an app named City Guide. The app allows a user to search for a location, use Google Maps to show the address of the location and listen for the userâs location changes.
You will learn how to use the Google Maps Android API, the Google Location Services API and the Google Places API for Android to do the following:
- Show a userâs current location
- Display and customize markers on a map
- Retrieve the address of a location given the coordinates
- Listen for location updates
- Search for places
Note
This Google Maps API tutorial assumes you are already familiar with the basics of Android development with Kotlin. If you are completely new to Android development, read through our Beginning Android Development with Kotlin tutorial to familiarize yourself with the basics.
Getting Started
Open Android Studio 3.0.1 or later and select Start a new Android Studio project from the Quick Start menu, or choose File/New ProjectâŠ:

In the Create New Project dialog, on the Create Android Project view, enter the name of the app as City Guide, company domain of android.raywenderlich.com, select your preferred folder location for the project files, make sure that Include Kotlin support, and click Next:

On the Target Android Devices view, check the Phone and Tablet box and select the minimum SDK you want the app to support. Specify API 16 from the Minimum SDK drop down and click Next.

On the Add an Activity to Mobile view, select the Google Maps Activity and click Next.

On the Configure Activity view, click Finish to complete the project creation process.

Android Studio will use Gradle to build your project. This may take a few seconds.
Open MapsActivity.kt
. It should look like this:
package com.raywenderlich.android.cityguide
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
class MapsActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var mMap: GoogleMap
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
// Add a marker in Sydney and move the camera
val sydney = LatLng(-34.0, 151.0)
mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
}
}
MapsActivity
currently implements the OnMapReadyCallback interface and extends AppCompatActivity.- The class overrides AppCompatActivityâs
onCreate()
method - You also override OnMapReadyCallbackâs onMapReady() method. This method is called when the map is ready to be used. The code declared in this method creates a marker with coordinates near Sydney, Australia and adds the marker to the map.
The template adds the following in the manifests/AndroidManifest.xml:
- A declaration of the
ACCESS_FINE_LOCATION
permission. This is required to access the userâs precise location. - The
com.google.android.geo.API_KEY
meta-data. This is used to specify the API key.
The template also adds a Google Play Services dependency to build.gradle
. This dependency exposes the Google Maps and Location Services APIs to the application.
implementation 'com.google.android.gms:play-services-maps:11.8.0'

All you have is a blank screen with no map; you havenât yet set up the API key for the Google Map. Youâll do that next.
Note
If youâre using an emulator, the emulatorâs installed version will have to satisfy the version of Google Play Services required in your build.gradle
file. If you see a message that you need to update the emulatorâs Google Play Services version, you can either download the latest Google APIs using your Android Studio SDK Manager and install on your Virtual Device, or lower the version in your gradle dependency.
Using the Google Maps APIs
To use any of the Google Maps APIs, you need to create an API key and enable any required APIs from the developer console. If you donât already have a Google account, create one now â itâs free!
Creating API Keys
Open res/values/
google_maps_api.xml
. You will see the following:

Now copy and paste the link shown above into your browser.

[Continue]
.
[Create API key]
button to continue.
[Close]
.Head back to google_maps_api.xml
, replace the value of google_maps_key
key with the copied API key.

Go back to the developer console and enable the Google Places API for Android. You will be using this later on to search for a place:

Setting up a Fused Location Client
Before adding any Kotlin code, youâll need to configure Android Studio to automatically insert import
statements to save you from having to add each one manually.
Go to your Android Studio Preferences (or Settings on PC) and go to Editor > General > Auto Import, select the Add unambiguous imports on the fly and the Show import popup checkboxes, and click OK.

Open MapsActivity.kt
and first rename the GoogleMap
property to map
by setting the cursor on it and hitting Shift+F6:
private lateinit var map: GoogleMap
Open your app build.gradle
file and add the Google Maps location dependency:
implementation 'com.google.android.gms:play-services-location:11.8.0'
Next, add a FusedLocationProviderClient
to MapActivity
private lateinit var fusedLocationClient: FusedLocationProviderClient
Add the following line of code to the end of onCreate()
,
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
Have MapActivity
implement the GoogleMap.OnMarkerClickListener
interface, which defines the onMarkerClick()
, called when a marker is clicked or tapped:
class MapsActivity : AppCompatActivity(), OnMapReadyCallback,
GoogleMap.OnMarkerClickListener {
/* ... ìë” ... */
}
Now you need to implement all methods declared in each of the interfaces added above. To do this, follow the steps below:

Select Implement members from the options that appear.

[OK]
.Update onMarkerClick() to be
override fun onMarkerClick(p0: Marker?) = false
Add the following code to onMapReady():
map.getUiSettings().setZoomControlsEnabled(true)
map.setOnMarkerClickListener(this)
Here you enable the zoom controls on the map and declare MapsActivity
as the callback triggered when the user clicks a marker on this map.

Enter a different set of latitude and longitude values and youâll see the marker move to your chosen location.
Replace the Sydney code with the following code to set a marker at New York City with the title âMy Favorite Cityâ:
val myPlace = LatLng(40.73, -73.99) // this is New York
map.addMarker(MarkerOptions().position(myPlace).title("My Favorite City"))
map.moveCamera(CameraUpdateFactory.newLatLng(myPlace))

Notice the map automatically centered the marker on the screen; moveCamera()
does this for you. However, the zoom level of the map isnât right, as itâs fully zoomed out.
Modify moveCamera()
as shown below:
map.moveCamera(CameraUpdateFactory.newLatLngZoom(myPlace, 12.0f))
Zoom level 0 corresponds to the fully zoomed-out world view. Most areas support zoom levels up to 20, while more remote areas only support zoom levels up to 13. A zoom level of 12 is a nice in-between value that shows enough detail without getting crazy-close.

User Permissions
Your app needs the ACCESS_FINE_LOCATION
permission for getting the userâs location details; youâve already included this in AndroidManifest.xml.
Starting with Android 6.0, user permissions are handled a little differently than before. You donât request permission during the installation of your app; rather, you request them at run time when the permission is actually required.
Permissions are classified into two categories: normal and dangerous categories. Permissions that belong to the dangerous category require run time permission from the user. Permissions that request access to the userâs private information such as the userâs CONTACTS, CALENDAR, LOCATION etc. are categorised as dangerous permissions.
Open MapsActivity.kt
and add a companion object
with the code to request location permission:
companion object {
private const val LOCATION_PERMISSION_REQUEST_CODE = 1
}
Create a new method called setUpMap()
as follows.
private fun setUpMap() {
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
return
}
}
The code above checks if the app has been granted the ACCESS_FINE_LOCATION
permission. If it hasnât, then request it from the user.
Add a call to setUpMap()
at the end of onMapReady()
.
![Build and run; click [Allow]
to grant permission.](https://koenig-media.raywenderlich.com/uploads/2018/01/allow.png =240x)
Note
A thorough discussion of user permissions is beyond the scope of this tutorial, but check out this document on requesting permissions at run time.
Getting Current Location
One of the most common uses for location services is finding the userâs current location. You do this by requesting the last known location of the userâs device from the Google Play services location APIs.
In MapsActivity.kt
, add the following new property:
private lateinit var lastLocation: Location
Next, remove the code in onMapReady()
that put a marker in New York:
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
map.uiSettings.isZoomControlsEnabled = true
map.setOnMarkerClickListener(this)
setUpMap()
}
Add the code below to the bottom of setUpMap():
// 1
map.isMyLocationEnabled = true
// 2
fusedLocationClient.lastLocation.addOnSuccessListener(this) { location ->
// Got last known location. In some rare situations this can be null.
// 3
if (location != null) {
lastLocation = location
val currentLatLng = LatLng(location.latitude, location.longitude)
map.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 12f))
}
}
Taking each commented section in turn:
- isMyLocationEnabled = true enables the
my-location
layer which draws a light blue dot on the userâs location. It also adds a button to the map that, when tapped, centers the map on the userâs location. - fusedLocationClient.getLastLocation() gives you the most recent location currently available.
- If you were able to retrieve the the most recent location, then move the camera to the userâs current location.

Emulator Testing
Itâs best to use a real Android device to test a map application. If for some reason, you need to test from an emulator, you can do so by mocking location data in the emulator.
One way to do this is by using the emulatorâs extended controls. Hereâs how youâd do that:


Enter the latitude and longitude values in the specified fields and click [Send]
.
Markers
As you may have noticed from the last run, the blue dot on the userâs location is not very prominent. The Android Maps API lets you use a marker object, which is an icon that can be placed at a particular point on the mapâs surface.
In MapsActivity.kt
add the following code.
private fun placeMarkerOnMap(location: LatLng) {
// 1
val markerOptions = MarkerOptions().position(location)
// 2
map.addMarker(markerOptions)
}
- Create a
MarkerOptions
object and sets the userâs current location as the position for the marker - Add the marker to the map
Now replace the setUpMap()
with the following:
private fun setUpMap() {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
return
}
map.isMyLocationEnabled = true
fusedLocationClient.lastLocation.addOnSuccessListener(this) { location ->
// Got last known location. In some rare situations this can be null.
if (location != null) {
lastLocation = location
val currentLatLng = LatLng(location.latitude, location.longitude)
placeMarkerOnMap(currentLatLng)
map.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 12f))
}
}
}
The only change you made to setUpMap()
here is adding a call to placeMarkerOnMap()
to show the marker.
Build and run to view your progress so far.

Donât like the default Android pins? You can also create a marker with a custom icon as the pin. Go back to placeMarkerOnMap()
and add the following line of code after the MarkerOptions
instantiation:
markerOptions.icon(
BitmapDescriptorFactory.fromBitmap(
BitmapFactory.decodeResource(resources, R.mipmap.ic_user_location)
)
)
Download custom pins named ic_user_location
from this link and unzip it.

mipmap
folders of the projectBuild and run to view your progress so far.

ic_user_location
icon in the projectWhat if all you want is the default pin but in a different color? Try to figure this out by yourself, and then check the spoiler below if you need more help:
Answer
Add this line of code to placeMarkerOnMap()
instead:
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))

Changing the Map Type
Depending on the functionality of your app, the normal map view might not be detailed enough for you.
The Android Maps API provides different map types to help you out: MAP_TYPE_NORMAL
, MAP_TYPE_SATELLITE
, MAP_TYPE_TERRAIN
, MAP_TYPE_HYBRID
Add the following inside setUpMap()
just below the setMyLocationEnabled()
call:
map.mapType = GoogleMap.MAP_TYPE_TERRAIN
GoogleMap.MAP_TYPE_TERRAIN
displays a more detailed view of the area, showing changes in elevation



Implementing Geocoding
Now that you have the userâs location, it would be nice if you could show the address of that location when the user clicks on the marker. Google has a class that does exactly that: Geocoder
. This takes the coordinates of a location and returns a readable address and vice versa.
Open MapsActivity
. Add the following method:
private fun getAddress(latLng: LatLng): String {
// 1
val geocoder = Geocoder(this)
val addresses: List<Address>?
val address: Address?
var addressText = ""
try {
// 2
addresses = geocoder.getFromLocation(latLng.latitude, latLng.longitude, 1)
// 3
if (null != addresses && !addresses.isEmpty()) {
address = addresses[0]
for (i in 0 until address.maxAddressLineIndex) {
addressText += if (i == 0) address.getAddressLine(i) else "\n" + address.getAddressLine(i)
}
}
} catch (e: IOException) {
Log.e("MapsActivity", e.localizedMessage)
}
return addressText
}
The import for Address
is ambiguous, so specify the following import to resolve the issue:
import android.location.Address
Briefly, hereâs whatâs going on:
- Creates a Geocoder object to turn a latitude and longitude coordinate into an address and vice versa.
- Asks the geocoder to get the address from the location passed to the method.
- If the response contains any address, then append it to a string and return.
Replace placeMarkerOnMap()
with the following.
private fun placeMarkerOnMap(location: LatLng) {
val markerOptions = MarkerOptions().position(location)
val titleStr = getAddress(location) // add these two lines
markerOptions.title(titleStr)
map.addMarker(markerOptions)
}
Here you added a call to getAddress()
and added this address as the marker title.
Build and run to view your progress so far

Click anywhere on the map to dismiss the address.
Notice that when you move locations, the blue dot moves with you, but the marker remains at itâs first location. If youâre using a physical device, try moving around to see this. If you are on emulator, change your coordinates to another location in your emulator control.
The marker doesnât move because your code does not know that the location has changed. The blue dot is controlled by the Google API, not your code. If you want the marker to follow the blue dot always, you need to receive location updates as a call-back in your code.
Receiving Location Updates
Knowing your userâs location at all times can help you provide a better experience. This section of the tutorial shows you how to continuously receive updates of your userâs location.
To do this, you first have to create a location request.
Open MapsActivity
. Now add the following properties:
// 1
private lateinit var locationCallback: LocationCallback
// 2
private lateinit var locationRequest: LocationRequest
private var locationUpdateState = false
companion object {
private const val LOCATION_PERMISSION_REQUEST_CODE = 1
// 3
private const val REQUEST_CHECK_SETTINGS = 2
}
- Declare a
LocationCallback
property. - Declare a
LocationRequest
property and a location updated state property. REQUEST_CHECK_SETTINGS
is used as the request code passed toonActivityResult
.
Next add the following:
private fun startLocationUpdates() {
//1
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION),
LOCATION_PERMISSION_REQUEST_CODE)
return
}
//2
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null /* Looper */)
}
- In
startLocationUpdates()
, if theACCESS_FINE_LOCATION
permission has not been granted, request it now and return. - If there is permission, request for location updates.
Now add the following method:
private fun createLocationRequest() {
// 1
locationRequest = LocationRequest()
// 2
locationRequest.interval = 10000
// 3
locationRequest.fastestInterval = 5000
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
val builder = LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest)
// 4
val client = LocationServices.getSettingsClient(this)
val task = client.checkLocationSettings(builder.build())
// 5
task.addOnSuccessListener {
locationUpdateState = true
startLocationUpdates()
}
task.addOnFailureListener { e ->
// 6
if (e is ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
e.startResolutionForResult(this@MapsActivity,
REQUEST_CHECK_SETTINGS)
} catch (sendEx: IntentSender.SendIntentException) {
// Ignore the error.
}
}
}
}
Hereâs whatâs going on in createLocationRequest()
:

Now add the following three methods:
Hereâs whatâs going on:
Setup the LocationCallback()
in onCreate()
to be:
Here you update lastLocation
with the new location and update the map with the new location coordinates.
Next, add a call to createLocationRequest()
to the bottom of onCreate()
:
Your app is now set to receive location updates. When you change your location, the map will update with a new marker showing your new location. Note that the markers are still clickable to get the address as before.
Build and run.

Since this app is supposed to be a guide, a user should be able to search for places of interest to them, right?
Thatâs where the Google Places API comes in; it provides your app the functionality to search for millions of institutions and places of interest. Itâs Android Library provides a number of cool functionalities, one of them being the Place Picker, which is a UI widget that lets you provide a place search functionality with very few lines of code. Too good to be true? Try it!
Add the places API to your app build.gradle
:
Once again, open MapsActivity
.
Add this constant to the companion object
:
Now add the following method:
This method creates a new builder for an intent to start the Place Picker UI and then starts the PlacePicker
intent.
Now add the following lines of code to onActivityResult()
:
Here you retrieve details about the selected place if it has a RESULT_OK
result for a PLACE_PICKER_REQUEST
request, and then place a marker on that position on the map.
You are almost ready to try out the place search â you just need to call loadPlacePicker() inside the code.
Youâll create a floating action button (FAB) at the bottom-right of the map to trigger this method. FAB requires CoordinatorLayout
which is part of the design support library.
Go back to build.gradle
for the app and add the Android support design library as a dependency:
Then replace the contents of res > layout > activity_maps.xml with the following lines of code:
You were using a fragment element for map earlier; youâve kept that and added a floating action button.
In MapsActivity
, add the following lines of code to onCreate()
:
Build and run.

You can download the final project from this tutorial here. Remember to put a valid Google Maps API key in google_maps_api.xml
when running the final project.
This Google Maps API tutorial only brushed the surface of what you can do with the Google Maps APIs. The official Google documentation has much more about web services and and the Android API here.
You can also check out the developer page on other ways to customize the marker. User permission checks for run-time permissions need a better implementation than what youâve done in this Google Maps API tutorial; the docs also have some great information about more advanced permission granting here.
Check out the developer pages for extensive reading on the Google Places API for Android, receiving location updates and mocking location data via the emulatorâs extended controls.
If you have any questions or comments, please feel free to join the forum discussion below!
- You create an instance of LocationRequest, add it to an instance of
LocationSettingsRequest.Builder
and retrieve and handle any changes to be made based on the current state of the userâs location settings. interval
specifies the rate at which your app will like to receive updates.fastestInterval
specifies the fastest rate at which the app can handle updates. Setting thefastestInterval
rate places a limit on how fast updates will be sent to your app.- re you start requesting for location updates, you need to check the state of the userâs location settings.
- You create a settings client and a task to check location settings.
- A task
success
means all is well and you can go ahead and initiate a location request. - A task
failure
means the location settings have some issues which can be fixed. This could be as a result of the userâs location settings turned off

Now add the following three methods:
// 1
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CHECK_SETTINGS) {
if (resultCode == Activity.RESULT_OK) {
locationUpdateState = true
startLocationUpdates()
}
}
}
// 2
override fun onPause() {
super.onPause()
fusedLocationClient.removeLocationUpdates(locationCallback)
}
// 3
public override fun onResume() {
super.onResume()
if (!locationUpdateState) {
startLocationUpdates()
}
}
Hereâs whatâs going on:
- Override
AppCompatActivity
âsonActivityResult()
method and start the update request if it has aRESULT_OK
result for aREQUEST_CHECK_SETTINGS
request. - Override
onPause()
to stop location update request - Override
onResume()
to restart the location update request.
Setup the LocationCallback()
in onCreate()
to be:
locationCallback = object : LocationCallback() {
override fun onLocationResult(p0: LocationResult) {
super.onLocationResult(p0)
lastLocation = p0.lastLocation
placeMarkerOnMap(LatLng(lastLocation.latitude, lastLocation.longitude))
}
}
Here you update lastLocation
with the new location and update the map with the new location coordinates.
Next, add a call to createLocationRequest()
to the bottom of onCreate()
:
createLocationRequest()
Your app is now set to receive location updates. When you change your location, the map will update with a new marker showing your new location. Note that the markers are still clickable to get the address as before.
Build and run.

Place Search
Since this app is supposed to be a guide, a user should be able to search for places of interest to them, right?
Thatâs where the Google Places API comes in; it provides your app the functionality to search for millions of institutions and places of interest. Itâs Android Library provides a number of cool functionalities, one of them being the Place Picker, which is a UI widget that lets you provide a place search functionality with very few lines of code. Too good to be true? Try it!
Add the places API to your app build.gradle
:
implementation 'com.google.android.gms:play-services-places:11.8.0'
Once again, open MapsActivity
.
Add this constant to the companion object
:
private const val PLACE_PICKER_REQUEST = 3
Now add the following method:
private fun loadPlacePicker() {
val builder = PlacePicker.IntentBuilder()
try {
startActivityForResult(builder.build(this), PLACE_PICKER_REQUEST)
} catch (e: GooglePlayServicesRepairableException) {
e.printStackTrace()
} catch (e: GooglePlayServicesNotAvailableException) {
e.printStackTrace()
}
}
This method creates a new builder for an intent to start the Place Picker UI and then starts the PlacePicker
intent.
Now add the following lines of code to onActivityResult()
:
if (requestCode == PLACE_PICKER_REQUEST) {
if (resultCode == RESULT_OK) {
val place = PlacePicker.getPlace(this, data)
var addressText = place.name.toString()
addressText += "\n" + place.address.toString()
placeMarkerOnMap(place.latLng)
}
}
Here you retrieve details about the selected place if it has a RESULT_OK
result for a PLACE_PICKER_REQUEST
request, and then place a marker on that position on the map.
You are almost ready to try out the place search â you just need to call loadPlacePicker()
inside the code.
Youâll create a floating action button (FAB) at the bottom-right of the map to trigger this method. FAB requires CoordinatorLayout
which is part of the design support library.
Go back to build.gradle
for the app and add the Android support design library as a dependency:
implementation 'com.android.support:design:26.1.0'
Note
As usual, if you are using a newer Android SDK version, you may need to update the version of this dependency as well so they match.
Then replace the contents of res > layout > activity_maps.xml with the following lines of code:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<fragment
android:id="@+id/map"
class="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginRight="8dp"
android:layout_marginBottom="112dp"
android:src="@android:drawable/ic_menu_search"/>
</android.support.design.widget.CoordinatorLayout>
You were using a fragment element for map earlier; youâve kept that and added a floating action button.
In MapsActivity
, add the following lines of code to onCreate()
:
val fab = findViewById<FloatingActionButton>(R.id.fab)
fab.setOnClickListener {
loadPlacePicker()
}
Build and run.

Where to Go From Here?
You can download the final project from this tutorial here. Remember to put a valid Google Maps API key in google_maps_api.xml when running the final project.
This Google Maps API tutorial only brushed the surface of what you can do with the Google Maps APIs. The official Google documentation has much more about web services and and the Android API here.
You can also check out the developer page on other ways to customize the marker. User permission checks for run-time permissions need a better implementation than what youâve done in this Google Maps API tutorial; the docs also have some great information about more advanced permission granting here.
Check out the developer pages for extensive reading on the Google Places API for Android, receiving location updates and mocking location data via the emulatorâs extended controls.
If you have any questions or comments, please feel free to join the forum discussion below!
- Override
AppCompatActivity
âsonActivityResult()
method and start the update request if it has aRESULT_OK
result for aREQUEST_CHECK_SETTINGS
request. - Override
onPause()
to stop location update request - Override
onResume()
to restart the location update request.
Note
As usual, if you are using a newer Android SDK version, you may need to update the version of this dependency as well so they match.
// 1
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CHECK_SETTINGS) {
if (resultCode == Activity.RESULT_OK) {
locationUpdateState = true
startLocationUpdates()
}
}
}
// 2
override fun onPause() {
super.onPause()
fusedLocationClient.removeLocationUpdates(locationCallback)
}
// 3
public override fun onResume() {
super.onResume()
if (!locationUpdateState) {
startLocationUpdates()
}
}
locationCallback = object : LocationCallback() {
override fun onLocationResult(p0: LocationResult) {
super.onLocationResult(p0)
lastLocation = p0.lastLocation
placeMarkerOnMap(LatLng(lastLocation.latitude, lastLocation.longitude))
}
}
createLocationRequest()
implementation 'com.google.android.gms:play-services-places:11.8.0'
private const val PLACE_PICKER_REQUEST = 3
private fun loadPlacePicker() {
val builder = PlacePicker.IntentBuilder()
try {
startActivityForResult(builder.build(this), PLACE_PICKER_REQUEST)
} catch (e: GooglePlayServicesRepairableException) {
e.printStackTrace()
} catch (e: GooglePlayServicesNotAvailableException) {
e.printStackTrace()
}
}
if (requestCode == PLACE_PICKER_REQUEST) {
if (resultCode == RESULT_OK) {
val place = PlacePicker.getPlace(this, data)
var addressText = place.name.toString()
addressText += "\n" + place.address.toString()
placeMarkerOnMap(place.latLng)
}
}
implementation 'com.android.support:design:26.1.0'
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<fragment
android:id="@+id/map"
class="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginRight="8dp"
android:layout_marginBottom="112dp"
android:src="@android:drawable/ic_menu_search"/>
</android.support.design.widget.CoordinatorLayout>
val fab = findViewById<FloatingActionButton>(R.id.fab)
fab.setOnClickListener {
loadPlacePicker()
}