Flutter后台定位插件carp_background_location的使用
Flutter后台定位插件carp_background_location的使用
CARP Background Location Plugin 是一个用于Android和iOS平台的后台定位插件,它可以在应用程序处于后台时继续工作。这个插件是background_locator_2
的一个简单包装器。关于安装和设置的指导,请参考background_locator_2
的wiki页面。
Android设置
添加权限
在AndroidManifest.xml
中添加以下权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
应用标签配置
在application
标签内添加如下内容:
<receiver android:name="yukams.app.background_locator_2.BootBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service android:name="yukams.app.background_locator_2.IsolateHolderService"
android:permission="android.permission.FOREGROUND_SERVICE"
android:exported="true"
android:foregroundServiceType = "location"/>
注意: 在Android 11及以上版本中,位置权限不能通过manifest文件自动设置。您需要引导用户手动将权限设置为“允许所有时间”。
iOS设置
修改Info.plist
在Info.plist
中添加以下键值对:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs access to location when open and in the background.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to location when in the background.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
修改AppDelegate.swift
覆盖您的AppDelegate.swift
文件:
import UIKit
import Flutter
import background_locator_2
func registerPlugins(registry: FlutterPluginRegistry) -> () {
if (!registry.hasPlugin("BackgroundLocatorPlugin")) {
GeneratedPluginRegistrant.register(with: registry)
}
}
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
BackgroundLocatorPlugin.setPluginRegistrantCallback(registerPlugins)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
使用方法
以下是使用carp_background_location
的基本示例代码:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:carp_background_location/carp_background_location.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
enum LocationStatus { UNKNOWN, INITIALIZED, RUNNING, STOPPED }
class _MyAppState extends State<MyApp> {
String logStr = '';
LocationDto? _lastLocation;
StreamSubscription<LocationDto>? locationSubscription;
LocationStatus _status = LocationStatus.UNKNOWN;
@override
void initState() {
super.initState();
// 配置位置管理器
LocationManager().interval = 1;
LocationManager().distanceFilter = 0;
LocationManager().notificationTitle = 'CARP Location Example';
LocationManager().notificationMsg = 'CARP is tracking your location';
_status = LocationStatus.INITIALIZED;
}
void getCurrentLocation() async =>
onData(await LocationManager().getCurrentLocation());
void onData(LocationDto location) {
print('>> $location');
setState(() {
_lastLocation = location;
});
}
/// 是否已授予“始终允许位置”权限?
Future<bool> isLocationAlwaysGranted() async =>
await Permission.locationAlways.isGranted;
/// 尝试请求用户授予“始终允许位置”权限。
/// 如果成功返回`true`,否则返回`false`。
Future<bool> askForLocationAlwaysPermission() async {
bool granted = await Permission.locationAlways.isGranted;
if (!granted) {
granted =
await Permission.locationAlways.request() == PermissionStatus.granted;
}
return granted;
}
/// 开始监听位置事件。
void start() async {
// 如果没有授予位置权限,则请求权限
if (!await isLocationAlwaysGranted())
await askForLocationAlwaysPermission();
locationSubscription?.cancel();
locationSubscription = LocationManager().locationStream.listen(onData);
await LocationManager().start();
setState(() {
_status = LocationStatus.RUNNING;
});
}
void stop() {
locationSubscription?.cancel();
LocationManager().stop();
setState(() {
_status = LocationStatus.STOPPED;
});
}
Widget stopButton() => SizedBox(
width: double.maxFinite,
child: ElevatedButton(
child: const Text('STOP'),
onPressed: stop,
),
);
Widget startButton() => SizedBox(
width: double.maxFinite,
child: ElevatedButton(
child: const Text('START'),
onPressed: start,
),
);
Widget statusText() => Text("Status: ${_status.toString().split('.').last}");
Widget currentLocationButton() => SizedBox(
width: double.maxFinite,
child: ElevatedButton(
child: const Text('CURRENT LOCATION'),
onPressed: getCurrentLocation,
),
);
Widget locationWidget() {
if (_lastLocation == null)
return Text("No location yet");
else
return Column(
children: <Widget>[
Text(
'${_lastLocation!.latitude}, ${_lastLocation!.longitude}',
),
Text(
'@',
),
Text(
'${DateTime.fromMillisecondsSinceEpoch(_lastLocation!.time ~/ 1)}')
],
);
}
@override
void dispose() => super.dispose();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('CARP Background Location'),
),
body: Container(
width: double.maxFinite,
padding: const EdgeInsets.all(22),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
startButton(),
stopButton(),
currentLocationButton(),
Divider(),
statusText(),
Divider(),
locationWidget(),
],
),
),
),
),
);
}
}
功能与问题
如果您有任何功能请求或遇到bug,请在issue tracker上提交。
许可证
该软件由Copenhagen Center for Health Technology (CACHET)持有版权,并遵循MIT许可证发布。更多信息请参见许可证。
更多关于Flutter后台定位插件carp_background_location的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter后台定位插件carp_background_location的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用carp_background_location
插件来实现后台定位的示例代码。这个插件允许应用在后台持续获取用户的位置信息。
首先,你需要在你的pubspec.yaml
文件中添加carp_background_location
依赖:
dependencies:
flutter:
sdk: flutter
carp_background_location: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
接下来,你需要在Android和iOS项目中配置一些必要的权限和设置。
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>
在android/app/build.gradle
文件中确保你的minSdkVersion
至少为23(Android 6.0 Marshmallow),因为后台定位需要这个API级别或更高:
android {
compileSdkVersion 30
defaultConfig {
applicationId "com.example.yourapp"
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0"
}
// 其他配置
}
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>
Flutter代码实现
在你的Flutter项目中,你需要初始化carp_background_location
插件并设置后台定位监听器。以下是一个简单的示例:
import 'package:flutter/material.dart';
import 'package:carp_background_location/carp_background_location.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late DataCollectionService _dataCollectionService;
late DataCollectionClientConfig _config;
@override
void initState() {
super.initState();
// 初始化配置
_config = DataCollectionClientConfig(
deviceRole: DeviceRole.PHONE,
studyId: 'your_study_id',
participantId: 'your_participant_id',
);
// 初始化数据收集服务
_dataCollectionService = DataCollectionService(
config: _config,
sampleRate: Duration(seconds: 5), // 每5秒收集一次位置数据
onSample: (sample) {
if (sample is LocationDataPoint) {
// 处理位置数据
print('Latitude: ${sample.latitude}, Longitude: ${sample.longitude}');
}
},
);
// 请求权限并开始收集数据
_requestPermissionsAndStart();
}
Future<void> _requestPermissionsAndStart() async {
// 请求位置权限
bool hasPermission = await _dataCollectionService.requestLocationPermissions();
if (hasPermission) {
// 开始收集位置数据
await _dataCollectionService.start();
} else {
// 处理权限被拒绝的情况
print('位置权限被拒绝');
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('后台定位示例'),
),
body: Center(
child: Text('检查控制台以查看位置数据'),
),
),
);
}
@override
void dispose() {
// 停止数据收集服务
_dataCollectionService.stop();
super.dispose();
}
}
这个示例展示了如何初始化carp_background_location
插件,请求位置权限,并开始定期收集位置数据。收集到的位置数据会在控制台中打印出来。
请注意,实际应用中你可能需要更复杂的错误处理和权限管理逻辑,以及考虑数据隐私和安全性问题。此外,后台定位可能会消耗更多的电池电量,因此请确保你的应用有足够的理由在后台运行并收集位置数据。