Chapters

Hide chapters

Android Apprentice

Fourth Edition · Android 11 · Kotlin 1.4 · Android Studio 4.1

Section II: Building a List App

Section 2: 7 chapters
Show chapters Hide chapters

Section III: Creating Map-Based Apps

Section 3: 7 chapters
Show chapters Hide chapters

13. Creating a Map-Based App
Written by Namrata Bandekar

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Have you ever been on a road trip and wanted to make notes about the places you’ve visited; needed to warn your future self about some heartburn-inducing greasy food from a roadside diner; or you wanted to keep reminders about the best menu items at your favorite local restaurants?

If you answered “yes” to any of those questions, then you’re in luck! You’re about to build PlaceBook, an app that meets all of those needs by letting you bookmark and make notes using a map-based interface.

Getting started

While building PlaceBook, you’ll use familiar techniques from the previous sections and learn about several new Android APIs. Along the way, you’ll use:

  • Google Maps API to display a map, track the user’s location and add custom markers.
  • Google Places API to display place information and search for nearby places.
  • Room Persistence Library to store data.

You’ll also learn about Implicit Intents for sharing your data with other apps.

There’s a lot of ground to cover, but in the end, the final product will look like this:

About PlaceBook

PlaceBook starts by displaying a Google Map centered around your current location. The map will display common places, and allow you to bookmark them. You can display details for bookmarked places and edit the place data and a corresponding photo.

Making a plan

With a large number of features to implement, it’s best to think about them in bite-sized pieces. From there, you can slowly build-up to the finished product. The steps you’ll take to accomplish this are as follows:

Location service components

The Android SDK provides three main components related to location and mapping:

Map wizard walk-through

To save time, you’ll use the Maps Activity project template to generate an app with a single Activity that displays a map.

Google Maps API key

Before your app will work, you need to generate an API key using the free Google Developer Console, which requires a Google account.

<string name="google_maps_key"
        templateMergeStrategy="preserve"
        translatable="false">
        AIza5sD-_G2dq7PjafW-Ad4pKpU5a</string>

Getting the keystore fingerprint

Although Android Studio conveniently placed your debug keystore fingerprint in the XML file, it’s helpful to know how to get the fingerprint yourself should you ever need to regenerate it. The following instructions work for debug builds; getting the SHA1 key for release builds is covered in Section VI, “Submitting Your App”.

keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android.
Alias name: androiddebugkey
Creation date: Jan 01, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 4aa9b300
Valid from: Mon Jan 01 08:04:04 UTC 2013 until: Mon Jan 01 18:04:04 PST 2033
Certificate fingerprints:
     MD5:  18:5E:95:D0:A6:86:89:BC:A8:70:BA:34:FF:6A:AC:A4
     SHA1: A5:1F:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:46
     Signature algorithm name: SHA1withRSA
     Version: 3

Maps and the emulator

If you’re installing on a device, that’s all you need. However, if you’re using an emulator, then things can get a little more complicated.

Running the app

Launch the app from Android Studio.

Google Maps Android API: Authorization failure.  Please see https://developers.google.com/maps/documentation/android-api/start for how to correctly set up the map.
Google Maps Android API: In the Google Developer Console (https://console.developers.google.com)
Ensure that the "Google Maps Android API v2" is enabled.
Ensure that the following Android Key exists:                                                                                        API Key: YOUR_KEY_HERE
    Android Application (<cert_fingerprint>;<package_name>): 6A:27:6F:34:38:DA:D3:04:C8:9C:8F:41:ED:BB:B7:18:02:77:67:D2;com.raywenderlich.placebook

Project dependencies

Before you can use maps in your app, you have to add the two required dependencies. To find the first one, open build.gradle from your application module folder. In the dependencies section, you’ll see the following line:

implementation 'com.google.android.gms:play-services-maps:17.0.0'

The manifest

First, from app/manifests, open AndroidManifest.xml. It’ll look like the following, with your API key displayed in place of @string/google_maps_key:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.raywenderlich.placebook">

  <!--
       The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
       Google Maps Android API v2, but you must specify either coarse or fine
       location permissions for the 'MyLocation' functionality.
  -->
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

  <application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:supportsRtl="true"
      android:theme="@style/AppTheme">

    <!--
         The API key for Google Maps-based APIs is defined as a string resource.
         (See the file "res/values/google_maps_api.xml").
         Note that the API key is linked to the encryption key used to sign the APK.
         You need a different API key for each encryption key, including the release key that is used to
         sign the APK for publishing.
         You can define the keys for the debug and release targets in src/debug/ and src/release/.
    -->
    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="@string/google_maps_key" />

    <activity
        android:name=".MapsActivity"
        android:label="@string/title_activity_maps">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>

</manifest>

The activity and layout

Open MapsActivity.kt. This is the startup Activity created from the Maps template. Note that it inherits from AppCompatActivity and the OnMapReadyCallback interface.

class MapsActivity : AppCompatActivity(), OnMapReadyCallback {

Map display options

There are two ways to display a map in your app:

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)
}
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MapsActivity" />

Asynchronous map setup

When you call getMapAsync(), the SupportMapFragment object handles all of the work of setting up the map and creating a GoogleMap object. The GoogleMap object is what you’ll use to control and query the map.

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))
}

The difficulty of determining locations

Determining a user’s location is a rather involved process under the hood. There are multiple sources of location data to handle, and they all affect your device’s idea of where it is in the world.

Location events over time
Tepiraor ajejvq esom nire

Key Points

As you can see, there are many moving parts, and there is a lot of code required to provide a seamless experience for the user. Thankfully, the location APIs are there to do the heavy lifting for you. In this chapter you learned:

Where to go from here?

Although you will continue to extend this app over the next few chapters, you can access more extensive information on the developer pages for the Google Places SDK for Android (https://stuff.mit.edu/afs/sipb/project/android/docs/guide/topics/location/strategies.html).

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now