simple_bg_location 1.0.0 copy "simple_bg_location: ^1.0.0" to clipboard
simple_bg_location: ^1.0.0 copied to clipboard

PlatformAndroidiOS
outdated

A simple background location plugin for Flutter. This plugin provides a cross-platform(iOS, Android) Api for generic location functions.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:simple_bg_location/simple_bg_device_info.dart';
import 'package:simple_bg_location/simple_bg_location.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Simple_BG_Location Tiny Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Position> positions = [];
  bool isReady = false;
  double odometer = 0;
  bool isTracking = false;
  final List<LocationEventItem> events = [];

  final scrollController = ScrollController();
  void _scrollToBottom() {
    scrollController.animateTo(scrollController.position.maxScrollExtent,
        duration: const Duration(milliseconds: 300), curve: Curves.easeOut);
  }

  @override
  void initState() {
    super.initState();
    SimpleBgLocation.onPosition(_onPosition, _positionErrorHandle);
    SimpleBgLocation.onNotificationAction(_onNotificationAction);
    SimpleBgLocation.ready().then((sbglState) {
      isReady = true;
      positions.addAll(sbglState.positions ?? []);
      events.addAll(positions.map((e) => LocationEventItem(
            LocationEventType.position,
            'position record restored from service',
            detail: 'lat: ${e.latitude}, lng: ${e.longitude}',
          )));
      odometer = 0;
      if (positions.length >= 2) {
        for (int i = 1; i < positions.length; i++) {
          final d = SimpleBgLocation.distance(
            positions[i - 1].latitude,
            positions[i - 1].longitude,
            positions[i].latitude,
            positions[i].longitude,
          );
          odometer += d;
        }
      }
      isTracking = sbglState.isTracking;
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToBottom());
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: const Text('Simple Background Location Demo'),
      ),
      body: ListView.separated(
        controller: scrollController,
        itemCount: events.length,
        itemBuilder: (context, index) {
          final item = events[index];
          if (item.type == LocationEventType.position) {
            return ListTile(
              dense: true,
              title: Text(
                item.title,
                style: const TextStyle(fontSize: 12.0),
              ),
              subtitle:
                  Text(item.detail, style: const TextStyle(fontSize: 10.0)),
              leading: const Icon(Icons.location_on),
            );
          } else {
            return ListTile(
              dense: true,
              title: Text(item.title, style: const TextStyle(fontSize: 12.0)),
              subtitle:
                  Text(item.detail, style: const TextStyle(fontSize: 10.0)),
              leading: const Icon(Icons.info),
            );
          }
        },
        separatorBuilder: (context, index) {
          return const Divider();
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: isReady
            ? () {
                if (!isTracking) {
                  _startPositionUpdate();
                } else {
                  SimpleBgLocation.stopPositionUpdate();
                  isTracking = false;
                  setState(() {});
                }
              }
            : null,
        tooltip: isTracking ? 'Stop' : 'Start',
        child: Icon(isTracking ? Icons.stop : Icons.play_arrow),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  void _startPositionUpdate() async {
    if (!(await SimpleBgLocation.isLocationServiceEnabled())) {
      events.add(const LocationEventItem(
        LocationEventType.log,
        'Location service disabled',
      ));
      setState(() {});
      SimpleBgLocation.openLocationSettings();
      return;
    }
    var permission = await SimpleBgLocation.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await SimpleBgLocation.requestPermission();
      if (permission == LocationPermission.denied) {
        events.add(const LocationEventItem(
          LocationEventType.log,
          'Permission denied',
        ));
        setState(() {});

        return;
      }
    }

    if (permission == LocationPermission.deniedForever) {
      events.add(const LocationEventItem(
        LocationEventType.log,
        'Permission denied forever',
      ));
      setState(() {});
      // Do not call openAppSetting directly in the formal product.
      // Instead, you should ask the user if they are willing,
      // and do not ask again after the user has refused multiple times.
      SimpleBgLocation.openAppSettings();

      return;
    }

    if ((await SimpleBgDeviceInfo.isPowerSaveMode())) {
      events.add(const LocationEventItem(
        LocationEventType.log,
        'Power save mode enabled!',
        detail: '''Track recording may not work properly in Power Save Mode. 
            If track does not record properly, disable Power Save Mode.''',
      ));
      return;
    }

    final requestSettings = RequestSettings.good();
    requestSettings.notificationConfig = ForegroundNotificationConfig(
      notificationId: 100,
      title: "Simple BG Location",
      text: "distance: {distance}",
      priority: ForegroundNotificationConfig.NOTIFICATION_PRIORITY_DEFAULT,
      actions: ['Action1', 'Action2', 'cancel'],
    );

    final success =
        await SimpleBgLocation.requestPositionUpdate(requestSettings);
    if (success) {
      isTracking = true;
    } else {
      events.add(const LocationEventItem(
        LocationEventType.log,
        'Error',
        detail: 'Request position update failed',
      ));
    }
    setState(() {});
  }

  void _onPosition(Position position) {
    final strEvent = 'lat: ${position.latitude}, lng: ${position.longitude}';
    events.add(LocationEventItem(LocationEventType.position, strEvent));
    setState(() {});
  }

  void _positionErrorHandle(PositionError err) {
    events.add(LocationEventItem(
        LocationEventType.log, 'PositionError CODE: ${err.code}',
        detail: err.message));
    isTracking = false;
    setState(() {});
  }

  void _onNotificationAction(String action) {
    events.add(LocationEventItem(
      LocationEventType.log,
      'Notification action: $action',
    ));
    setState(() {});
  }
}

class LocationEventItem {
  final String title;
  final String detail;
  final LocationEventType type;

  const LocationEventItem(this.type, this.title, {this.detail = ''});
}

enum LocationEventType { log, position }
7
likes
150
points
19
downloads

Publisher

unverified uploader

Weekly Downloads

A simple background location plugin for Flutter. This plugin provides a cross-platform(iOS, Android) Api for generic location functions.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

collection, flutter, flutter_plugin_android_lifecycle, plugin_platform_interface

More

Packages that depend on simple_bg_location

Packages that implement simple_bg_location