flutter_background_fetch
flutter_background_fetch copied to clipboard
[BUG] No implementation found for method listen
After upgrading to Flutter 3.3 and doing some refactorings on our app we are seeing some very high incidents of background crashes for Android users.
Environment
- Plugin version: 1.1.0 to 1.1.2
- Platform: Android
- OS version: Android 5 to 13
- Device manufacturer / model: Samsung, Google and others
- Flutter info (
flutter info
,flutter doctor
): [✓] Flutter (Channel stable, 3.3.6, on macOS 12.6 21G115 darwin-x64, locale en-GB) [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3) [✓] Xcode - develop for iOS and macOS (Xcode 14.0.1) [✓] Chrome - develop for the web [✓] Android Studio (version 2020.3) [✓] VS Code (version 1.73.0) [✓] Connected device (2 available) [✓] HTTP Host Availability - Plugin config: see below
To Reproduce We can't reproduce the error, but we get about 40 thousand crashes daily affecting about 13 thousand Android users of our app. These crashes all report the following:
Non-fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError: MissingPluginException(No implementation found for method listen on channel com.transistorsoft/flutter_background_fetch/events). Error thrown Instance of 'ErrorDescription'.
at MethodChannel._invokeMethod(platform_channel.dart:294)
at EventChannel.receiveBroadcastStream.<fn>(platform_channel.dart:637)
The config is as follows:
import 'dart:async';
import 'dart:io';
import 'dart:ui';
import 'package:background_fetch/background_fetch.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';
import '../../service_locator.dart';
import 'store_service.dart';
import 'download_service.dart';
class ScheduleService extends StatefulWidget {
final Widget? child;
const ScheduleService({Key? key, this.child}) : super(key: key);
@override
_ScheduleServiceState createState() => _ScheduleServiceState();
}
class _ScheduleServiceState extends State<ScheduleService> {
@override
Widget build(BuildContext context) {
return widget.child!;
}
Future<void> _onTimeout(String taskId) async {
BackgroundFetch.finish(taskId);
}
Future<void> _onFetch(String taskId) async {
await locator<DownloadService>().runBackgroundTask();
BackgroundFetch.finish(taskId);
}
Future<void> _initPlatformState() async {
final store = locator<StoreService>();
final config = BackgroundFetchConfig(
minimumFetchInterval: 60, // 60 minutes
enableHeadless: true,
requiresBatteryNotLow: false,
requiresCharging: false,
requiresStorageNotLow: false,
requiresDeviceIdle: true,
requiredNetworkType:
store.useMobileData ? NetworkType.ANY : NetworkType.UNMETERED,
);
// from the docs: "There is no such thing as stopOnTerminate: false for iOS"
if (!Platform.isIOS) {
config.stopOnTerminate = false;
}
try {
await BackgroundFetch.configure(config, _onFetch, _onTimeout);
} catch (e, s) {
FirebaseCrashlytics.instance
.recordError(e, s, reason: 'BackgroundFetch.configure');
}
}
@override
void initState() {
super.initState();
BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
// do some async setup
Future.delayed(const Duration(seconds: 3), () async {
await _initPlatformState();
});
}
}
/// This "Headless Task" is run when app is terminated.
@pragma('vm:entry-point')
Future<void> backgroundFetchHeadlessTask(HeadlessTask task) async {
if (task.timeout) {
BackgroundFetch.finish(task.taskId);
return;
}
/// temporary workaround till Flutter 2.11+
/// https://github.com/flutter/flutter/issues/99155#issuecomment-1060956399
// if (Platform.isAndroid) PathProviderAndroid.registerWith();
// if (Platform.isIOS) PathProviderIOS.registerWith();
DartPluginRegistrant.ensureInitialized();
await Firebase.initializeApp();
await setupHeadlessServiceLocator(await StoreService.instance());
if (!locator<StoreService>().hasStartDate) {
BackgroundFetch.finish(task.taskId);
return;
}
await locator<DownloadService>().runBackgroundTask();
BackgroundFetch.finish(task.taskId);
}
@override
void initState() {
super.initState();
BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
You must not .registerHeadlessTask
within a Widget
. You must do that in your lib/main.dart
.
See API docs
Thank you for your quick response @christocracy . We will refactor asap and check.
You must not
.registerHeadlessTask
within aWidget
can I do it in static method?
Just follow the instructions exactly and put it in main.dart as directed.
Still Facing same issue.
Same issue for me
This issue is stale because it has been open for 30 days with no activity.
This issue was closed because it has been inactive for 14 days since being marked as stale.