Preparing to add a map to a React Native app

The installation instructions for adding react-native-maps are here (as of 2020/01/20). I will be following the build configuration on Android, because I’m using an Android emulator (and a Linux OS, not a Mac, for my builds).

There are 6 steps given in the “build config for Android” section.

Step (1) – edit settings.gradle if using React Native 0.59 and lower

Step 1 says it is for “React Native 0.59 and lower)”. Which version of React Native am I using? In my project root, I take a look at package.json. Under dependencies I see:

  "dependencies": {
    "@react-native-community/masked-view": "^0.1.6",
    "react": "16.9.0",
    "react-native": "0.61.5",

I’ve got React Native 0.61.5. So I can skip step 1, which involves adding some lines to android/settings.gradle. If you’re following along, you’ll need to check this to be sure about whether or not you can skip this step.

Step (2) – add build.gradle dependency for React Native 0.59 and lower

Step 2 tells you to add a dependency to your android/app/build.gradle file, but again, only if you’re using React Native 0.59 or lower, so I can skip that step as well.

Step (3) – edit build.gradle

Step 3.1 tells you to edit your build.gradle. This is literally what they tell you to do; I’m quoting:

3.1 (React Native all versions) If you’ve defined project-wide properties (recommended) in your root build.gradle, this library will detect the presence of the following properties:

buildscript {...}
allprojects {...}

/**
+ Project-wide Gradle configuration properties
*/
ext {
    compileSdkVersion   = xxx
    targetSdkVersion    = xxx
    buildToolsVersion   = "xxx"
    minSdkVersion       = xxx
    supportLibVersion   = "xxx"
    playServicesVersion = "xxx" // or set latest version
    androidMapsUtilsVersion = "xxx"
}

or do

buildscript {
    ext {
        buildToolsVersion = "xxx"
        minSdkVersion = xxx
        compileSdkVersion = xxx
        targetSdkVersion = xxx
        supportLibVersion = "xxx"
        playServicesVersion = "xxx" // or set latest version
        androidMapsUtilsVersion = "xxx"
    }
}

I found that kind of confusing :/

First, what’s that about defining “project-wide properties in your root build.gradle”? What are these “xxx” variables; how should they be set, and why are some quoted but others are not?

Let’s talk about “If you’ve defined project-wide properties…”. Me? I haven’t done anything with build.gradle. My project was completely installed when I ran npx react-native init AwesomeProject as described in my blog post of January 6. The installer must have done something, but I don’t know what. From my Android development experience, I do know there are typically two build.gradle files in Android Studio projects. One is at the root level for the project (one step above the app directory), and the other is under the folder app.

I’m going to take a guess, and bet that the React Native install put my project-wide properties in the root build.gradle.

Here is the full content of my own android/build.gradle file prior to any changes:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 16
        compileSdkVersion = 28
        targetSdkVersion = 27
    }
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath('com.android.tools.build:gradle:3.5.2')

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url("$rootDir/../node_modules/react-native/android")
        }
        maven {
            // Android JSC is installed from npm
            url("$rootDir/../node_modules/jsc-android/dist")
        }

        google()
        jcenter()
        maven { url 'https://jitpack.io' }
    }
}

I notice a couple of things. First, there are quotes around my buildToolsVersion version. I didn’t check, but it looks like this is a string variable, whereas unquoted numbers must be, well, numbers, like the minSdkVersion is 16. Soooo…. I guess supportLibVersion, playServicesVersion, and androidMapsUtilsVersion versions are all strings. Because the documentation refers to them all as xxx, you might think all of these strings have to be the same. That’s not the case. After all, my targetSdkVersion is not the same as the buildToolsVersion. What should I fill in for xxx? Well, it turns out that each of those versions is different, and it’s not really clear how to figure out which version to use. This is what I wound up doing with mine:

buildscript {
    ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 16
        compileSdkVersion = 28
        targetSdkVersion = 27
        supportLibVersion = "28.0.0"
        playServicesVersion = "17.0.0"
        androidMapsUtilsVersion = "0.6.2"
    }
...

I figured this out by looking for the most recent versions at maven. There’s a helpful comment at StackOverflow which suggests doing that. The versions I used are all the latest versions. Note: there’s no “plus” sign on any of them. I’ve seen some people using androidMapsUtilsVersion = "0.5+". YMMV!

Step 3.2 is for people who have not specified “project-wide properties”. I believe I can skip this.

Step (4) – Google Maps API Key

Everyone has to do Step 4, which is to add your Google Maps API Key to the project. I’ve already got such a key because I’ve built several Android apps that use the Google Maps SDK for Android. Instructions to get your own Google Maps API Key are here. Caveat: you’ll need to register a credit card. But you probably won’t have to pay anything. Caveat #2: you can’t make unlimited calls to the Maps API.

Once you get your key, you may add it to your AndroidManifest.xml file as suggested in Step 4. However, it is not the greatest practice to put it there, especially if you’re checking AndroidManifest.xml into a source version control system (normally you’d want AndroidManifest.xml in version control). The API key is a secret, like a password, and you don’t want everyone to know it.

If you’ve ever created a Google Maps app using Android Studio, you’ll find that there’s a special file created for you where you’re supposed to store your API key. It’s in google_maps_api.xml, which is in app/src/release/res/values/google_maps_api.xml and app/src/debug/res/values/google_maps_api.xml. It has a few lines, like this:

<resources>
    <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">AIz...etc</string>
</resources>

This file is most commonly where you want to put your key. Then, you reference that key in your AndroidManifest.xml like this:

    <application ...>
...
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />

Step (5) – add import for React Native 0.59 and lower

Again, I can skip this step.

Step (6) – make sure Google Play Services is installed

Google Play Services was already installed in my Android emulator; I checked to see which apps were installed, and found it. If you need to do this, check out Google’s instructions.

That’s it – Finished!

Now, you’re ready to put a map into your React Native app. Want to try something simple? You can start by taking a look at the example React Native Maps app on GitHub.