/react-native-google-places

iOS/Android Google Places Widgets (Autocomplete, Place Picker) and API Services for React Native Apps

Primary LanguageJava

react-native-google-places

iOS/Android Google Places Widgets (Autocomplete, Place Picker) and API Services for React Native Apps

Shots

Versioning:

  • for RN >= 0.40.0, use v2+ (e.g. react-native-google-places@2.5.0)
  • for RN (0.33.0 - 0.39.0), use v1+ or 0.8.8 (e.g. react-native-google-places@1.1.0) No longer updated

Sample App

  • A new sample app is available to help with sample usage and debugging issues.

Install

npm i react-native-google-places --save
react-native link react-native-google-places

OR

yarn add react-native-google-places
react-native link react-native-google-places

Google Places API Set-Up

  1. Sign up for Google Places API for Android in Google API Console to grab your Android API key (not browser key).
  2. Read further API setup guides at https://developers.google.com/places/android-api/signup.
  3. Similarly, sign up for Google Places API for iOS in Google API Console to grab your iOS API key (not browser key).
  4. Ensure you check out further guides at https://developers.google.com/places/ios-api/start.
  5. With both keys in place, you can proceed.

Post-install Steps

iOS (requires CocoaPods)
Auto Linking With Your Project (iOS & Android)
  • This was done automatically for you when you ran react-native link react-native-google-places. Or you can run the command now if you have not already.
Manual Linking With Your Project (iOS)
  • In XCode, in the project navigator, right click Libraries ➜ Add Files to [your project's name].
  • Go to node_modulesreact-native-google-places and add RNGooglePlaces.xcodeproj.
  • In XCode, in the project navigator, select your project. Add libRNGooglePlaces.a to your project's Build PhasesLink Binary With Libraries.
Install CocoaPods Dependencies
  • If you do not have CocoaPods already installed on your machine, run gem install cocoapods to set it up the first time. (Hint: Go grab a cup of coffee!)
  • If you are not using Cocoapods in your project already, run cd ios && pod init at the root directory of your project.
  • Add pod 'GooglePlaces', pod 'GooglePlacePicker' and pod 'GoogleMaps' to your Podfile. Otherwise just edit your Podfile to include:
source 'https://github.com/CocoaPods/Specs.git'

target 'YOUR_APP_TARGET_NAME' do

  pod 'GooglePlaces'
  pod 'GoogleMaps'
  pod 'GooglePlacePicker'

end
  • In your AppDelegate.m file, import the Google Places library by adding @import GooglePlaces; and @import GoogleMaps; on top of the file.
  • Within the didFinishLaunchingWithOptions method, instantiate the library as follows:
[GMSPlacesClient provideAPIKey:@"YOUR_IOS_API_KEY_HERE"];
[GMSServices provideAPIKey:@"YOUR_IOS_API_KEY_HERE"];
  • By now, you should be all set to install the packages from your Podfile. Run pod install from your ios directory.
  • Close Xcode, and then open (double-click) your project's .xcworkspace file to launch Xcode. From this time onwards, you must use the .xcworkspace file to open the project. Or just use the react-native run-ios command as usual to run your app in the simulator.
Android
  • In your AndroidManifest.xml file, request location permissions and add your API key in a meta-data tag (ensure you are within the <application> tag as follows:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
      android:name=".MainApplication"
      ...>
	<meta-data
		android:name="com.google.android.geo.API_KEY"
		android:value="YOUR_ANDROID_API_KEY_HERE"/>
	...
</application>
Manual Linking With Your Project (Android)
  • The following additional setup steps are optional as they should have been taken care of, for you when you ran react-native link react-native-google-places. Otherwise, do the following or just ensure they are in place;
  • Add the following in your android/settings.gradle file:
include ':react-native-google-places'
project(':react-native-google-places').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-places/android')
  • Add the following in your android/app/build.grade file:
dependencies {
    ...
    compile project(':react-native-google-places')
}
  • Add the Google Maven Repo in your android/build.gradle file:
allprojects {
    repositories {
        ...
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        maven {
            url "https://maven.google.com" 
        }
    }
}
  • Add the following in your ...MainApplication.java file:
import com.arttitude360.reactnative.rngoogleplaces.RNGooglePlacesPackage;

@Override
protected List<ReactPackage> getPackages() {
  return Arrays.<ReactPackage>asList(
      new MainReactPackage(),
      ...
      new RNGooglePlacesPackage() //<-- Add line
  );
}
  • Finally, we can run react-native run-android to get started.
Configuring Versions for Dependencies (Optional & for Android Only)
  • Option 1: Use Project-Wide Gradle Config:

You can define project-wide properties (recommended) in your root /android/build.gradle, and let the library auto-detect the presence of the following properties:

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

    /**
     + Project-wide Gradle configuration properties (replace versions as appropriate)
     */
    ext {
      compileSdkVersion   = 25
      targetSdkVersion    = 25
      buildToolsVersion   = "25.0.2"
      supportLibVersion   = "25.0.2"
      googlePlayServicesVersion = "11.6.2"
      androidMapsUtilsVersion = "0.5+"
    }
  • Option 2: Use Specific Gradle Config:

If you do not have project-wide properties defined or want to use a different Google Play-Services version than the one included in this library (shown above), use the following instead (switch 11.6.2 for the desired version):

  ...
  dependencies {
      ...
      compile(project(':react-native-google-places')){
          exclude group: 'com.google.android.gms', module: 'play-services-base'
          exclude group: 'com.google.android.gms', module: 'play-services-places'
          exclude group: 'com.google.android.gms', module: 'play-services-location'
      }
      compile 'com.google.android.gms:play-services-base:11.6.2'
      compile 'com.google.android.gms:play-services-places:11.6.2'
      compile 'com.google.android.gms:play-services-location:11.6.2'
  }

Usage

Allows your users to enter place names and addresses - and autocompletes your users' queries as they type.

Import library

import RNGooglePlaces from 'react-native-google-places';

Open Autocomplete Modal (e.g as Callback to an onPress event)

class GPlacesDemo extends Component {
  openSearchModal() {
    RNGooglePlaces.openAutocompleteModal()
    .then((place) => {
		console.log(place);
		// place represents user's selection from the
		// suggestions and it is a simplified Google Place object.
    })
    .catch(error => console.log(error.message));  // error is a Javascript Error object
  }

  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity
          style={styles.button}
          onPress={() => this.openSearchModal()}
        >
          <Text>Pick a Place</Text>
        </TouchableOpacity>
      </View>
    );
  }
}
Optional Parameters

To filter autocomplete results as listed for Android and iOS in the official docs, you can pass an options object as a parameter to the openAutocompleteModal() method as follows:

  RNGooglePlaces.openAutocompleteModal({
	  type: 'establishment',
	  country: 'CA',
	  latitude: 53.544389,
	  longitude: -113.490927,
	  radius: 10
  })
    .then((place) => {
    console.log(place);
    })
    .catch(error => console.log(error.message));
  • type (String) - The type of results to return. Can be one of (geocode, address, establishment, regions, and cities). (optional)
  • country (String) - Limit results to a specific country using a ISO 3166-1 Alpha-2 country code (case insensitive). If this is not set, no country filtering will take place. (optional)
  • latitude (Number) - Latitude of the point around which you wish to retrieve place information (required if longitude is given)
  • longitude (Number) - Longitude of the point around which you wish to retrieve place information (required if latitude is given)
  • radius (Number) - Radius (in kilo-meters) within which to retrieve place information. Only works if latitude and longitude are also given. Note that setting a radius biases results to the indicated area, but may not fully restrict results to the specified area. Defaults to 0.1.
  • useOverlay (Boolean) [Android Only] - If true, the autocomplete modal will open as an overlay. Defaults to false.

Open PlacePicker Modal

class GPlacesDemo extends Component {
  openSearchModal() {
    RNGooglePlaces.openPlacePickerModal()
    .then((place) => {
		console.log(place);
		// place represents user's selection from the
		// suggestions and it is a simplified Google Place object.
    })
    .catch(error => console.log(error.message));  // error is a Javascript Error object
  }

  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity
          style={styles.button}
          onPress={() => this.openSearchModal()}
        >
          <Text>Open Place Picker</Text>
        </TouchableOpacity>
      </View>
    );
  }
}

To set the initial viewport that the place picker map should show when the picker is launched, you can pass a latLngBounds object as a parameter to the openPlacePickerModal() method as follows. The latLngBounds object takes the following optional keys:

  • latitude (Number) - Latitude of the point which you want the map centered on (required if longitude is given)
  • longitude (Number) - Longitude of the point which you want the map centered on (required if latitude is given)
  • radius (Number) - Radius (in kilo-meters) from the center of the map view to the edge. Use this to set the default "zoom" of the map view when it is first opened. Only works if latitude and longitude are also given. Defaults to 0.1.

If no initial viewport is set (no argument is passed to the openPlacePickerModal() method), the viewport will be centered on the device's location, with the zoom at city-block level.

  RNGooglePlaces.openPlacePickerModal({
	  latitude: 53.544389,
	  longitude: -113.490927,
	  radius: 0.01 // 10 meters
  })
    .then((place) => {
    console.log(place);
    })
    .catch(error => console.log(error.message));

Example Response from the Autocomplete & PlacePicker Modals

{
	placeID: "ChIJZa6ezJa8j4AR1p1nTSaRtuQ",
	website: "https://www.facebook.com/",
	phoneNumber: "+1 650-543-4800",
	address: "1 Hacker Way, Menlo Park, CA 94025, USA",
	name: "Facebook HQ",
	types: [ 'street_address', 'geocode' ],
	latitude: 37.4843428,
	longitude: -122.14839939999999
}
  • Note: The keys available from the response from the resolved Promise from calling RNGooglePlaces.openAutocompleteModal() are dependent on the selected place - as phoneNumber, website, north, south, east, west, priceLevel, rating are not set on all Google Place objects.

Get Current Place

This method returns to you the place where the device is currently located. That is, the place at the device's currently-reported location. For each place, the result includes an indication of the likelihood that the place is the right one. A higher value for likelihood means a greater probability that the place is the best match.

  RNGooglePlaces.getCurrentPlace()
    .then((results) => console.log(results))
    .catch((error) => console.log(error.message));

Example Response from Calling getCurrentPlace()

[{ name: 'Facebook HQ',
  website: 'https://www.facebook.com/',
  longitude: -122.14835169999999,
  address: '1 Hacker Way, Menlo Park, CA 94025, USA',
  latitude: 37.48485,
  placeID: 'ChIJZa6ezJa8j4AR1p1nTSaRtuQ',
  types: [ 'street_address', 'geocode' ],
  phoneNumber: '+1 650-543-4800',
  likelihood: 0.9663974,
  ...
},{
  ...
}]

The sum of the likelihoods in a given result set is always less than or equal to 1.0. Note that the sum isn't necessarily 1.0.

Using Your Own Custom UI/Views

If you have specific branding needs or you would rather build out your own custom search input and suggestions list (think Uber), you may profit from calling the API methods below which would get you autocomplete predictions programmatically using the underlying iOS and Android SDKs.

Get Autocomplete Predictions

  RNGooglePlaces.getAutocompletePredictions('facebook')
    .then((results) => this.setState({ predictions: results }))
    .catch((error) => console.log(error.message));
Optional Parameters

To filter autocomplete results as listed for Android and iOS in the official docs, you can pass an options object as a second parameter to the getAutocompletePredictions() method as follows:

  RNGooglePlaces.getAutocompletePredictions('Lagos', {
	  type: 'cities',
	  country: 'NG'
  })
    .then((place) => {
    console.log(place);
    })
    .catch(error => console.log(error.message));

OR

RNGooglePlaces.getAutocompletePredictions('pizza', {
	  type: 'establishments',
	  latitude: 53.544389,
	  longitude: -113.490927,
	  radius: 10
  })
    .then((place) => {
    console.log(place);
    })
    .catch(error => console.log(error.message));
  • type (String) - The type of results to return. Can be one of (geocode, address, establishment, regions, and cities). (optional)
  • country (String) - Limit results to a specific country using a ISO 3166-1 Alpha-2 country code (case insensitive). If this is not set, no country filtering will take place. (optional)
  • latitude (Number) - Latitude of the point around which you wish to retrieve place information (required if longitude is given)
  • longitude (Number) - Longitude of the point around which you wish to retrieve place information (required if latitude is given)
  • radius (Number) - Radius (in kilo-meters) within which to retrieve place information. Only works if latitude and longitude are also given. Note that setting a radius biases results to the indicated area, but may not fully restrict results to the specified area. Defaults to 0.1.

Example Response from Calling getAutocompletePredictions()

[ { primaryText: 'Facebook HQ',
    placeID: 'ChIJZa6ezJa8j4AR1p1nTSaRtuQ',
    secondaryText: 'Hacker Way, Menlo Park, CA, United States',
    fullText: 'Facebook HQ, Hacker Way, Menlo Park, CA, United States' },
    types: [ 'street_address', 'geocode' ],
  { primaryText: 'Facebook Way',
    placeID: 'EitGYWNlYm9vayBXYXksIE1lbmxvIFBhcmssIENBLCBVbml0ZWQgU3RhdGVz',
    secondaryText: 'Menlo Park, CA, United States',
    fullText: 'Facebook Way, Menlo Park, CA, United States' },
    types: [ 'street_address', 'geocode' ],

    ...
]

Look-Up Place By ID

  RNGooglePlaces.lookUpPlaceByID('ChIJZa6ezJa8j4AR1p1nTSaRtuQ')
    .then((results) => console.log(results))
    .catch((error) => console.log(error.message));

Example Response from Calling lookUpPlaceByID()

{ name: 'Facebook HQ',
  website: 'https://www.facebook.com/',
  longitude: -122.14835169999999,
  address: '1 Hacker Way, Menlo Park, CA 94025, USA',
  latitude: 37.48485,
  placeID: 'ChIJZa6ezJa8j4AR1p1nTSaRtuQ',
  types: [ 'street_address', 'geocode' ],
  phoneNumber: '+1 650-543-4800',
}

Look-Up Places By IDs (2 or more places at a time)

  const placeIDs = ['ChIJZa6ezJa8j4AR1p1nTSaRtuQ', 'other_place_id'];
  RNGooglePlaces.lookUpPlacesByIDs(placeIDs)
    .then((results) => console.log(results))
    .catch((error) => console.log(error.message));

Example Response from Calling lookUpPlacesByIDs()

[
    { name: 'Facebook HQ',
      website: 'https://www.facebook.com/',
      longitude: -122.14835169999999,
      address: '1 Hacker Way, Menlo Park, CA 94025, USA',
      latitude: 37.48485,
      placeID: 'ChIJZa6ezJa8j4AR1p1nTSaRtuQ',
      types: [ 'street_address', 'geocode' ],
      phoneNumber: '+1 650-543-4800',
    }
]
  • Note: Check Autocomplete & PlacePicker response for notes and other available keys.

Design Hint

The typical use flow would be to call getAutocompletePredictions() when the value of your search input changes to populate your suggestion listview and call lookUpPlaceByID() to retrieve the place details when a place on your listview is selected.

PS (from Google)

  • Use of the getAutocompletePredictions() method is subject to tiered query limits. See the documentation on Android & iOS Usage Limits.
  • Also, your UI must either display a 'Powered by Google' attribution, or appear within a Google-branded map.

Troubleshooting

On iOS

You have to link dependencies and re-run the build:

  1. Run react-native link
  2. Try Manual Linking With Your Project steps above.
  3. Run react-native run-ios

On Android

  1. Run "android" and make sure every packages is updated.
  2. If not installed yet, you have to install the following packages:
  • Extras / Google Play services

  • Extras / Google Repository

  • Android (API 23+) / Google APIs Intel x86 Atom System Image Rev. 13

  • Check manual installation steps

  • Ensure your API key has permissions for Google Place and Google Android Maps

  • If you have a different version of play serivces than the one included in this library (which is currently at 10.2.4), use the following instead (switch 10.2.0 for the desired version) in your android/app/build.grade file:

    ...
    dependencies {
        ...
        compile(project(':react-native-google-places')){
            exclude group: 'com.google.android.gms', module: 'play-services-base'
            exclude group: 'com.google.android.gms', module: 'play-services-places'
            exclude group: 'com.google.android.gms', module: 'play-services-location'
        }
        compile 'com.google.android.gms:play-services-base:11.6.2'
        compile 'com.google.android.gms:play-services-places:11.6.2'
        compile 'com.google.android.gms:play-services-location:11.6.2'
    }

License

The MIT License.