flutter_background_service
flutter_background_service copied to clipboard
how to work with other plugin?
i am write an app that can backgroud location tracking and use flutter_bmflocation=3.2.1. it is run fine,when app is first start and ervery thing work fine. but when i killed the app, it don't track,and catch the third plugin MissingPluginException.
E/flutter (23674): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method flutter_bmflocation/setOptions on channel flutter_bmflocation)
E/flutter (23674): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:294:7)
E/flutter (23674): <asynchronous suspension>
E/flutter (23674): #1 BMFLocationOptionsDispatcher.setLocationOptions (package:flutter_bmflocation/src/private/dispatcher/bdmap_location_options_dispather.dart:15:18)
E/flutter (23674): <asynchronous suspension>
E/flutter (23674):
and my onStart code is like this:
@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
WidgetsFlutterBinding.ensureInitialized();
DartPluginRegistrant.ensureInitialized();
final LocationFlutterPlugin locPlugin = LocationFlutterPlugin();
SpUtils.init();
if (service is AndroidServiceInstance) {
service.on('setAsForeground').listen((event) {
service.setAsForegroundService();
});
service.on('setAsBackground').listen((event) {
service.setAsBackgroundService();
});
}
service.on('stopService').listen((event) {
locPlugin.stopLocation();
service.stopSelf();
});
// location track callback ,return location info
locPlugin.seriesLocationCallback(callback: (data){
service.invoke("updateLocation", {"location":data.getMap()});
});
Timer.periodic(const Duration(seconds: 5), (timer) async {
if (service is AndroidServiceInstance) {
if (await service.isForegroundService()) {
service.setForegroundNotificationInfo(
title: "My App Service",
content: "Updated at ${DateTime.now()}",
);
}
}
service.invoke('update', {"current_date": DateTime.now().toIso8601String(),},);
bool? isAgree = SpUtils.getBaiduAgree();
bool isPermission = await PermissionUtils.checkPermissionStatus(Permission.location);
print("isAgree ${isAgree} isPermission ${isPermission}");
if (isAgree && isPermission){
BaiduLocationAndroidOption androidOption = BaiduPlugin.initAndroidOptions();
BaiduLocationIOSOption iosOption = BaiduPlugin.initIOSOptions();
print('location settings:${iosOption.getMap()}');
locPlugin.prepareLoc(androidOption.getMap(), iosOption.getMap());
print('start location track');
locPlugin.startLocation();
}
});
}
There are so many kinds of flutter plugin that requires an Activity object for registering their platform channels. Since the Service is not an Activity, there is impossible to use any flutter plugin that requires an Activity. You have to look into the plugin native code, and if you found that platform channel is registered in onActivityAttached, or any method handler requires an activity from it, then it means we cannot use that plugin in a Service.
@ekasetiawans At the beginning, I thought the same as you, so I went to check the source code, but didn't find any need for Activity. i have no idea, so i came here for help.
@xiaochonzi have you tried with other flutter plugin, for example shared_preferences? if you can use any method from it, then i think the problem is in the plugin you use.
@ekasetiawans yes ,i have runed the example which you write. and ervery thing run fine.
@ekasetiawans I've solved the problem, and sure enough it was a problem with a 3rd party plugin that used the static keyword when declaring the MethodChannel in android java code. But what is puzzling is how static affects this bug.
@ekasetiawans I've solved the problem, and sure enough it was a problem with a 3rd party plugin that used the static keyword when declaring the MethodChannel in android java code. But what is puzzling is how static affects this bug.
Could you elaborate more?
I use the geolocator package and it works fine with this lib
I use the geolocator package and it works fine with this lib
How did you use the geolocator package can you share your source code?
I use the geolocator package and it works fine with this lib
Yes, this plugin is working fine.
Process:
- Add the plugin geolocator: {{latestversion}}
- follow my code to add geo location with onStart()
Future<Position> _determinePosition() async {
bool serviceEnabled;
LocationPermission permission;
// Test if location services are enabled.
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
// Location services are not enabled don't continue
// accessing the position and request users of the
// App to enable the location services.
return Future.error('Location services are disabled.');
}
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
// Permissions are denied, next time you could try
// requesting permissions again (this is also where
// Android's shouldShowRequestPermissionRationale
// returned true. According to Android guidelines
// your App should show an explanatory UI now.
return Future.error('Location permissions are denied');
}
}
if (permission == LocationPermission.deniedForever) {
// Permissions are denied forever, handle appropriately.
return Future.error(
'Location permissions are permanently denied, we cannot request permissions.');
}
// When we reach here, permissions are granted and we can
// continue accessing the position of the device.
return await Geolocator.getCurrentPosition();
}
@pragma('vm:entry-point')
void onStart(
ServiceInstance service,
// LocationControllerCubit locationControllerCubit,
// UpdateLocationOnDbCubit updateLocationOnDbCubit,
) async {
// For flutter prior to version 3.0.0
// We have to register the plugin manually
/// OPTIONAL when use custom notification
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
double longitude = 0;
double latitude = 0;
if (service is AndroidServiceInstance) {
service.on('start_service').listen((event) async {
await service.setAsForegroundService();
});
service.on('setAsForeground').listen((event) async {
await service.setAsForegroundService();
});
service.on('setAsBackground').listen((event) async {
await service.setAsBackgroundService();
});
}
service.on("stop_service").listen((event) async {
await service.stopSelf();
});
// bring to foreground
Timer.periodic(const Duration(seconds: 1), (timer) async {
if (service is AndroidServiceInstance) {
if (await service.isForegroundService()) {
final location = await _determinePosition();
if (longitude != location.longitude || latitude != location.latitude) {
longitude = location.longitude;
latitude = location.latitude;
flutterLocalNotificationsPlugin.show(
888,
'COOL LOCATION SERVICE',
'Latitude: ${location.latitude}, Longitude: ${location.longitude}',
const NotificationDetails(
android: AndroidNotificationDetails(
'my_foreground',
'AWESOME SERVICE:',
icon: 'ic_bg_service_small',
ongoing: true,
),
),
payload: "service",
);
print("+++++++++BACKGROUND LOCATION++++++++");
print(location.latitude);
print(location.longitude);
}
}
}
});
}
How to work with plugin that don't hace registerWith? I cannot use record (https://pub.dev/packages/record) with flutter_background_service
@kotoSky 我自己重写了百度地图的flutter插件,可以和flutter_background_service一起用,而且在项目中用起来了
@kotoSky 厉害
@xiaochonzi 大佬您的插件我突然发现介绍说只支持安卓,如果不支持苹果那您编写的高德地图是不是安卓苹果都可以用,我要么前台定位换成高德,后台换成百度
@kotoSky ios没有安卓那套机制,后台运行如果app被划掉,就没法后台运行了。(好比使用网易云音乐听歌,如果网易云后台划掉就不能听)所以我只做了安卓部分,另外我觉得百度的定位其实要比高德的好,而且我的那个高德定位插件很久没有更新了。
@xiaochonzi 如果你想在ios也是用百度地图也简单。找到百度自己写的flutter插件,找到ios部分代码拿过来改一下就行。
@kotoSky 厉害,可以试试开源一下,我的毕竟是半成品,如果你安卓和ios都搞好了,可以服务更多人
@xiaochonzi 还得是大佬写的dart端代码稳,让我只是在你代码上cv一下就完成了,但是目前IOS只有一个单次定位功能,我试着把其他功能都弄好再上传一下