Google_Maps_Places_Autocomplete_Widgets
Three interchangeable Google Places backends — same widgets, same results:
- ✅ Places API (New) (default) — modern REST API, works on every platform including Flutter web
- ✅ Legacy Places API — one parameter (
apiVersion: PlacesApiVersion.legacy) for older Cloud projects where it is still enabled- ✅ Native Places SDKs for Android/iOS — via the companion package
google_maps_places_autocomplete_widgets_native: app-restricted API keys with zero configuration, plus optional Firebase App Check attestation so a leaked or scraped key cannot be abused outside your genuine app…or inject any custom backend (e.g. a key-hiding server proxy) via
placeApiProvider:.
Feature complete, 'drop in' replacements for Flutter TextField or TextFormField widgets, providing address autocompletion using the Google Maps Places API.
The only required additional parameter is your Google Maps API key
(or omit it entirely and supply your own placeApiProvider backend).
Just rename TextField -> AddressAutocompleteTextField,
(or TextFormField -> AddressAutocompleteTextFormField),
and add your mapsApiKey:'YOUR_GOOGLE_MAPS_API_KEY' as the only required additional parameter.
As of v2.0.0 the widgets use Places API (New) by default (the legacy
Places API cannot be enabled on new Google Cloud projects). Make sure
"Places API (New)"
is enabled for your API key's project. Existing 1.x users: see
MIGRATION.md — for most apps no code changes are needed. To
temporarily keep using the legacy API, pass apiVersion: PlacesApiVersion.legacy.
If desired customize any look/behavior of the autocompletion using the additional optional parameters.
Additionally any of the other Google Places autocomplete information can be retrieved.
- Postal code/Zip code autocompletion is supported using the
type:AutoCompleteType.postalCodeparameter. - Cities autocompletion is supported using the
type:AutoCompleteType.citiesparameter.
(type:AutoCompleteType.citiesreturns anyAutoCompleteType.localityorAutoCompleteType.administrativeAreaLevel_3matched). - Businesses and Establishment autocompletion is supported using the
type:AutoCompleteType.establishmentparameter. - Region autocompletion is supported using the
type:AutoCompleteType.regionsparameter.
(AutoCompleteType.regionsreturns anyAutoCompleteType.locality,AutoCompleteType.sublocality,AutoCompleteType.postal_code,AutoCompleteType.country,AutoCompleteType.administrativeAreaLevel_1orAutoCompleteType.administrativeAreaLevel_2matched) - Or you can combine up to 5 of the
AutoCompleteTypeenums using thetypesparameter
(eg.types:[AutoCompleteType.bookStore,AutoCompleteType.bicycleStore,AutoCompleteType.school]).
(See Table 3, Table 1, and Table 2).
Easily incorporated into existing forms which contain multiple fields for capturing address information.
Demo

Features
- Uses Google Places API (New) by default; the legacy Places API remains
available via
apiVersion: PlacesApiVersion.legacy. - Supports application-restricted API keys via
androidPackageName,androidCertSha1FingerprintandiosBundleId(sent as Google'sX-Android-Package/X-Android-Cert/X-Ios-Bundle-Identifierheaders). For the strongest client-side key protection (native SDK identity + optional Firebase App Check attestation) use the companion packagegoogle_maps_places_autocomplete_widgets_nativeon Android/iOS. - Pluggable backend: implement the public
PlaceApiProviderabstract class and pass it asplaceApiProvider:to use your own proxy/native backend (also handy as a fake in widget tests). - Flutter web now works (with the default new API):
places.googleapis.comsupports CORS, so browsers can call it directly — use a referrer-restricted key. The legacy API never worked on web (its endpoint sends no CORS headers). - Support for most common
TextFieldandTextFormFieldparameters (and any less common parameter can easily be added). - Support for both address and postal/zip code autocompletion. (
type:AutoCompleteType.addressortype:AutoCompleteType.postalCode) - Support for ANY of other the Google Places autocompletion types (See Table 3, Table 1, and Table 2)
- Robust set of optional callbacks that all customizing behavior in virtually any way.
- Easy 'drop in' replacement of address field in any flutter form.
- Easy customization of virtually every look and feel display/behavior property.
- Hooks allow filling multiple form fields (City, State, Zip, etc.) from results of user's address selection from the initial address form field autocomplete suggestions.
- Hooks to allow clearing of multiple other form fields when the clear button is used in the address autocomplete widget.
- Ability to customize the search query string with contents of other form fields before querying google maps places api.
- Ability to use the contents of the autocomplete suggestion without additional google maps places details api request.
- The base classes and mixin generics provided in this package allow for the addition of address autocompletion to virtually any of custom widgets.
Securing your Google Maps API key
Any API key that ships inside an app binary or web page can be extracted — from an APK/IPA, from browser dev tools, or by sniffing traffic — and a leaked Places key can be abused to run up your bill. Places API (New) gives you escalating levels of protection, all supported by this package family:
| Approach | Platforms | Protection | |
|---|---|---|---|
| 1 | Restricted key + this package's androidPackageName: / androidCertSha1Fingerprint: / iosBundleId: parameters (sent as Google's restriction headers over REST) |
all | Deterrent only — these header values are public information, so they stop key-scraping bots and accidental reuse, not determined attackers |
| 2 | google_maps_places_autocomplete_widgets_native — the companion package backing these same widgets with Google's native Places SDKs |
Android, iOS | The SDK attaches your app's identity (package + signing cert / bundle id) itself, so app-restricted keys work with zero configuration and can't be borrowed by simply copying headers |
| 3 | The native package with Firebase App Check enabled (useAppCheck: true) |
Android, iOS | Cryptographic app attestation (Play Integrity / App Attest). With enforcement turned on, Google rejects every request that doesn't come from your genuine app — a scraped or leaked key becomes useless |
| 4 | Your own backend proxy injected via placeApiProvider: |
all | Strongest: the key lives on your server and never ships to clients at all |
On web, use an HTTP-referrer-restricted key (the browser itself enforces nothing — tier 4 is the only strong option there). Whatever the tier, also set API restrictions (key valid only for Places API (New)) and quota caps in the Cloud console.
Using the native Places SDK backend (Android/iOS)
The companion package drops into the same widgets — initialize once at
startup and inject its provider (no mapsApiKey: on the widget at all,
since core 2.1.0):
await NativePlaceApiProvider.initialize(
mapsApiKey: yourKey,
useAppCheck: true, // opt-in Firebase App Check attestation (tier 3)
);
AddressAutocompleteTextField(
placeApiProvider: NativePlaceApiProvider(componentCountry: 'us'),
onSuggestionClick: onSuggestionClick,
),
Everything else about the widgets — callbacks, styling, the parsed Place
results — is identical on either backend. See
that package's README
for platform setup and a step-by-step App Check walkthrough (Firebase
project, debug tokens, monitoring, and flipping on enforcement). The full
flow — including a leaked key being rejected under enforcement while the
real app keeps working — has been verified end-to-end on physical devices.
Usage
You can find a complete example of usage in example/lib/main.dart.
import the package:
import 'package:google_maps_places_autocomplete_widgets/address_autocomplete_widgets.dart';
Add your google places api key, optional onSuggestionClick callback,
and optional language and country restrictions parameters:
AddressAutocompleteTextField(
mapsApiKey: 'YOUR GOOGLE MAPS API KEY HERE',
onSuggestionClick: onSuggestionClick,
componentCountry: 'us',
language: 'en-US'
//..any other arguments that you would use with a TextField..
),
or
AddressAutocompleteTextFormField(
mapsApiKey: 'YOUR GOOGLE MAPS API KEY HERE',
onSuggestionClick: onSuggestionClick,
componentCountry: 'us',
language: 'en-US'
//..any other arguments that you would use with a TextFormField..
),
To utilize any of the robust set of retrieved Place details write a
onSuggestionClick callback function:
void onSuggestionClick(Place placeDetails) {
setState(() {
// examples of the returned address details
_name = placeDetails.name;
_formattedAddress = placeDetails.formattedAddress;
_formattedAddressZipPlus4 = placeDetails.formattedAddressZipPlus4;
_streetAddress = placeDetails.streetAddress;
_streetNumber = placeDetails.streetNumber;
_street = placeDetails.street;
_streetShort = placeDetails.streetShort;
_city = placeDetails.city;
_county = placeDetails.county;
_state = placeDetails.state;
_stateShort = placeDetails.stateShort;
_zipCode = placeDetails.zipCode;
_zipCodeSuffix = placeDetails.zipCodeSuffix;
_zipCodePlus4 = placeDetails.zipCodePlus4;
_country = placeDetails.country;
_vicinity = placeDetails.vicinity;
_lat = placeDetails.lat;
_lng = placeDetails.lng;
});
}
Notes when using Places API (New) (the default)
- The legacy
addresstype filter has no equivalent in the new API;AutoCompleteType.address(the default) is translated tostreet_address+premise+subpremise. Usetype: AutoCompleteType.geocodefor broader geocoding matches. Suggestion.termsis alwaysnull(no new-API equivalent).- See MIGRATION.md for key-restriction setup and custom
placeApiProviderbackends.
More complex use and customization examples
A complete example mobile/desktop applications illustrates the use of both common and optional parameters. This includes the use of the address autocomplete TextFormField widget to fill multiple other TextFormFields from the user's selected address suggestion.
Additional information
This package follows the official Google Maps Places API documentation. The
autocomplete requests use your chosen type/types filters (defaulting to
address results) and the details request retrieves the address components,
formatted address and location used to populate the returned Place.
GitHub Repo: https://github.com/timmaffett/google_maps_places_autocomplete_widgets
Acknowledgements
This package was originally based on source code from the package
maps_places_autocomplete 0.0.2 by @leandro-zanardi. As I customized my use case
within my own apps the source code diverged significantly from the original package
and it was easiest for me to create my own new package.
The rather unfortunate (and long) name for this package is a result of the pub.dev namespace clutter of various packages also using Google Maps Places API.
Libraries
- address_autocomplete_widgets
- Use AddressAutocompleteTextField to replace TextField widgets where you want to add Google Places autocompletion.
Use AddressAutocompleteTextFormField to replace TextFormField widgets where you want to add Google Places autocompletion.
You only requirement is to supply your Google Maps API key in the
mapsApiKeyparameter. You optionally can specify the type of Google Places autocomplete information returned using thetypeortypesparameters (The default is AutoCompleteType.address). - api/autocomplete_types
- api/legacy_place_api_provider
- api/new_api_type_mapping
- api/new_place_api_provider
- api/place_api_provider
- api/place_builder
- api/places_api_version
- model/place
- model/suggestion
- service/address_service
- widgets/address_autocomplete_generic
- widgets/address_autocomplete_textfield
- widgets/address_autocomplete_textformfield