Package selection guidance compiled from public package information, community data, and project usage.
geoflutterfire_plus is a Flutter package that extends Firebase Firestore functionality by enabling geospatial data storage and querying. It allows developers to store documents with geographic coordinates and perform location-based queries, such as finding nearby points of interest or filtering results within a radius. Built on top of Firestore, it simplifies working with geolocation in mobile and web applications. The package supports all major platforms including Android, iOS, Web, macOS, and Windows, making it ideal for cross-platform apps requiring real-time location awareness.
Use cases
Finding nearby users or locations
Real-time location-based filtering
Geofencing in mobile apps
Location-aware dashboards
Tracking moving objects
Proximity search in social apps
Key features
Geospatial document indexing
Radius-based queries
Integration with Firestore
Cross-platform support
Simple API for location queries
Automatic coordinate handling
Suitable for
Location-based services
Social networking apps
Delivery and ride-sharing apps
Travel and mapping tools
Real-time tracking systems
Apps requiring proximity detection
Considerations
Requires Firestore with geospatial indexes
Higher data usage for frequent location updates
Limited to Firestore's free tier limits
Needs proper error handling for network issues
May impact performance with large datasets
Depends on accurate device location permissions
Original README
Original README snapshot from the linked source repository. Visit the repository for the latest content.
geoflutterfire_plus 🌍
geoflutterfire_plus allows your Flutter apps to query geographic data saved in Cloud Firestore.
This package is forked from GeoFlutterFire and whole codes are redesigned with some new features, and will be maintained to work with latest Flutter SDK, Dart SDK, and other dependency packages.
Getting started
Prerequisites are following.
Dart: '>=2.17.0 <3.0.0'
Flutter: '>=2.10.0'
Run this command in your project.
flutter pub add geoflutterfire_plus
Or, add dependency to your pubspec.yaml.
dependencies:geoflutterfire_plus:<latest-version>
Geohash and geo queries
Refer to Firebase official document Geo queries to understand what Geohash is, why you need to save geo location as Geohash, and how to query them. It will also help you understand limitations of using Geohashes for querying locations.
Save geo data
In order to save geo data as documents of Cloud Firestore, use GeoFirePoint. GeoFirePoint.data gives geopoint (GeoPoint type defined in cloud_firestore package) and Geohash string.
// Define GeoFirePoint by instantiating GeoFirePoint with latitude and longitude.finalGeoFirePoint geoFirePoint = GeoFirePoint(GeoPoint(35.681236, 139.767125));
// Gets GeoPoint instance and Geohash string as Map<String, dynamic>.finalMap<String, dynamic> data = geoFirePoint.data;
// {geopoint: Instance of 'GeoPoint', geohash: xn76urx66}print(data);
GeoCollectionReference instance provides add method to create a new document in the collection (internally, just calling add method of cloud_firestore).
// Adds new documents to locations collection.GeoCollectionReference<Map<String, dynamic>>(
FirebaseFirestore.instance.collection('locations'),
).add(<String, dynamic>{
'geo': geoFirePoint.data,
'name': name,
'isVisible': true,
});
Or, you can just call add or set method of cloud_firestore to save the data. For example,
// Adds new documents to locations collection.FirebaseFirestore.instance.collection('locations').add(
<String, dynamic>{
'geo': geoFirePoint.data,
'name': 'Tokyo Station',
'isVisible': true,
},
);
The created document would be like the screenshot below. Geohash string (geohash) and Cloud Firestore GeoPoint data (geopoint) is saved in geo field as map type.
In order to set or update the pair of latitude and longitude as cloud_firestore GeoPoint and also Geohash string on the specified document's given field, GeoCollectionReference.set or GeoCollectionReference.updatePoint methods are available.
// Sets a new document by giving geoFirePoint.data to 'geo' field.GeoCollectionReference(FirebaseFirestore.instance.collection('locations'))
.set(
id: 'your-document-id',
data: {
'geo': geoFirePoint.data,
'foo': 'foo',
'bar': 'bar',
},
options: SetOptions(merge: true),
);
// Updates an existing document's 'geo' field by giving GeoPoint instance.GeoCollectionReference(FirebaseFirestore.instance.collection('locations'))
.updatePoint(
id: 'your-document-id',
field: 'geo',
geopoint: GeoPoint(35.681236, 139.767125),
);
Query geo data
In order to query location documents within a 50 km radius of a given point, you will write query like the following:
Basic query
// cloud_firestore [GeoPoint] of Tokyo Station.constGeoPoint tokyoStation = GeoPoint(35.681236, 139.767125);
// Center of the geo query.finalGeoFirePoint center = GeoFirePoint(tokyoStation);
// Detection range from the center point.constdouble radiusInKm = 50;
// Field name of Cloud Firestore documents where the geohash is saved.constString field = 'geo';
// Reference to locations collection.finalCollectionReference<Map<String, dynamic>> collectionReference =
FirebaseFirestore.instance.collection('locations');
// Function to get GeoPoint instance from Cloud Firestore document data.GeoPointgeopointFrom(Map<String, dynamic> data) =>
(data['geo'] asMap<String, dynamic>)['geopoint'] asGeoPoint;
// Streamed document snapshots of geo query under given conditions.finalStream<List<DocumentSnapshot<Map<String, dynamic>>>> stream =
GeoCollectionReference<Map<String, dynamic>>(collectionReference)
.subscribeWithin(
center: center,
radiusInKm: radiusInKm,
field: field,
geopointFrom: geopointFrom,
);
Using withConverter
If you would like to use withConverter to type-safely write query, first, you need to define its entity class and factory constructors.
/// Reference to the collection where the location data is stored.final typedCollectionReference =
FirebaseFirestore.instance.collection('locations').withConverter<Location>(
fromFirestore: (ds, _) => Location.fromDocumentSnapshot(ds),
toFirestore: (obj, _) => obj.toJson(),
);
// Function to get GeoPoint instance from Location instance.GeoPoint geopointFrom: (Location location) => location.geo.geopoint;
You can write query in the same way as the first example.
// Streamed typed document snapshots of geo query under given conditions.finalStream<List<DocumentSnapshot<Location>>> stream =
GeoCollectionReference<Location>(typedCollectionReference).subscribeWithin(
center: center,
radiusInKm: radiusInKm,
field: field,
geopointFrom: geopointFrom,
);
Custom query conditions
If you would like to add custom query conditions, queryBuilder parameter of fetchWithin (fetchWithinWithDistance) / subscribeWithin (subscribeWithinWithDistance) method is available.
For example, when you filter only isVisible field is true documents, your queryBuilder would be like this:
Then, just give the queryBuilder to the parameter of fetchWithin (fetchWithinWithDistance) / subscribeWithin (subscribeWithinWithDistance) method.
🚨 Note: Custom query condition may require a composite index. If the index is not created, you will see the "[cloud_firestore/failed-precondition] The query requires an index..." error from Firestore on the debug console. You can create the index by clicking the link in the error message.
🚨 Limitation: currently limit and orderBy queries are not supported because of the geo hash query algorithm and Cloud Firestore query limitations. Alternatively documents can be sorted on client side after getting the data (documents).
Examples
If you would like to try out the features, refer to the example project.