iOS/Android Google Places Widgets (Autocomplete, Place Picker) and API Services for React Native Apps
Notice: The Google Play Services version of the Places SDK for Android (in Google Play Services 16.0.0) is deprecated as of January 29, 2019, and will be turned off on July 29, 2019. A new version of the Places SDK for Android is now available.
I recommend you migrate your applications to the version 3.0.1 (or above) of this package - Heads up! There are tons of breaking changes in the new release. Visit the updated README to get started
- for RN >= 0.40.0, use v2+ (e.g. [email protected])
I recommend you migrate your applications to the version 3.0.1 (or above) of this package - Heads up! There are tons of breaking changes in the new release. Visit the updated README to get started
- A new sample app is available to help with sample usage and debugging issues.
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
- Sign up for Google Places API for Android in Google API Console to grab your Android API key (not browser key).
- Read further API setup guides at https://developers.google.com/places/android-api/signup.
- Similarly, sign up for Google Places API for iOS in Google API Console to grab your iOS API key (not browser key).
- Ensure you check out further guides at https://developers.google.com/places/ios-api/start.
- With both keys in place, you can proceed.
- 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.
- In XCode, in the project navigator, right click
Libraries ➜ Add Files to [your project's name]
. - Go to
node_modules
➜react-native-google-places
and addRNGooglePlaces.xcodeproj
. - In XCode, in the project navigator, select your project. Add
libRNGooglePlaces.a
to your project'sBuild Phases
➜Link Binary With Libraries
.
- 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'
andpod '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 yourios
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 thereact-native run-ios
command as usual to run your app in the simulator.
- 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>
- 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.
- 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'
}
Allows your users to enter place names and addresses - and autocompletes your users' queries as they type.
import RNGooglePlaces from 'react-native-google-places';
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>
);
}
}
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
, andcities
). (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 iflongitude
is given)longitude
(Number) - Longitude of the point around which you wish to retrieve place information (required iflatitude
is given)radius
(Number) - Radius (in kilo-meters) within which to retrieve place information. Only works iflatitude
andlongitude
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 to0.1
.useOverlay
(Boolean) [Android Only] - If true, the autocomplete modal will open as an overlay. Defaults tofalse
.
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 iflongitude
is given)longitude
(Number) - Longitude of the point which you want the map centered on (required iflatitude
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 iflatitude
andlongitude
are also given. Defaults to0.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));
{
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 callingRNGooglePlaces.openAutocompleteModal()
are dependent on the selected place - asphoneNumber, website, north, south, east, west, priceLevel, rating
are not set on allGoogle Place
objects.
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));
[{ 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.
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
.
RNGooglePlaces.getAutocompletePredictions('facebook')
.then((results) => this.setState({ predictions: results }))
.catch((error) => console.log(error.message));
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
, andcities
). (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 iflongitude
is given)longitude
(Number) - Longitude of the point around which you wish to retrieve place information (required iflatitude
is given)radius
(Number) - Radius (in kilo-meters) within which to retrieve place information. Only works iflatitude
andlongitude
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 to0.1
.
[ { 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' ],
...
]
RNGooglePlaces.lookUpPlaceByID('ChIJZa6ezJa8j4AR1p1nTSaRtuQ')
.then((results) => console.log(results))
.catch((error) => console.log(error.message));
{ 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',
}
const placeIDs = ['ChIJZa6ezJa8j4AR1p1nTSaRtuQ', 'other_place_id'];
RNGooglePlaces.lookUpPlacesByIDs(placeIDs)
.then((results) => console.log(results))
.catch((error) => console.log(error.message));
[
{ 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.
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.
- 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.
You have to link dependencies and re-run the build:
- Run
react-native link
- Try
Manual Linking With Your Project
steps above. - Run
react-native run-ios
- Run "android" and make sure every packages is updated.
- 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
andGoogle 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' }
The MIT License.