Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sisyfus/86a2817bc0d7c7f06e7cb866596c79d8 to your computer and use it in GitHub Desktop.
Save sisyfus/86a2817bc0d7c7f06e7cb866596c79d8 to your computer and use it in GitHub Desktop.
Flutter Background Geolocation hello_world.dart https://shop.transistorsoft.com/blogs/news
/*
* Forked from https://gist.github.com/christocracy/a0464846de8a9c27c7e9de5616082878
* Modified to use the geolocation package as a Riverpod provider
* flutter_background_geolocation Hello World
* https://github.com/transistorsoft/flutter_background_geolocation
*/
import 'package:flutter/material.dart';
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart'
as bg;
import 'package:flutter_riverpod/flutter_riverpod.dart';
// For pretty-printing location JSON. Not a requirement of flutter_background_geolocation
//
import 'dart:convert';
JsonEncoder encoder = const JsonEncoder.withIndent(" ");
//
void main() => runApp(const ProviderScope(child: MyApp()));
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BackgroundGeolocation Demo',
theme: ThemeData(
primarySwatch: Colors.amber,
),
home: const MyHomePage(title: 'BackgroundGeolocation Demo'),
);
}
}
class MyHomePage extends ConsumerWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
Widget build(BuildContext context, WidgetRef ref) {
final locationData = ref.watch(bgLocationNotifierProvider);
final bg.Location? bgLocation = locationData.bgLocation;
final bg.ProviderChangeEvent? bgProviderChangeEvent =
locationData.bgProviderChangeEvent;
String mainContent = '';
String odometerKM = '';
if (bgLocation != null) {
mainContent = encoder.convert(bgLocation.toMap());
odometerKM = (bgLocation.odometer / 1000.0).toStringAsFixed(1);
}
if (bgProviderChangeEvent != null) {
mainContent = encoder.convert(bgProviderChangeEvent.toMap());
}
return Scaffold(
appBar: AppBar(
title: const Text('Background Geolocation'),
actions: <Widget>[
Switch(
value: locationData.enabled,
onChanged: (bool enabled) {
ref
.read(bgLocationNotifierProvider.notifier)
.onClickEnable(enabled);
}),
],
),
body: SingleChildScrollView(
child: Text(mainContent),
),
bottomNavigationBar: BottomAppBar(
child: Container(
padding: const EdgeInsets.only(left: 5.0, right: 5.0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: const Icon(Icons.gps_fixed),
onPressed: () {
ref
.read(bgLocationNotifierProvider.notifier)
.onClickGetCurrentPosition();
},
),
Text('${locationData.motionActivity} · $odometerKM km'),
MaterialButton(
minWidth: 50.0,
color: (locationData.isMoving) ? Colors.red : Colors.green,
onPressed: () => ref
.read(bgLocationNotifierProvider.notifier)
.onClickChangePace(),
child: Icon(
(locationData.isMoving) ? Icons.pause : Icons.play_arrow,
color: Colors.white),
),
],
),
)),
);
}
}
class LocationData {
LocationData({
this.bgLocation,
this.bgProviderChangeEvent,
required this.isMoving,
required this.enabled,
required this.motionActivity,
});
final bg.Location? bgLocation;
final bg.ProviderChangeEvent? bgProviderChangeEvent;
final bool isMoving;
final bool enabled;
final String motionActivity;
LocationData copyWith({
bg.Location? bgLocation,
bg.ProviderChangeEvent? bgProviderChangeEvent,
bool? isMoving,
bool? enabled,
String? motionActivity,
}) {
return LocationData(
bgLocation: bgLocation ?? this.bgLocation,
bgProviderChangeEvent:
bgProviderChangeEvent ?? this.bgProviderChangeEvent,
isMoving: isMoving ?? this.isMoving,
enabled: enabled ?? this.enabled,
motionActivity: motionActivity ?? this.motionActivity,
);
}
}
class BGLocationNotifier extends Notifier<LocationData> {
@override
build() {
_initializeBGGeolocation();
return LocationData(
bgLocation: null,
isMoving: false,
enabled: false,
motionActivity: 'UNKNOWN',
);
}
void _initializeBGGeolocation() async {
final bg.State bgState = await bg.BackgroundGeolocation.ready(
bg.Config(
desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH,
distanceFilter: 10.0,
persistMode: bg.Config.PERSIST_MODE_NONE, //non default
stopOnTerminate: true, //non default
startOnBoot: false, //non default
logLevel: bg.Config.LOG_LEVEL_VERBOSE,
reset: true),
);
state = state.copyWith(
isMoving: bgState.isMoving!,
enabled: bgState.enabled,
);
bg.BackgroundGeolocation.onLocation(_onLocation);
bg.BackgroundGeolocation.onProviderChange(_onProviderChange);
bg.BackgroundGeolocation.onMotionChange(_onMotionChange);
bg.BackgroundGeolocation.onActivityChange(_onActivityChange);
}
void _onLocation(bg.Location location) {
print('[location] - $location');
state = state.copyWith(
bgLocation: location,
bgProviderChangeEvent: null,
);
}
void _onMotionChange(bg.Location location) {
print('[motionchange] - $location');
}
void _onActivityChange(bg.ActivityChangeEvent event) {
print('[activitychange] - $event');
state = state.copyWith(
motionActivity: event.activity,
);
}
void _onProviderChange(bg.ProviderChangeEvent event) {
print('$event');
state = state.copyWith(
bgLocation: null,
bgProviderChangeEvent: event,
);
}
void _onConnectivityChange(bg.ConnectivityChangeEvent event) {
print('$event');
}
void onClickEnable(bool enabled) async {
if (enabled) {
final bgState = await bg.BackgroundGeolocation.start();
print('[start] success $bgState');
state = state.copyWith(
enabled: bgState.enabled,
isMoving: bgState.isMoving,
);
} else {
final bgState = await bg.BackgroundGeolocation.stop();
print('[stop] success: $bgState');
// Reset odometer.
bg.BackgroundGeolocation.setOdometer(0.0);
state = state.copyWith(
enabled: bgState.enabled,
isMoving: bgState.isMoving,
);
}
}
void onClickChangePace() async {
state = state.copyWith(isMoving: !state.isMoving);
print("[onClickChangePace] -> ${state.isMoving}");
try {
final isMoving =
await bg.BackgroundGeolocation.changePace(state.isMoving);
print('[changePace] success $isMoving');
} on Exception catch (e) {
print('[changePace] ERROR: $e');
}
}
void onClickGetCurrentPosition() async {
try {
final location = await bg.BackgroundGeolocation.getCurrentPosition(
persist: false, // <-- do not persist this location
desiredAccuracy: 0, // <-- desire best possible accuracy
timeout: 30000, // <-- wait 30s before giving up.
samples: 3 // <-- sample 3 location before selecting best.
);
print('[getCurrentPosition] - $location');
} on Exception catch (e) {
print('[getCurrentPosition] ERROR: $e');
}
}
}
final bgLocationNotifierProvider =
NotifierProvider<BGLocationNotifier, LocationData>(BGLocationNotifier.new);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment