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