google_places_sdk_flutter 0.6.1 copy "google_places_sdk_flutter: ^0.6.1" to clipboard
google_places_sdk_flutter: ^0.6.1 copied to clipboard

Cross-platform Google Places autocomplete widgets and clients built on Places API (New).

Google Places SDK Flutter #

pub package CI

A cross-platform Google Places client and autocomplete widget toolkit for Flutter. Use the ready-made widget for a quick place picker, or use the typed client APIs when the application needs more control.

Contents #

Preview #

Package example

Quick start #

Add the package:

flutter pub add google_places_sdk_flutter

Create a client and pass it to PlacesAutocompleteField:

import 'package:flutter/material.dart';
import 'package:google_places_sdk_flutter/google_places_sdk_flutter.dart';

class PlacePicker extends StatefulWidget {
  const PlacePicker({super.key});

  @override
  State<PlacePicker> createState() => _PlacePickerState();
}

class _PlacePickerState extends State<PlacePicker> {
  final _client = PlacesClient(
    apiKey: const String.fromEnvironment('GOOGLE_MAPS_API_KEY'),
  );

  @override
  void dispose() {
    _client.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return PlacesAutocompleteField(
      client: _client,
      decoration: const InputDecoration(
        labelText: 'Choose a place',
        border: OutlineInputBorder(),
      ),
      onSelection: (selection) {
        debugPrint(selection.displayText);
      },
    );
  }
}

Pass the key when running the application:

flutter run --dart-define=GOOGLE_MAPS_API_KEY=your_key_here

On web, the same client uses the Google Maps JavaScript Places library. Before shipping, apply the correct Google API and application restrictions. REST-only web operations should use the authenticated proxy described in the security guide.

Common usage #

Load place details after selection #

Enable details loading when the selection callback needs an address, coordinates, or other Place data:

PlacesAutocompleteField(
  client: client,
  fetchPlaceDetailsOnSelection: true,
  selectionFields: PlaceFieldPresets.recommended,
  onSelection: (selection) {
    debugPrint(selection.place?.formattedAddress);
    debugPrint(selection.place?.location?.toString());
  },
)

Use the field inside a Form #

PlacesAutocompleteFormField supports normal Flutter validation and reset behavior:

final formKey = GlobalKey<FormState>();

Form(
  key: formKey,
  child: PlacesAutocompleteFormField(
    client: client,
    validator: (selection) =>
        selection == null ? 'Choose a place.' : null,
  ),
);

formKey.currentState!.reset();

Use PlacesAutocompleteOverlay.show() when the search should open in a dialog or fullscreen page instead of appearing inline.

Search without a widget #

The client also supports Place Details, Text Search, Nearby Search, Time Zone, and Place Photos:

final results = await client.searchText(
  const TextSearchRequest(
    textQuery: 'coffee near me',
    pageSize: 10,
  ),
);

for (final place in results) {
  debugPrint(place.displayName?.text);
}

Use searchTextPage() only when pagination metadata is needed:

final page = await client.searchTextPage(
  const TextSearchRequest(
    textQuery: 'coffee near me',
    pageSize: 10,
  ),
);

if (page.nextPageToken case final token?) {
  final nextPage = await client.searchTextPage(
    TextSearchRequest(
      textQuery: 'coffee near me',
      pageSize: 10,
      pageToken: token,
    ),
  );
  debugPrint('${nextPage.results.length} more places');
}

Show the distance to each suggestion #

Set origin and Google returns a distance for every suggestion, which the field renders beside it:

PlacesAutocompleteField(
  client: client,
  origin: const PlaceCoordinates(latitude: 40.7580, longitude: -73.9855),
)

Two things to know before you use it:

  • Distances are straight-line, not driving or walking distance. They will not match what a maps app shows for the same pair.
  • origin only computes the number. It does not change which places are returned — use locationBias or locationRestriction for that.

Without origin, no distance is requested and none is rendered. That is the default.

Using the device's location as the origin

This package never requests location permission, and does not depend on any location library. Your app fetches the coordinates and passes them in. Any package works; the example below uses geolocator.

Add the platform configuration first, or the request fails at runtime:

android/app/src/main/AndroidManifest.xml, inside <manifest>:

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

ios/Runner/Info.plist, inside the top-level <dict>:

<key>NSLocationWhenInUseUsageDescription</key>
<string>Used to show how far each place is from you.</string>

On web the browser prompts on its own, but the page must be served over HTTPS (or localhost). macOS needs a location entitlement in both macos/Runner/DebugProfile.entitlements and Release.entitlements. Desktop support otherwise depends on the location package you choose, not on this one.

Then resolve the coordinates and hand them to the field:

class _SearchPageState extends State<SearchPage> {
  PlaceCoordinates? _origin;

  @override
  void initState() {
    super.initState();
    _loadOrigin();
  }

  Future<void> _loadOrigin() async {
    if (!await Geolocator.isLocationServiceEnabled()) {
      return;
    }
    var permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
    }
    if (permission == LocationPermission.denied ||
        permission == LocationPermission.deniedForever) {
      return;
    }
    final position = await Geolocator.getCurrentPosition();
    if (!mounted) {
      return;
    }
    setState(() {
      _origin = PlaceCoordinates(
        latitude: position.latitude,
        longitude: position.longitude,
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return PlacesAutocompleteField(client: widget.client, origin: _origin);
  }
}

Every early return leaves _origin as null, so search keeps working and simply shows no distances. Denying permission degrades the feature rather than breaking the field.

A first GPS fix can take several seconds. Resolving it in initState as above means the field is usable immediately and distances appear once the fix lands — do not block the search on it.

Display photo attribution #

When a returned photo includes authors, display Google's supplied attribution beside the image:

PlacesPhotoAttribution(photo: photo)

PlacePhoto.authors is available when a custom attribution layout is needed.

What's new #

Version 0.6.1 is a bug-fix release. Dialog and fullscreen modes now honor the field's decoration, suggestionBuilder, showPoweredByGoogle, onClearField, and enabled; Retry works on web; and the new origin option makes Google return a distance for each suggestion, which the widget renders.

It also contains a security fix: photo media no longer sends the API key as a URL query parameter. Rotate any key used with fetchPhotoMedia on 0.5.00.6.0.

Version 0.6.0 added Text Search pagination, cancellation, typed errors, richer Place data, complete Form reset behavior, photo attribution helpers, and safer proxy and web options. There are no public API removals or required source migrations in either release. Text Search maxResultCount, string proxyBaseUrl, and direct browser REST fallback are deprecated, with replacements available now.

See What's new in 0.6.1 and What's new in 0.6.0 for examples, compatibility notices, and the extended feature summaries.

Advanced usage #

The sections below are for applications that need headless autocomplete, explicit cancellation, custom transports, or detailed error handling. The quick-start widget manages these concerns automatically for normal use.

Headless autocomplete sessions #

Reuse one session token for a headless autocomplete flow and pass it to Place Details. End abandoned sessions explicitly:

final sessionToken = AutocompleteSessionToken.generate();

final suggestions = await client.autocomplete(
  AutocompleteRequest(
    input: 'coffee',
    sessionToken: sessionToken,
  ),
);

if (suggestions.isEmpty) {
  await client.endAutocompleteSession(sessionToken);
} else {
  final place = await client.fetchPlace(
    PlaceDetailsRequest(
      placeId: suggestions.first.placeId,
      sessionToken: sessionToken,
    ),
  );
  debugPrint(place.displayName?.text);
}

Use autocompleteSuggestions() with includeQueryPredictions: true when the application also accepts suggested search phrases instead of only places.

Cancel work that is no longer needed #

Every client operation accepts an optional cancellation token:

final cancellation = PlacesCancellationToken();

final request = client.searchText(
  const TextSearchRequest(textQuery: 'coffee'),
  cancellationToken: cancellation,
);

cancellation.cancel();
await request;

HTTP transports abort the request. Maps JavaScript safely ignores a late completion and reports a typed cancellation error.

Secure proxy and platform identity #

Use a keyless authenticated proxy client when the application should not carry a Google web-service key:

final client = PlacesClient.proxy(
  placesEndpoint: Uri.parse('https://api.example.com/maps/places/v1'),
  timeZoneEndpoint: Uri.parse('https://api.example.com/maps/timezone'),
  authentication: (_) async => <String, String>{
    'Authorization': 'Bearer ${await session.currentAccessToken()}',
  },
);

The proxy must authenticate clients, allowlist operations, enforce quotas, and add its restricted Google credential server-side. The package never forwards a Google key to configured proxy endpoints.

PlacesProxyConfiguration can combine Maps JavaScript with proxy fallback. PlacesApplicationIdentity.android() and .ios() can add Google's documented application identity headers for direct mobile REST calls.

See Security and transport configuration for the setup guide, transport matrix, CSP options, and direct-fallback risks.

Typed errors and HTTP ownership #

All package-generated failures are PlacesException values:

try {
  await client.searchText(
    const TextSearchRequest(textQuery: 'coffee'),
  );
} on PlacesException catch (error) {
  debugPrint('${error.kind.name}: ${error.message}');
  if (error.retryable) {
    // Offer a retry action.
  }
}

An injected http.Client remains caller-owned by default. Transfer ownership only when PlacesClient.close() should also close it:

final client = PlacesClient(
  apiKey: apiKey,
  httpClient: injectedClient,
  options: const PlacesClientOptions(
    httpClientOwnership: PlacesHttpClientOwnership.placesClient,
  ),
);

HTTP client injection is unsupported on web.

Common options #

Option Default Use when
fieldMode inline You want inline, dialog, or fullscreen UI.
languageCode null You want localized Google results.
regionCode null You want region-aware ranking or formatting.
locationBias null You prefer results near an area.
locationRestriction null You only want results inside an area.
includedPrimaryTypes empty You want types such as restaurant or (cities).
fetchPlaceDetailsOnSelection false The selection needs full Place data.
fetchTimeZoneOnSelection false The selection needs Time Zone data.
selectionFields recommended You want to control the details payload.
includeQueryPredictions false You also accept suggested search phrases.
maxSuggestions 5 You want fewer than Google's five suggestions.
showPoweredByGoogle true The package should render Google attribution.

locationBias and locationRestriction cannot be used together.

Example app #

The example application demonstrates inline and Form fields, dialog and fullscreen modes, locale and RTL behavior, Text Search pagination, Place details, Time Zone data, and proxy configuration.

Run it with:

cd example
flutter run --dart-define=GOOGLE_MAPS_API_KEY=your_key_here

More documentation #

9
likes
160
points
1.66k
downloads
screenshot

Documentation

API reference

Publisher

verified publishereventer.co.il

Weekly Downloads

Cross-platform Google Places autocomplete widgets and clients built on Places API (New).

Repository (GitHub)
View/report issues

Topics

#flutter #autocomplete #google-maps #places #address

License

BSD-3-Clause (license)

Dependencies

flutter, http, web

More

Packages that depend on google_places_sdk_flutter