2

I'm working on a mailing application and i'm stuck when i try to share a file to send it by email with the receive_sharing_intent package

I'm able to get the file in the application with it's path and all, but then i need to redirect the user to the mail editor page. When i try to use this to get to the mailEditor page :

Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => MailEditor(
            message: message,
            editorType: 'new',
          ),
        ),
      );

I get this error :

[ERROR:flutter/shell/common/shell.cc(213)] Dart Error: Unhandled exception: Navigator operation requested with a context that does not include a Navigator. The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.

This package being developed by the community i couldn't find much help anywhere on the internet.

I failed to use the ReceiveSharingIntent method anywhere else than the main.dart file, so maybe there's a way to use it directly on my mailEditor page that i didn't find?

If more code is needed here is my ReceiveSharingIntent method :

class MyApp extends StatefulWidget {
  // This widget is the root of your application.
  @override
  _MssProState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void dispose() {
    _intentDataStreamSubscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // For sharing images coming from outside the app while the app is in the memory
    _intentDataStreamSubscription = ReceiveSharingIntent.getMediaStream().listen((List<SharedMediaFile> value) {
      _sharedFiles = value;

      Message message = Message();
      for (var i = 0; i < _sharedFiles.length; i++) {
        File file = File(_sharedFiles[i].path);

        Attachment attachment = Attachment(
          fileName: basename(file.path),
          attachmentPart: i + 1,
          contentType: lookupMimeType(file.path),
          name: basename(file.path),
        );
      }

        Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => MailEditor(
            message: message,
            editorType: 'new',
          ),
        ),
      ); 
    });

    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Login(),
      routes: {
        '/login': (BuildContext context) => Login(),
      },
    );
  }

Thanks a lot for any help and suggestions, i've been stuck on this for a while.

Edit: Added more code for context

Anthony D
  • 323
  • 8
  • 19

1 Answers1

0

Navigator should be used inside the build() method. If you want to use context outside of it, pass it as an argument like BuildContext context.

wafL
  • 577
  • 4
  • 14
  • Yes you are right, and in fact it is in the build method of the main.dart file. The problem is that the share intents are coming from outside the app, and directly call this method, so it doesn't start the app in the same way i guess and this must cause the context to not be ready when i need it – Anthony D Aug 20 '20 at 12:06
  • 1
    @AnthonyD Indeed. If you are in the middle of a Widget transition, that being going back or forth, you can't call navigator, because it is in what is called "Bad State". SetState and Navigator should only be called after initState and before dispose. – wafL Aug 20 '20 at 12:09
  • It must be feasible in a way, it does work for gmail. Maybe there's a way to wait for the good state for me to call the navigator? – Anthony D Aug 20 '20 at 12:40
  • 1
    @AnthonyD you don't wait for the state to turn good. It has to do when you call setState. For example, caliing setState() inside initState is going to throw an error, because the initState function has the purpose to execute code before the build function. Therefore, you can't say to the app to rebuild before it is even build. Furthermore, calling setState on dispose is useless, since the build that has been made was discarded, and you are calling for it to rebuild. If you call `_intentDataStreamSubscription` during initState(), that same error will occur. May I ask for more code, for context? – wafL Aug 20 '20 at 13:35
  • To be honest i don't really how the package works internaly, right now i'm trying to share the intent while the application is in memory (I'll do the non-launched version afterwards if this does work) so the build method should have already built. Thanks for your time, i added more code to the question ! – Anthony D Aug 20 '20 at 14:42
  • @AnthonyD the last thing I would try is to insert `_intentDataStreamSubscription` to the initState() function, so the listener can be registered prior to the build function. – wafL Aug 20 '20 at 14:47