Skip to content

Instantly share code, notes, and snippets.

@venbrinoDev
Created April 9, 2024 13:53
Show Gist options
  • Save venbrinoDev/92734e87f75105f43cb9ac7ccb8aed30 to your computer and use it in GitHub Desktop.
Save venbrinoDev/92734e87f75105f43cb9ac7ccb8aed30 to your computer and use it in GitHub Desktop.
Location Utilities

Location Service

you can just create an intsance/(you can register this with get_it/ioc contiainer) for easy usage

import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:your_project_folder/permission_manager.dart';

class LocationService {
  PolylinePoints polylinePoints = PolylinePoints();

  ///retrun proximity Measurment
  ///
  /// return resullt in [Measurement.km] by default
  Future<double> proximity(
      {required LatLng latLng,
      Measurement measurement = Measurement.km}) async {
    final currentLatLng = await currentLocation();

    if (currentLatLng != null) {
      final distance = Geolocator.distanceBetween(currentLatLng.latitude,
          currentLatLng.longitude, latLng.latitude, latLng.longitude);
      return distance.toMeasurement(measurement);
    }
    return 0;
  }

  
  ///Get the route between two co-ordinate
  ///
  /// [dotenv.get('GOOGLE_API_KEY')] you can replace this with your google Api key
  Future<List<LatLng>> getRouteBetweenCoordinates({
    required LatLng currentLocation,
    required LatLng destination,
  }) async {
    final result = await polylinePoints.getRouteBetweenCoordinates(
      dotenv.get('GOOGLE_API_KEY'),
      PointLatLng(currentLocation.latitude, currentLocation.longitude),
      PointLatLng(destination.latitude, destination.longitude),
    );

    return result.points
        .map((value) => LatLng(value.latitude, value.longitude))
        .toList();
  }

  ///This check if your
  ///current Distance is < [proxixmityCheck]
  ///or current Distance ==[proxixmityCheck]
  Future<bool> isProximtySatisified(
      {required LatLng latLng,
      double proxixmityCheck = 400,
      Measurement measurement = Measurement.km}) async {
    final currentLatLng = await currentLocation();

    if (currentLatLng != null) {
      final distance = Geolocator.distanceBetween(currentLatLng.latitude,
          currentLatLng.longitude, latLng.latitude, latLng.longitude);

      return proxixmityCheck > distance || proxixmityCheck == distance;
    }
    return false;
  }

  ///Get current location
  Future<LatLng?> currentLocation() async {
    final permissionGranted =
        await PermissionManager.isLocationPermissionEnable();

    if (!permissionGranted) {
      await PermissionManager.requestLocationPermission();
    }
    return _myLocation();
  }

  ///This listen to user location and send back the
  ///[LatLng] - [distanceFilter] is 20m by default
  Stream<LatLng> listenToLocationUpdate({
    int distanceFilter = 20,
  }) {
    return Geolocator.getPositionStream(
            locationSettings: LocationSettings(distanceFilter: distanceFilter))
        .map((event) => LatLng(event.latitude, event.longitude));
  }

  Future<LatLng?> _myLocation() async {
    Position? position;
    try {
      final currentPostion = await Geolocator.getCurrentPosition(
          timeLimit: const Duration(seconds: 2),
          desiredAccuracy: LocationAccuracy.best);

      position = currentPostion;
    } catch (_) {
      position = await Geolocator.getLastKnownPosition();
    }

    return position != null
        ? LatLng(position.latitude, position.longitude)
        : null;
  }
}

enum Measurement {
  m,
  km;
}

extension DoubleExt on double {
  double toMeasurement(Measurement measurement, {int roundOff = 2}) =>
      switch (measurement) {
        Measurement.m => double.parse(toStringAsFixed(roundOff)),
        Measurement.km => double.parse((this / 1000).toStringAsFixed(roundOff))
      };
}

Location Manager

Manage your location permission(see Permission manager for down to make easy integration )

import 'package:geolocator/geolocator.dart';

class LocationPermissonManager {
  LocationPermissonManager._();

  static final _instance = LocationPermissonManager._();

  static final internal = _instance;

  factory LocationPermissonManager() {
    return _instance;
  }
  
  Future<LocationPermission> requestLocationPermssion() async {
    LocationPermission permission = await Geolocator.checkPermission();

    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
    }
    return permission;
  }

  Future<bool> hasAccepted() async {
    return await Geolocator.isLocationServiceEnabled();
  }

  Stream<ServiceStatus> status() {
    return Geolocator.getServiceStatusStream();
  }
}

Permission Mananger

This contain only the location manager for now (you can use the permission package to support more)

///Manage Permisssion in the app
///Support only [LocationPermissonManager]
class PermissionManager {
  static Future<bool> isLocationPermissionEnable() {
    return LocationPermissonManager.internal.hasAccepted();
  }

  static Future<LocationPermission> requestLocationPermission() {
    return LocationPermissonManager.internal.requestLocationPermssion();
  }

  static Stream<ServiceStatus>? locationStatus() =>
      LocationPermissonManager.internal.status();
}

///Eg 
Permission.requestLocationPermission();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment