Permalink
415 lines (326 sloc) 13.4 KB

Installation

Install the library from npm:

npm install react-native-maps --save

The library ships with platform native code that needs to be compiled together with React Native. This requires you to configure your build tools.

The actual map implementation depends on the platform. On Android, one has to use Google Maps, which in turn requires you to obtain an API key for the Android SDK.

On iOS, one can choose between Google Maps or the native Apple Maps implementation.

When using Google Maps on iOS, you need to also register for the iOS SDK and include the Google Maps library in your build. The native Apple Maps based implementation works out-of-the-box and is therefore simpler to use at the price of missing some of the features supported by the Google Maps backend.

Build configuration on iOS

Using React Native Link

Run react-native link react-native-maps after which you should be able to use this library on iOS. Note that by default this will use Apple Maps and you will miss some of the features provided by Google (see the instruction on manually enabling Google Maps below).

Using CocoaPods

If the CocoaPods package manager is new to you, please first review its installation guide

Setup your Podfile (found at ios/Podfile as below, replacing all references to _YOUR_PROJECT_TARGET_ with your project target (it's the same as project name by default).

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target '_YOUR_PROJECT_TARGET_' do
  rn_path = '../node_modules/react-native'
  rn_maps_path = '../node_modules/react-native-maps'

  # See http://facebook.github.io/react-native/docs/integration-with-existing-apps.html#configuring-cocoapods-dependencies
  pod 'yoga', path: "#{rn_path}/ReactCommon/yoga/yoga.podspec"
  pod 'React', path: rn_path, subspecs: [
    'Core',
    'CxxBridge',
    'DevSupport',
    'RCTActionSheet',
    'RCTAnimation',
    'RCTGeolocation',
    'RCTImage',
    'RCTLinkingIOS',
    'RCTNetwork',
    'RCTSettings',
    'RCTText',
    'RCTVibration',
    'RCTWebSocket',
  ]

  # React Native third party dependencies podspecs
  pod 'DoubleConversion', :podspec => "#{rn_path}/third-party-podspecs/DoubleConversion.podspec"
  pod 'glog', :podspec => "#{rn_path}/third-party-podspecs/glog.podspec"
  # If you are using React Native <0.54, you will get the following error:
  # "The name of the given podspec `GLog` doesn't match the expected one `glog`"
  # Use the following line instead:
  #pod 'GLog', :podspec => "#{rn_path}/third-party-podspecs/GLog.podspec"
  pod 'Folly', :podspec => "#{rn_path}/third-party-podspecs/Folly.podspec"

  # react-native-maps dependencies
  pod 'react-native-maps', path: rn_maps_path
  # pod 'react-native-google-maps', path: rn_maps_path  # Unomment this line if you want to support GoogleMaps on iOS
  # pod 'GoogleMaps'  # Uncomment this line if you want to support GoogleMaps on iOS
  # pod 'Google-Maps-iOS-Utils' # Uncomment this line if you want to support GoogleMaps on iOS
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name == 'react-native-google-maps'
      target.build_configurations.each do |config|
        config.build_settings['CLANG_ENABLE_MODULES'] = 'No'
      end
    end
    if target.name == "React"
      target.remove_from_project
    end
  end
end

Then run in the ios folder

pod install 

and open the produced workspace file (.xcworkspace) in XCode to build your project.

Enabling Google Maps on iOS

If you want to enable Google Maps on iOS, obtain the Google API key and edit your AppDelegate.m as follows:

+ #import <GoogleMaps/GoogleMaps.h>

@implementation AppDelegate
...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
+  [GMSServices provideAPIKey:@"_YOUR_API_KEY_"]; // add this line using the api key obtained from Google Console
...

The [GMSServices provideAPIKey] should be the first call of the method.

Then, do either of the following

  1. If you are using CocoaPods to manage your dependecies, uncomment the lines related to Google Maps from the Podfile and run pod install.

  2. If you used React Native link, you may include Google Maps manually as a XCode framework following the instructions from SDK docs -> Install manually. Then, to link this library to the framework, add the following to your package.json and replace the REPLACE_ME_RELATIVE_PATH_TO_GOOGLE_MAPS_INSTALL with the relative path from your project root to the directory in which you installed the Google Maps frameworks:

    {
      "name": "your-app",
      "scripts": {
        "postinstall": "./node_modules/react-native-maps/enable-google-maps REPLACE_ME_RELATIVE_PATH_TO_GOOGLE_MAPS_INSTALL"
      }
    }

    Re-run npm install or yarn to ensure the postinstall script is run.

  3. Import and add {PROVIDER_GOOGLE} to your JavaScript:

      import MapView, { PROVIDER_GOOGLE } from 'react-native-maps';
      ...
      
      <MapView
         provider={PROVIDER_GOOGLE}
         style={styles.map}
         ...
      >
      

Build configuration on Android

Ensure your build files match the following requirements:

  1. Define the react-native-maps project in android/settings.gradle:
...
include ':react-native-maps'
project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/lib/android')
  1. Add the react-native-maps as an dependency of your app in android/app/build.gradle:
...
dependencies {
  ...
  implementation project(':react-native-maps')
}

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   = 26
    targetSdkVersion    = 26
    buildToolsVersion   = "26.0.2"
    supportLibVersion   = "26.1.0"
    googlePlayServicesVersion = "11.8.0"
    androidMapsUtilsVersion = "0.5+"
}

If you do not have project-wide properties defined and have a different play-services version than the one included in this library, use the following instead (switch 10.0.1 for the desired version):

...
dependencies {
   ...
   implementation(project(':react-native-maps')){
       exclude group: 'com.google.android.gms', module: 'play-services-base'
       exclude group: 'com.google.android.gms', module: 'play-services-maps'
   }
   implementation 'com.google.android.gms:play-services-base:10.0.1'
   implementation 'com.google.android.gms:play-services-maps:10.0.1'
}
  1. Specify your Google Maps API Key:

    Add your API key to your manifest file (android/app/src/main/AndroidManifest.xml):

<application>
   <!-- You will only need to add this meta-data tag, but make sure it's a child of application -->
   <meta-data
     android:name="com.google.android.geo.API_KEY"
     android:value="Your Google maps API Key Here"/>
</application>

Note: As shown above, com.google.android.geo.API_KEY is the recommended metadata name for the API key. A key with this name can be used to authenticate to multiple Google Maps-based APIs on the Android platform, including the Google Maps Android API. For backwards compatibility, the API also supports the name com.google.android.maps.v2.API_KEY. This legacy name allows authentication to the Android Maps API v2 only. An application can specify only one of the API key metadata names. If both are specified, the API throws an exception.

Source: https://developers.google.com/maps/documentation/android-api/signup

  1. Add import com.airbnb.android.react.maps.MapsPackage; and new MapsPackage() in your MainApplication.java :
import com.airbnb.android.react.maps.MapsPackage;
...
    @Override
    protected List<ReactPackage> getPackages() {
        return Arrays.<ReactPackage>asList(
                new MainReactPackage(),
                new MapsPackage()
        );
    }
  1. Ensure that you have Google Play Services installed:
  • For the Genymotion emulator, you can follow these instructions.
  • For a physical device you need to search on Google for 'Google Play Services'. There will be a link that takes you to the Play Store and from there you will see a button to update it (do not search within the Play Store).

Troubleshooting

The map background is blank (Google Maps)

If google logo/markers/polylines etc are displayed but the map background is otherwise blank, this is likely an API key issue. Verify your API keys and their restrictions. Ensure the native provideAPIKey call is the first line of didFinishLaunchingWithOptions.

Ensure also that the relevant Google APIs have been enabled for your project from the URLs below:

For reference, you may read the relevant issue reports: (#118, #176, #684).

No map whatsoever

Ensure the map component and its container have viewport dimensions. An example is below:

import MapView, { PROVIDER_GOOGLE } from 'react-native-maps'; // remove PROVIDER_GOOGLE import if not using Google Maps
...
const styles = StyleSheet.create({
 container: {
   ...StyleSheet.absoluteFillObject,
   height: 400,
   width: 400,
   justifyContent: 'flex-end',
   alignItems: 'center',
 },
 map: {
   ...StyleSheet.absoluteFillObject,
 },
});

export default () => (
   <View style={styles.container}>
     <MapView
       provider={PROVIDER_GOOGLE} // remove if not using Google Maps
       style={styles.map}
       region={{
         latitude: 37.78825,
         longitude: -122.4324,
         latitudeDelta: 0.015,
         longitudeDelta: 0.0121,
       }}
     >
     </MapView>
   </View>
);

Build issues with Google Maps iOS Utils (iOS)

If your XCode project uses dynamic frameworks (e.g. you also have Swift code in your project), you cannot install Google-Maps-iOS-Utils with CocoaPods. The issue and a workaround for it has been documented here.

Runtime errors on iOS (Apple Maps)

If you are trying to mount the map with the GOOGLE_PROVIDER during runtime, but your build has been configured for the Apple Maps backend, a runtime exception will be raised.

In addition, when using Apple Maps, some Google-only functionalities have been disabled via runtime errors.

An exception will be raised if you try to use advanced features that depend on the Google Maps SDK for iOS. These include

  • Making markers from KML files
  • Heatmap rendering
  • Marker clustering
  • etc.

Clearing caches

Run these commands to clean caches

# NPM
watchman watch-del-all
npm cache clean

# Android, if you encounter `com.android.dex.DexException: Multiple dex files define Landroid/support/v7/appcompat/R$anim`, then clear build folder.
cd android
./gradlew clean
cd ..

When using XCode <9

If you use Xcode with version less than 9 you may get use of undeclared identifier 'MKMapTypeMutedStandard' or Entry, ":CFBundleIdentifier", Does Not Exist errors. In this case you have to update your Xcode.

When using Android studio

Make sure your Android studio is up to date and set up following the React Native docs.

In particular, the following packages have to be installed:

  • Extras / Google Play services
  • Extras / Google Repository
  • Android 6.0 (API 23) / Google APIs Intel x86 Atom System Image Rev. 19
  • Android SDK Build-tools 23.0.3

No native module found exception on Android

Be sure to have new MapsPackage() in your MainApplication.java :

import com.airbnb.android.react.maps.MapsPackage;
...
    @Override
    protected List<ReactPackage> getPackages() {
        return Arrays.<ReactPackage>asList(
                new MainReactPackage(),
                new MapsPackage()
        );
    }

Android emulator issues

  • When starting Android emulator, make sure you have enabled Wipe user data.
  • If you are using Android Virtual Devices (AVD), ensure that Use Host GPU is checked in the settings for your virtual device.
  • If using an emulator and the only thing that shows up on the screen is the message: [APPNAME] won't run without Google Play services which are not supported by your device., you need to change the emulator CPU/ABI setting to a system image that includes Google APIs. These may need to be downloaded from the Android SDK Manager first.