geocoder_pro 1.1.0
geocoder_pro: ^1.1.0 copied to clipboard
A powerful Flutter package for forward and reverse geocoding with Google Maps and free OpenStreetMap (Nominatim), spatial distance, and address utilities.
Geocoder Pro #
A powerful, developer-friendly Flutter and Dart package for forward and reverse geocoding. Supports both Google Maps Geocoding API and free OpenStreetMap (Nominatim), spatial distance calculations, compass bearings, geofencing, and typed error handling.
π Highlights & Features #
- π Free OpenStreetMap (Nominatim) Support β Geocode without needing an API key or credit card.
- π Google Maps Geocoding API β Full enterprise Google Maps support with component filtering, bounding boxes, and region biasing.
- π Forward & Reverse Geocoding β Convert addresses to geographic coordinates and coordinates back to human-readable addresses.
- π Multiple Results Support β Fetch lists of matching locations, not just the single top result.
- π Spatial & Geolocation Utilities (
GeoUtils) β Calculate Haversine distances (meters, km, miles), compass bearings, radius geofencing, and DMS coordinate conversions. - π‘οΈ Typed Exceptions β Clean, predictable error handling (
ApiKeyException,QuotaExceededException,NetworkException,NotFoundException). - π Modern & Immutable Models β Fully immutable
GeoData,GeoCoordinates, andGeoBoundswithcopyWith, JSON serialization, equality, and hash codes. - π§ͺ Test-Ready Architecture β Inject custom
http.Clientinstances to easily mock and test geocoding in your apps. - π― 100% Backward Compatible β Existing code using
GeocoderPro.getDataFromCoordinatesorGeocoderPro.getDataFromAddresscontinues to work seamlessly.
π Providers Overview #
| Feature | OpenStreetMap (Nominatim) | Google Maps API |
|---|---|---|
| API Key Required | β No (100% Free) | β Yes |
| Forward Geocoding | β Yes | β Yes |
| Reverse Geocoding | β Yes | β Yes |
| Multiple Results | β Yes | β Yes |
| Language Support | β Yes | β Yes |
| Component Filtering | β Country codes | β Countries, postal codes, admin areas |
| Bounding Box Bias | β Yes | β Viewport & Bounds |
π¦ Installation #
Add geocoder_pro to your pubspec.yaml:
dependencies:
geocoder_pro: ^1.1.0
Then import the library:
import 'package:geocoder_pro/geocoder_pro.dart';
π Quick Start #
1. Free OpenStreetMap Geocoding (No API Key Required) #
// Forward Geocoding (Address -> Coordinates)
final geoData = await GeocoderPro.nominatim().getDataFromAddress('Eiffel Tower, Paris');
if (geoData != null) {
print('Address: ${geoData.formattedAddress}');
print('Latitude: ${geoData.latitude}, Longitude: ${geoData.longitude}');
print('City: ${geoData.city}, Country: ${geoData.country}');
}
// Reverse Geocoding (Coordinates -> Address)
final reverseData = await GeocoderPro.nominatim().getDataFromCoordinates(
latitude: 48.8584,
longitude: 2.2945,
);
print('Resolved Address: ${reverseData?.formattedAddress}');
2. Google Maps Geocoding #
// Initialize Google Geocoder
final googleGeocoder = GeocoderPro.google(apiKey: 'YOUR_GOOGLE_MAPS_API_KEY');
// Forward Geocoding
final data = await googleGeocoder.getDataFromAddress(
'1600 Amphitheatre Pkwy, Mountain View, CA',
language: 'en',
);
print('Coordinates: ${data?.latitude}, ${data?.longitude}');
print('State: ${data?.state}, Postal Code: ${data?.postalCode}');
// Reverse Geocoding
final loc = await googleGeocoder.getDataFromCoordinates(
latitude: 37.4220,
longitude: -122.0841,
);
print('Formatted Address: ${loc?.formattedAddress}');
3. Static Helper Methods (Backward Compatible) #
Existing static methods remain fully supported:
// Google Maps Reverse Geocoding
GeoData? data = await GeocoderPro.getDataFromCoordinates(
latitude: 40.714224,
longitude: -73.961452,
googleMapApiKey: 'YOUR_API_KEY',
language: 'en',
);
// Google Maps Forward Geocoding
GeoData? place = await GeocoderPro.getDataFromAddress(
address: '277 Bedford Ave, Brooklyn, NY 11211, USA',
googleMapApiKey: 'YOUR_API_KEY',
);
You can also use the provider-agnostic fromAddress and fromCoordinates methods which automatically default to OpenStreetMap if no API key is specified:
// Automatically uses OpenStreetMap when apiKey is omitted
final data = await GeocoderPro.fromAddress('Colosseum, Rome');
4. Fetching Multiple Matching Locations #
final List<GeoData> results = await GeocoderPro.nominatim()
.getAddressesFromAddress('Springfield', limit: 5);
for (final item in results) {
print('${item.formattedAddress} -> (${item.latitude}, ${item.longitude})');
}
π Spatial Utilities & Distance Calculations #
GeocoderPro includes spatial tools powered by the Haversine formula:
const nyLat = 40.7128, nyLon = -74.0060;
const lonLat = 51.5074, lonLon = -0.1278;
// 1. Great-Circle Distance
final double distanceKm = GeoUtils.distanceBetweenKm(nyLat, nyLon, lonLat, lonLon);
final double distanceMiles = GeoUtils.distanceBetweenMiles(nyLat, nyLon, lonLat, lonLon);
print('Distance: $distanceKm km ($distanceMiles miles)'); // ~5570 km
// 2. Initial Compass Bearing
final double bearing = GeoUtils.bearingBetween(nyLat, nyLon, lonLat, lonLon);
print('Bearing: $bearingΒ°'); // e.g. 51.2Β° (NE)
// 3. Geofencing Check
final bool isNearby = GeoUtils.isWithinRadius(
centerLatitude: nyLat,
centerLongitude: nyLon,
targetLatitude: 40.7306,
targetLongitude: -73.9352,
radiusInMeters: 10000, // 10 km radius
);
// 4. Coordinates DMS Formatting
final String dms = GeoUtils.formatCoordinates(40.7128, -74.0060, dms: true);
print(dms); // 40Β° 42' 46.1" N, 74Β° 0' 21.6" W
// 5. Human-Readable Distance Formatter
print(GeoUtils.formatDistance(350)); // "350 m"
print(GeoUtils.formatDistance(2500)); // "2.5 km"
print(GeoUtils.formatDistance(5000, imperial: true)); // "3.11 mi"
π‘οΈ Robust Error Handling #
geocoder_pro provides structured, typed exceptions so your app can handle API and network issues gracefully:
try {
final result = await GeocoderPro.google(apiKey: 'INVALID_KEY')
.getDataFromAddress('Paris, France');
} on ApiKeyException catch (e) {
print('API Key Issue: ${e.message}');
} on QuotaExceededException catch (e) {
print('Rate limit or billing quota exceeded: ${e.message}');
} on NetworkException catch (e) {
print('Network/Connection error: ${e.message}');
} on GeocoderException catch (e) {
print('General Geocoding error: ${e.message}');
}
π§ͺ Unit Testing with Custom HTTP Clients #
All providers support injecting a custom http.Client:
import 'package:http/testing.dart';
final mockClient = MockClient((request) async {
return http.Response(myMockJsonResponse, 200);
});
final geocoder = GeocoderPro.google(
apiKey: 'TEST_KEY',
client: mockClient,
);
final result = await geocoder.getDataFromAddress('Test Address');
π± Interactive Example App #
Check out the example/ folder for a complete Material 3 Flutter application featuring:
- Live Forward Geocoding with quick presets
- Live Reverse Geocoding with coordinate inputs
- Distance, Bearing & Geofence Calculator
- Interactive Provider Switch (Free OpenStreetMap & Google Maps)
- Raw JSON Inspector modal
π License #
This project is licensed under the MIT License - see the LICENSE file for details.
π€ Contributing #
Contributions, issues, and feature requests are welcome! Feel free to check the issues page.