-
Notifications
You must be signed in to change notification settings - Fork 228
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
How to add and manage session tokens in flutter project #76
Comments
Hi, I'll stick around, I'm struggling with the same topic |
If you're still struggling with this, you can manage session tokens by creating a
|
Thanks @flikkr ! I will integrate UUID package and check. |
Thanks @flikkr ! But actually, if i'm not mistaken the places autocomplete API returns a session token in the first response, and you can use that session token as many times as you want for autocomplete calls until the first call you make to the places details api (once a place was selected). What would be great is a way to handle these session tokens internally (capture it within the PlacesResponse object and reuse it with further autocomplete calls en place details calls) |
I am not very familiar with this topic. But I don't see any session token return by the API And Google seems to recommend to generate your own session token - https://developers.google.com/maps/documentation/places/web-service/session-tokens |
I created this handy class to wrap the autocomplete() of this library : Features :
import 'dart:async';
import 'package:google_maps_webservice/places.dart';
import 'package:uuid/uuid.dart';
class AutoCompleteSession {
static const Uuid uuid = Uuid();
static final _logger = AppLogger.getLogger(); // TODO provide your own logger or just use print()
final StreamController<List<Prediction>> _controller = StreamController();
final GoogleMapsPlaces _places;
final int _debounceDuration;
Timer? _debounce;
late String _sessionToken;
var _previousSearch = "";
AutoCompleteSession(this._places, this._debounceDuration) {
_resetToken();
}
/// Search for address
///
/// @remarks:
/// The session begins when the user starts typing a query,
/// and concludes when they select a place and a call to Place Details is made.
///
/// Each session can have multiple queries, followed by one place selection.
/// The API key(s) used for each request within a session must belong to the same Google Cloud Console project.
/// Once a session has concluded, the token is no longer valid; your app must generate a fresh token for each session.
/// If the sessiontoken parameter is omitted, or if you reuse a session token, the session is charged as if no session
/// token was provided (each request is billed separately).
/// @return bool TRUE if the autocomplete will search for value
bool search(final String input) {
if (_previousSearch == input.trim()) {
_logger.d("Skip autocomplete searching - same input detected");
return false;
}
_previousSearch = input.trim();
if (_debounce?.isActive ?? false) {
_debounce?.cancel();
}
if (_previousSearch == "") { // skip empty requests
_logger.d("Skip autocomplete searching - empty input");
return false;
}
_debounce = Timer(Duration(milliseconds: _debounceDuration), () async {
_places.autocomplete(input, sessionToken: _sessionToken, components: [Component(Component.country, "fr")], types: ["address"]).then((result) {
if (result.isOkay) {
_controller.add(result.predictions);
} else if(result.hasNoResults) {
_controller.add([]);
} else {
_logger.d(result.errorMessage);
_controller.addError(Exception(result.errorMessage));
}
}).catchError((err) {
_logger.d(err.errorMessage);
_controller.addError(Exception(err.errorMessage));
});
});
return true;
}
/// Get place details
///
/// @fields: Basic fields (cheap): address_component, adr_address, business_status, formatted_address, geometry, icon, icon_mask_base_uri, icon_background_color, name,
/// permanently_closed, photo, type, url, utc_offset, or vicinity
Future<PlacesDetailsResponse?> getDetails(final Prediction prediction) async {
final String? placeId = prediction.placeId;
if (placeId != null) {
if (_debounce?.isActive ?? false) {
_debounce?.cancel();
}
final result = await _places.getDetailsByPlaceId(placeId, sessionToken: _sessionToken, fields: ["place_id", "geometry", "formatted_address", "name", "type"]);
_resetToken();
return result;
}
return null;
}
/// Get stream
Stream<List<Prediction>> stream() {
return _controller.stream;
}
/// Close the session
void close() {
if (_debounce?.isActive ?? false) {
_debounce?.cancel();
}
if (!_controller.isClosed) {
_controller.close();
}
}
void _resetToken() {
_sessionToken = uuid.v4().toString();
_previousSearch = "";
_logger.d("Autocomplete session - resetting token !");
}
} You can use it like this in your code : var places = GoogleMapsPlaces(apiKey: "GOOGLE PLACES API KEY");
var autocompleteSession = AutoCompleteSession(_places, 330);
// observe results in a stream an update your UI with it
autocompleteSession.stream().listen(
(results) => /* update your ui or store here */,
onError: (err) => print("err in mapAddController"),
onDone: () => print("DONE"),
);
// to search for string input
autoCompleteSession.search(input);
// then when the user click on a predictions
autoCompleteSession.getPlaceDetails(prediction); // will reset token and cleanup :)
// don't forget to close the session when UI is disposed
autoCompleteSession.close(); |
Hello,
Thanks for sharing such a useful package for integrating various Google APIs under one roof.
I am glad using it. But I am facing issues with pricing because in Google Autocomplete requests, there are a lot of queries generated without maintaining session tokens.
The APIs I use :
Please guide how to handle session tokens in flutter app to reduce pricing from Google Maps !
The text was updated successfully, but these errors were encountered: