Skip to content

MissingPluginException "No implementation found for method" in path_provider when called from isolate #99155

Closed

Description

@Henk-Keijzer

E/flutter ( 9978): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: MissingPluginException(No implementation found for method getApplicationDocumentsDirectory on channel plugins.flutter.io/path_provider)
E/flutter ( 9978): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:165:7)
E/flutter ( 9978):
E/flutter ( 9978): #1 getApplicationDocumentsDirectory (package:path_provider/path_provider.dart:115:24)
E/flutter ( 9978):
E/flutter ( 9978): #2 onBackgroundStart (package:szwmobiletracker/main.dart:135:19)
E/flutter ( 9978):
E/flutter ( 9978):

Just updated to path_provider version 2.0.9

Activity

  1. stuartmorgan-g commented on Feb 25, 2022

    @stuartmorgan-g
    Contributor

    Please use the issue template when filing issues; your report is missing a lot of information that is requested in the template.

    What version of Flutter are you using? What platform is this on? What is the complete reproducible test case?

  2. Henk-Keijzer commented on Feb 25, 2022

    @Henk-Keijzer
    Author
  3. Henk-Keijzer commented on Feb 25, 2022

    @Henk-Keijzer
    Author

    And it worked before............

  4. stuartmorgan-g commented on Feb 25, 2022

    @stuartmorgan-g
    Contributor

    We still need a reproducible case.

    And it worked before............

    There was a recent change to path_provider_android, but to understand what the issue with that change is we need a reproducible test case.

  5. Henk-Keijzer commented on Feb 25, 2022

    @Henk-Keijzer
    Author

    But I'm not willing to share my complete program publicly. And I have no time to produce a dummy with the same issue.
    I just did a full flutter pub upgrade. These are the packages I use:

    import 'dart:async';
    import 'dart:io';
    import 'dart:convert';
    import 'package:intl/intl.dart';
    import 'package:geolocator/geolocator.dart';
    import 'package:flutter/material.dart';
    import 'package:qr_code_scanner/qr_code_scanner.dart';
    import 'package:http/http.dart' as http;
    import 'package:uuid/uuid.dart';
    import 'package:flutter_background_service/flutter_background_service.dart';
    import 'package:path_provider/path_provider.dart';
    import 'package:path/path.dart' as p;
    

    The stack trace with filenames and line numbers should provide enough insight for the experts to find where the issue is:

    E/flutter ( 9978): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: MissingPluginException(No implementation found for method getApplicationDocumentsDirectory on channel plugins.flutter.io/path_provider)
    E/flutter ( 9978): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:165:7)
    E/flutter ( 9978):
    E/flutter ( 9978): https://github.com/flutter/flutter/pull/1 getApplicationDocumentsDirectory (package:path_provider/path_provider.dart:115:24)
    E/flutter ( 9978):
    E/flutter ( 9978): https://github.com/flutter/flutter/pull/2 onBackgroundStart (package:szwmobiletracker/main.dart:135:19)
    E/flutter ( 9978):
    E/flutter ( 9978):
    
  6. stuartmorgan-g commented on Feb 25, 2022

    @stuartmorgan-g
    Contributor

    And I have no time to produce a dummy with the same issue.

    We need reproducible test cases to investigate issues. See https://github.com/flutter/flutter/wiki/Issue-hygiene#issues-should-have-clear-steps-to-reproduce and https://github.com/flutter/flutter/wiki/Issue-hygiene#issues-should-have-clear-steps-to-reproduce

    We have automated tests that use path_provider, and they pass. Your use case is clearly different in some way; without knowing how, we can't investigate.

    The stack trace with filenames and line numbers should provide enough insight for the experts to find where the issue is

    It isn't, because we don't know anything about what szwmobiletracker/main.dart:135 is doing. For instance, whether or not it is running in an isolate is likely important here, and we have absolutely no way to determine that from the information you have provided.

  7. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Feb 25, 2022
  8. Henk-Keijzer commented on Feb 26, 2022

    @Henk-Keijzer
    Author

    The call to path_provider ( Directory dir = await getApplicationDocumentsDirectory(); ) is indeed done from a background process, started using the flutter_background_service package.

  9. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Feb 26, 2022
  10. Henk-Keijzer commented on Feb 26, 2022

    @Henk-Keijzer
    Author

    Here is the code of an app giving exactly the same result when calling the path_provider from the background process.

    Details
    import 'dart:async';
    import 'dart:io';
    import 'package:flutter/material.dart';
    import 'package:flutter_background_service/flutter_background_service.dart';
    import 'package:path_provider/path_provider.dart';
    import 'package:path/path.dart' as p;
    
    late File dataFile;
    Timer bgEventTimer = Timer.periodic(const Duration(seconds: 15), (timer) {  }); // without a function, so it is actually cancelled
    
    Future main() async {
      WidgetsFlutterBinding.ensureInitialized();
      //
      // get the file path
      Directory dir = await getApplicationDocumentsDirectory();
      dataFile = File(p.join(dir.path, 'bgData.txt'));
      //
      await initializeBackgroundService();
      //
      runApp(const MyApp());
    }
    
    Future<void> initializeBackgroundService() async {
      final backgroundService = FlutterBackgroundService();
      await backgroundService.configure(
        androidConfiguration: AndroidConfiguration(
          // auto start service
          autoStart: true,
          // this will executed when app is in foreground or background in separated isolate
          onStart: onBackgroundStart,
          // true means that notification arte visible
          isForegroundMode: true,
        ),
        iosConfiguration: IosConfiguration(
          // auto start service
          autoStart: true,
          // this will executed when app is in foreground in separated isolate
          onForeground: onBackgroundStart,
          // you have to enable background fetch capability on xcode project
          onBackground: onBackgroundStart,
        ),
      );
    }
    
    void onBackgroundStart() async {
      WidgetsFlutterBinding.ensureInitialized();
      bgEventTimer.cancel(); // just in case we were still running
      final backgroundService = FlutterBackgroundService();
      Directory dir = await getApplicationDocumentsDirectory();
      File bgDataFile = File(p.join(dir.path, 'bgData.txt'));
      // just in case we started without a bgData file....
      if (bgDataFile.existsSync() == false) {
        backgroundService.stopBackgroundService(); // just exit the background service
        return;
      }
      //
      // start our timer job (after we defined it)
      //
      void bgTimerJob () async {
      }
      //
      bgEventTimer = Timer.periodic(const Duration(seconds: 1), (timer) { bgTimerJob(); });
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Path Provider test',
          theme: ThemeData(
            primarySwatch: Colors.green,
          ),
          home: const MyHomePage(title: 'Path Provider test'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({Key? key, required this.title}) : super(key: key);
      final String title;
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
              title: Text(widget.title),
          ),
          body: Center(
            child: Stack(
            ),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    
    
    }
    
  11. Henk-Keijzer commented on Feb 26, 2022

    @Henk-Keijzer
    Author

    By the way, I used shared_preferences before, but that gave the same problems in combination with the background service. I really do need to store info in a file in the background, also when the foreground is not running (could use the background sendData method, but where does that go when the foreground is not active?)

  12. stuartmorgan-g commented on Feb 26, 2022

    @stuartmorgan-g
    Contributor

    This is due to #98591 then, and is the path_provider version of #98473.

    The workaround described there will work for path_provider as well:

    • Add dependencies on path_provider_android and path_provider_ios.
    • At the beginning of your background isolate entry point, add something like:
      if (Platform.isAndroid) PathProviderAndroid.registerWith();
      if (Platform.isIOS) PathProviderIOS.registerWith();
      
  13. changed the title [-]Method not implemented in path_provider... ?[/-] [+]MissingPluginException "No implementation found for method" in path_provider when called from isolate[/+] on Feb 26, 2022
  14. added
    P1High-priority issues at the top of the work list
    p: path_providerPlugin that provides resolved paths to some platform directories
    on Feb 26, 2022
  15. Henk-Keijzer commented on Feb 26, 2022

    @Henk-Keijzer
    Author

    Ok, that works! Thanks!!

  16. Henk-Keijzer commented on Mar 1, 2022

    @Henk-Keijzer
    Author
  17. stuartmorgan-g commented on Mar 1, 2022

    @stuartmorgan-g
  18. Henk-Keijzer commented on Mar 1, 2022

    @Henk-Keijzer
    Author
  19. stuartmorgan-g commented on Mar 1, 2022

    @stuartmorgan-g
  20. stuartmorgan-g commented on Mar 3, 2022

    @stuartmorgan-g
    Contributor

    The longer-term solution is that anything setting up an isolate where plugins are expected to work should call DartPluginRegistrant.ensureInitialized(), which will run all Dart plugin registration (similar to how they already need to call WidgetsFlutterBinding.ensureInitialized() to make platform message work in the first place). That's not currently on stable yet though, as it only just landed on master.

  21. stuartmorgan-g commented on Mar 7, 2022

    @stuartmorgan-g
    Contributor

    To summarize the solution: at the start of the entry point for any isolate that needs to use plugins (where you are presumably already calling WidgetsFlutterBinding.ensureInitialized()):

    • For Flutter 2.11+ (currently master), call DartPluginRegistrant.ensureInitialized(), which will run the Dart plugin registration for all plugins that need it.
    • For older versions of Flutter, manually call the registerWith of any plugin implementations you use that have Dart registration. For path_provider, see above for details.

    Since the plan going forward is to require DartPluginRegistrant.ensureInitialized() in isolates, closing as fixed.

  22. Henk-Keijzer commented on Mar 7, 2022

    @Henk-Keijzer
    Author
  23. subhashish-bacancy commented on Mar 15, 2022

    @subhashish-bacancy
  24. github-actions commented on Mar 29, 2022

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  25. locked as resolved and limited conversation to collaborators on Mar 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority issues at the top of the work listp: path_providerPlugin that provides resolved paths to some platform directoriespackageflutter/packages repository. See also p: labels.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions