Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Support session tokens #262

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ build/Release
node_modules
npm-debug.log

# Prettier
.prettierignore

# OSX
#
.DS_Store
Expand Down
249 changes: 138 additions & 111 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ end
##### 2) Configuration on iOS
- In your `AppDelegate.m` file, import the Google Places library by adding
```objectivec
@import GooglePlaces;
@import GoogleMaps;
@import GooglePlaces;
@import GoogleMaps;
```
on top of the file.
- Within the `didFinishLaunchingWithOptions` method, instantiate the library as follows - **read about a better way to secure this below**:
Expand All @@ -111,9 +111,9 @@ on top of the file.

```plist
<key>NSLocationWhenInUseUsageDescription</key>
<string>RNGPDemos needs your location to show you places</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>RNGPDemos needs your location to show you places</string>
<string>RNGPDemos needs your location to show you places</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>RNGPDemos needs your location to show you places</string>
```


Expand All @@ -125,7 +125,6 @@ on top of the file.

```xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
```

Expand Down Expand Up @@ -224,9 +223,9 @@ 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.
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
}
Expand All @@ -250,22 +249,21 @@ class GPlacesDemo extends Component {
To customize autocomplete results as listed for [Android](https://developers.google.com/places/android-sdk/autocomplete) and [iOS](https://developers.google.com/places/ios-sdk/autocomplete) in the official docs, you can pass an `options` object as a parameter to the `openAutocompleteModal()` method as follows:

```javascript
RNGooglePlaces.openAutocompleteModal({
initialQuery: 'vestar',
locationRestriction: {
latitudeSW: 6.3670553,
longitudeSW: 2.7062895,
latitudeNE: 6.6967964,
longitudeNE: 4.351055
},
country: 'NG',
type: 'establishment'
}, ['placeID', 'location', 'name', 'address', 'types', 'openingHours', 'plusCode', 'rating', 'userRatingsTotal', 'viewport']
)
.then((place) => {
console.log(place);
})
.catch(error => console.log(error.message));
RNGooglePlaces.openAutocompleteModal({
initialQuery: 'vestar',
locationRestriction: {
latitudeSW: 6.3670553,
longitudeSW: 2.7062895,
latitudeNE: 6.6967964,
longitudeNE: 4.351055
},
country: 'NG',
type: 'establishment'
}, [
'placeID', 'location', 'name', 'address', 'types', 'openingHours', 'plusCode', 'rating', 'userRatingsTotal', 'viewport'
])
.then((place) => console.log(place))
.catch(error => console.log(error.message));
```
**OPTIONS**
- **`type`** _(String)_ - The type of results to return. Can only be one of (`geocode`, `address`, `establishment`, `regions`, and `cities`). *(optional)*
Expand All @@ -285,61 +283,54 @@ To customize autocomplete results as listed for [Android](https://developers.goo

#### Example Response from the Autocomplete Modal
```javascript
{ priceLevel: 0,
viewport: {
longitudeSW: 3.320172219708498,
latitudeSW: 6.572546249999999,
longitudeNE: 3.322870180291502,
latitudeNE: 6.584909250000001
},
address: 'Lagos, Nigeria',
location: {
longitude: 3.3211348,
latitude: 6.5818185
},
addressComponents: [
{ shortName: 'Lagos',
name: 'Lagos',
types: [ 'locality', 'political' ]
},
{ shortName: 'LA',
name: 'Lagos',
types: [ 'administrative_area_level_1', 'political' ]
},
{ shortName: 'NG',
name: 'Nigeria',
types: [ 'country', 'political' ]
}
],
userRatingsTotal: 939,
plusCode: {
globalCode: '6FR5H8JC+PF',
compoundCode: 'H8JC+PF Lagos, Nigeria'
},
rating: 3.2,
types: [ 'airport', 'point_of_interest', 'establishment' ],
attributions: [],
placeID: 'ChIJhRTXUeeROxARmk_Rp3PtIvI',
name: 'Murtala Muhammed International Airport'
{
priceLevel: 0,
viewport: {
longitudeSW: 3.320172219708498,
latitudeSW: 6.572546249999999,
longitudeNE: 3.322870180291502,
latitudeNE: 6.584909250000001
},
address: 'Lagos, Nigeria',
location: {
longitude: 3.3211348,
latitude: 6.5818185
},
addressComponents: [
{ shortName: 'Lagos', name: 'Lagos', types: [ 'locality', 'political' ] },
{ shortName: 'LA', name: 'Lagos', types: [ 'administrative_area_level_1', 'political' ] },
{ shortName: 'NG', name: 'Nigeria', types: [ 'country', 'political' ] }
],
userRatingsTotal: 939,
plusCode: {
globalCode: '6FR5H8JC+PF',
compoundCode: 'H8JC+PF Lagos, Nigeria'
},
rating: 3.2,
types: [ 'airport', 'point_of_interest', 'establishment' ],
attributions: [],
placeID: 'ChIJhRTXUeeROxARmk_Rp3PtIvI',
name: 'Murtala Muhammed International Airport'
}
```

- 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. Ensure you have required the appropriate permissions, as stated post-install steps above, before making this request.

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

OR

```javascript
RNGooglePlaces.getCurrentPlace(['placeID', 'location', 'name', 'address'])
.then((results) => console.log(results))
.catch((error) => console.log(error.message));
RNGooglePlaces.getCurrentPlace(['placeID', 'location', 'name', 'address'])
.then((results) => console.log(results))
.catch((error) => console.log(error.message));
```
**PLACE FIELDS**
- To prevent yourself from incurring huge usage bill, you can select the result fields you need in your application. Pass an *(optional)* `placeFields` as the only param to `getCurrentPlace`.
Expand All @@ -350,7 +341,8 @@ OR
#### Example Response from Calling getCurrentPlace()

```javascript
[{ name: 'Facebook HQ',
[{
name: 'Facebook HQ',
website: 'https://www.facebook.com/',
longitude: -122.14835169999999,
address: '1 Hacker Way, Menlo Park, CA 94025, USA',
Expand All @@ -370,43 +362,77 @@ The sum of the likelihoods in a given result set is always less than or equal to
### 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`.

#### Session Tokens (and why you should care)

Recommended read:
* [Places API - Session Tokens](https://developers.google.com/places/web-service/session-tokens)
* [Places API - Usage and Billing](https://developers.google.com/places/web-service/usage-and-billing)

Calling the following methods (`getAutocompletePredictions` and `lookUpPlaceByID`) without a session token can result in unwanted expensive bills from Google. This happens because the Places APIs are billed by SKU. Usage is tracked for each Product SKU, and an API may have more than one Product SKU (more on the **Usage and Billing** link above).

This module exposes a function named `beginAutocompleteSession` that once invoked will generate a **Session Token** on the module instance. This Session Token will be reused for each subsequent `getAutocompletePredictions` and `lookUpPlaceByID` calls. As of October 2019, Session Tokens **MUST** be renewed upon calling `lookUpPlaceByID`, as this API call marks the "end" of a session for billing purposes. **FORGETTING TO GENERATE A NEW SESSION TOKEN AFTER CALLING `lookupPlaceById` CAN INCREASE YOUR BILL**.

Example of how an Autocomplete Session would look like:

```javascript
// Generate session token
RNGooglePlaces.beginAutocompleteSession();

// You might call this several times (as the user is typing his query)
RNGooglePlaces.getAutocompletePredictions('facebook')
.then((results) => this.setState({ predictions: results }))
.catch((error) => console.log(error.message));

// Lookup a place by its ID
RNGooglePlaces.lookUpPlaceByID('ChIJZa6ezJa8j4AR1p1nTSaRtuQ');

// Generate new session token in case your user cancels his selection and wants to continue searching
RNGooglePlaces.beginAutocompleteSession();
```

In case you want to make Places API calls without using a session token, a function named `cancelAutocompleteSession` is also exposed. Invoking it will erase an existing Session Token.

```javascript
RNGooglePlaces.cancelAutocompleteSession();
```

#### Get Autocomplete Predictions

```javascript
RNGooglePlaces.getAutocompletePredictions('facebook')
.then((results) => this.setState({ predictions: results }))
.catch((error) => console.log(error.message));
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](https://developers.google.com/places/android-api/autocomplete#restrict_autocomplete_results) and [iOS](https://developers.google.com/places/ios-api/autocomplete#call_gmsplacesclient) in the official docs, you can pass an `options` object as a second parameter to the `getAutocompletePredictions()` method as follows:

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

```javascript
RNGooglePlaces.getAutocompletePredictions('pizza', {
type: 'establishments',
locationBias: {
latitudeSW: 6.3670553,
longitudeSW: 2.7062895,
latitudeNE: 6.6967964,
longitudeNE: 4.351055
}
})
.then((place) => {
console.log(place);
})
.catch(error => console.log(error.message));
type: 'establishments',
locationBias: {
latitudeSW: 6.3670553,
longitudeSW: 2.7062895,
latitudeNE: 6.6967964,
longitudeNE: 4.351055
}
})
.then((place) => {
console.log(place);
})
.catch(error => console.log(error.message));
```


Expand All @@ -422,34 +448,34 @@ RNGooglePlaces.getAutocompletePredictions('pizza', {
#### Example Response from Calling getAutocompletePredictions()

```javascript
[ { 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' ],

...
]
[{
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

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

```javascript
RNGooglePlaces.lookUpPlaceByID('ChIJZa6ezJa8j4AR1p1nTSaRtuQ', ['placeID', 'location', 'name', 'address'])
.then((results) => console.log(results))
.catch((error) => console.log(error.message));
RNGooglePlaces.lookUpPlaceByID('ChIJZa6ezJa8j4AR1p1nTSaRtuQ', ['placeID', 'location', 'name', 'address'])
.then((results) => console.log(results))
.catch((error) => console.log(error.message));
```


Expand All @@ -461,7 +487,8 @@ OR
#### Example Response from Calling lookUpPlaceByID()

```javascript
{ name: 'Facebook HQ',
{
name: 'Facebook HQ',
website: 'https://www.facebook.com/',
longitude: -122.14835169999999,
address: '1 Hacker Way, Menlo Park, CA 94025, USA',
Expand Down
Loading