smart_location_plus
A unified Flutter location package that combines geolocator and geocoding into one clean, easy-to-use API with a built-in, lightweight pure-Dart geofencing engine.
Zero boilerplate by default. Full customization when you need it.
Why smart_location_plus?
Without smart_location_plus |
With smart_location_plus |
|---|---|
| 3 packages to learn | 1 API |
| 50+ lines of boilerplate | 1–3 lines |
| Manual permission checks | Auto-handled |
| Geocoding is a separate async step | Auto-resolved |
| Complex geofence setup | watchZone() with simple callbacks |
Installation
dependencies:
smart_location_plus: ^0.1.0
Android — AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- For background / geofencing -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
iOS — Info.plist
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access to show relevant features.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app uses background location for geofencing.</string>
Quick Start
import 'package:smart_location_plus/smart_location_plus.dart';
// Get location + address in one call
final loc = await SmartLocation.locateOnce();
print(loc.address); // "MG Road, Mumbai, Maharashtra, India"
print(loc.city); // "Mumbai"
print(loc.latitude); // 19.2183
API Reference
locateOnce()
// Zero config
final loc = await SmartLocation.locateOnce();
// Fully customized
final loc = await SmartLocation.locateOnce(
locationConfig: LocationConfig(
accuracy: LocationAccuracy.best,
timeLimit: Duration(seconds: 8),
activityType: ActivityType.automotiveNavigation,
),
geocodingConfig: GeocodingConfig(
localeIdentifier: 'hi', // Hindi address
maxResults: 3,
),
);
locateAndWatch()
// Basic stream
SmartLocation.locateAndWatch().listen((loc) {
print('${loc.latitude}, ${loc.longitude}');
});
// High accuracy, skip address for performance
SmartLocation.locateAndWatch(
locationConfig: LocationConfig(
accuracy: LocationAccuracy.high,
distanceFilter: 10,
),
geocodingConfig: GeocodingConfig(resolveAddress: false),
).listen((loc) => updateMap(loc));
reverseGeocode() and forwardGeocode()
// Coordinates → address
final result = await SmartLocation.reverseGeocode(
latitude: 19.2183,
longitude: 73.0587,
config: GeocodingConfig(localeIdentifier: 'en_IN'),
);
print(result.address);
// Address → coordinates
final result = await SmartLocation.forwardGeocode(
address: 'Gateway of India, Mumbai',
);
print('${result.latitude}, ${result.longitude}');
watchZone() — Geofencing
await SmartLocation.watchZone(
zones: [
LocationZone(
id: 'home',
latitude: 19.2183,
longitude: 73.0587,
config: GeofenceConfig(
radius: 100,
loiteringDelay: 30000,
listenFor: {GeofenceEvent.enter, GeofenceEvent.exit, GeofenceEvent.dwell},
),
onEnter: (zone) => print('Home!'),
onExit: (zone) => print('Left home'),
onDwell: (zone) => print('Still home'),
),
],
globalConfig: GeofenceConfig(
useActivityRecognition: true,
onError: (e) => print(e),
),
);
Utilities
// Distance between two points
final metres = SmartLocation.distanceBetween(
startLat: 19.2183, startLng: 73.0587,
endLat: 19.3000, endLng: 73.0700,
);
// Bearing
final degrees = SmartLocation.bearingBetween(...);
// Is point inside zone?
final inside = SmartLocation.isInsideZone(
latitude: 19.2185, longitude: 73.0589,
zone: LocationZone(id: 'home', latitude: 19.2183, longitude: 73.0587),
);
Error Handling
try {
final loc = await SmartLocation.locateOnce();
} on LocationServiceDisabledException {
// GPS is off
} on LocationPermissionDeniedException {
// User denied permission
} on LocationPermissionPermanentlyDeniedException {
await SmartLocation.openAppSettings();
} on LocationTimeoutException {
// Took too long
} on AddressNotFoundException {
// Geocoding failed
}
Powered By
License
MIT