Flutter后台定位插件background_locator_2的使用
Flutter后台定位插件background_locator_2的使用
background_locator_2
是一个用于在应用被杀死后仍然能够获取位置更新的Flutter插件。本文将介绍如何安装、配置和使用该插件,并提供完整的示例代码。
安装与设置
安装步骤
-
在
pubspec.yaml
文件中添加background_locator_2
依赖:dependencies: flutter: sdk: flutter background_locator_2: ^最新版本号
-
运行
flutter pub get
来安装依赖。
设置步骤
请参考 官方Wiki 获取详细的安装和设置说明。
使用方法
以下是一个完整的示例代码,展示了如何使用 background_locator_2
插件来实现后台定位功能。
import 'dart:async';
import 'dart:isolate';
import 'dart:ui';
import 'package:background_locator_2/background_locator.dart';
import 'package:background_locator_2/location_dto.dart';
import 'package:background_locator_2/settings/android_settings.dart';
import 'package:background_locator_2/settings/ios_settings.dart';
import 'package:background_locator_2/settings/locator_settings.dart';
import 'package:flutter/material.dart';
import 'package:location_permissions/location_permissions.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ReceivePort port = ReceivePort();
String logStr = '';
bool isRunning;
LocationDto lastLocation;
@override
void initState() {
super.initState();
if (IsolateNameServer.lookupPortByName('com.example.background_location') != null) {
IsolateNameServer.removePortNameMapping('com.example.background_location');
}
IsolateNameServer.registerPortWithName(port.sendPort, 'com.example.background_location');
port.listen(
(dynamic data) async {
await updateUI(data);
},
);
initPlatformState();
}
@override
void dispose() {
super.dispose();
}
Future<void> updateUI(dynamic data) async {
final log = await FileManager.readLogFile();
LocationDto locationDto = (data != null) ? LocationDto.fromJson(data) : null;
await _updateNotificationText(locationDto);
setState(() {
if (data != null) {
lastLocation = locationDto;
}
logStr = log;
});
}
Future<void> _updateNotificationText(LocationDto data) async {
if (data == null) {
return;
}
await BackgroundLocator.updateNotificationText(
title: "New location received",
msg: "${DateTime.now()}",
bigMsg: "${data.latitude}, ${data.longitude}");
}
Future<void> initPlatformState() async {
print('Initializing...');
await BackgroundLocator.initialize();
logStr = await FileManager.readLogFile();
print('Initialization done');
final _isRunning = await BackgroundLocator.isServiceRunning();
setState(() {
isRunning = _isRunning;
});
print('Running ${isRunning.toString()}');
}
@override
Widget build(BuildContext context) {
final start = SizedBox(
width: double.maxFinite,
child: ElevatedButton(
child: Text('Start'),
onPressed: () {
_onStart();
},
),
);
final stop = SizedBox(
width: double.maxFinite,
child: ElevatedButton(
child: Text('Stop'),
onPressed: () {
onStop();
},
),
);
final clear = SizedBox(
width: double.maxFinite,
child: ElevatedButton(
child: Text('Clear Log'),
onPressed: () {
FileManager.clearLogFile();
setState(() {
logStr = '';
});
},
),
);
String msgStatus = "-";
if (isRunning != null) {
if (isRunning) {
msgStatus = 'Is running';
} else {
msgStatus = 'Is not running';
}
}
final status = Text("Status: $msgStatus");
final log = Text(
logStr,
);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter background Locator'),
),
body: Container(
width: double.maxFinite,
padding: const EdgeInsets.all(22),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[start, stop, clear, status, log],
),
),
),
),
);
}
void onStop() async {
await BackgroundLocator.unRegisterLocationUpdate();
final _isRunning = await BackgroundLocator.isServiceRunning();
setState(() {
isRunning = _isRunning;
});
}
void _onStart() async {
if (await _checkLocationPermission()) {
await _startLocator();
final _isRunning = await BackgroundLocator.isServiceRunning();
setState(() {
isRunning = _isRunning;
lastLocation = null;
});
} else {
// show error
}
}
Future<bool> _checkLocationPermission() async {
final access = await LocationPermissions().checkPermissionStatus();
switch (access) {
case PermissionStatus.unknown:
case PermissionStatus.denied:
case PermissionStatus.restricted:
final permission = await LocationPermissions().requestPermissions(
permissionLevel: LocationPermissionLevel.locationAlways,
);
if (permission == PermissionStatus.granted) {
return true;
} else {
return false;
}
break;
case PermissionStatus.granted:
return true;
break;
default:
return false;
break;
}
}
Future<void> _startLocator() async {
Map<String, dynamic> data = {'countInit': 1};
return await BackgroundLocator.registerLocationUpdate(
LocationCallbackHandler.callback,
initCallback: LocationCallbackHandler.initCallback,
initDataCallback: data,
disposeCallback: LocationCallbackHandler.disposeCallback,
iosSettings: IOSSettings(
accuracy: LocationAccuracy.NAVIGATION,
distanceFilter: 0,
stopWithTerminate: true),
autoStop: false,
androidSettings: AndroidSettings(
accuracy: LocationAccuracy.NAVIGATION,
interval: 5,
distanceFilter: 0,
client: LocationClient.google,
androidNotificationSettings: AndroidNotificationSettings(
notificationChannelName: 'Location tracking',
notificationTitle: 'Start Location Tracking',
notificationMsg: 'Track location in background',
notificationBigMsg:
'Background location is on to keep the app up-to-date with your location. This is required for main features to work properly when the app is not running.',
notificationIconColor: Colors.grey,
notificationTapCallback:
LocationCallbackHandler.notificationCallback)));
}
}
关键点解释
- 权限管理:确保请求并处理位置权限。
- 后台服务注册:通过
BackgroundLocator.registerLocationUpdate
方法启动后台定位服务。 - 通知更新:使用
BackgroundLocator.updateNotificationText
更新通知内容。
结论
通过上述步骤和示例代码,您可以轻松地在Flutter应用中集成后台定位功能。更多详细信息和高级用法,请参考 官方Wiki。
更多关于Flutter后台定位插件background_locator_2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter后台定位插件background_locator_2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter应用中使用background_locator_2
插件来实现后台定位的示例代码。这个插件允许应用在后台持续获取位置信息。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加background_locator_2
及其依赖的依赖项:
dependencies:
flutter:
sdk: flutter
background_locator_2: ^x.y.z # 请替换为最新版本号
geolocator: ^x.y.z # background_locator_2依赖于geolocator
2. 配置Android权限
在android/app/src/main/AndroidManifest.xml
中添加必要的权限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourapp">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 其他配置 -->
</manifest>
3. 配置iOS权限
在ios/Runner/Info.plist
中添加必要的权限:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>需要您的位置信息以便在后台跟踪您的位置</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>需要您的位置信息以便在后台跟踪您的位置</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要您的位置信息</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
4. 实现后台定位功能
在你的Dart代码中,你需要设置后台定位服务,并处理位置更新。
import 'package:flutter/material.dart';
import 'package:background_locator_2/background_locator_2.dart';
import 'package:geolocator/geolocator.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
configureBackgroundLocator();
runApp(MyApp());
}
void configureBackgroundLocator() async {
// 注册位置回调
BackgroundLocator.registerLocationUpdate(
locationCallback,
autoStart: true,
androidSettings: AndroidSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 10.0,
interval: 60000, // 每分钟更新一次
),
iosSettings: IOSSettings(
accuracy: LocationAccuracy.best,
distanceFilter: 10.0,
activityType: ActivityType.automotiveNavigation,
pauseLocationUpdatesAutomatically: false,
),
);
// 请求后台位置权限
BackgroundLocator.requestPermission().then((status) {
if (status == LocationPermission.deniedForever) {
// 用户永久拒绝了位置权限
} else if (status == LocationPermission.denied) {
// 用户拒绝了位置权限
} else if (status == LocationPermission.whileInUse || status == LocationPermission.always) {
// 用户同意了位置权限
BackgroundLocator.start();
}
});
}
void locationCallback(LocationData location) async {
// 在这里处理位置更新,比如保存到数据库或发送到服务器
print('${location.latitude}, ${location.longitude}');
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Background Locator Example'),
),
body: Center(
child: Text('Check the console for location updates'),
),
),
);
}
}
5. 启动前台服务(可选)
为了保持应用在后台运行时持续获取位置,你可能需要启动一个前台服务。这通常用于Android设备,iOS则不需要。
void startForegroundService() {
BackgroundLocator.startForegroundService(
notificationTitle: '位置跟踪',
notificationMsg: '应用正在后台跟踪您的位置',
notificationImportance: NotificationImportance.High,
);
}
你可以在BackgroundLocator.requestPermission().then(...)
的回调中调用startForegroundService()
函数来启动前台服务。
注意事项
- 在实际开发中,确保你的应用遵循相关的隐私政策和用户协议,以合法合规的方式使用位置信息。
- 测试后台定位功能时,请确保设备未连接到调试器,因为某些设备在连接调试器时不会触发后台限制。
这个示例代码展示了如何在Flutter应用中使用background_locator_2
插件来实现后台定位功能。根据你的具体需求,你可能需要调整配置和处理逻辑。