3

I have a little link in my app that says "Send us an e-mail". When you click it, I want the default email app to open, with an email started to our email address. I used to make it do exactly that with the launch() method in the url_launcher package like this:

import 'package:url_launcher/url_launcher.dart' as url;

Future<bool?> pressedSendUsEmail() async {
  bool? success;
  try {
    print('Pressed Send us an e-mail...');
    success = await url.launch('mailto:our.email@gmail.com');  // Works like a charm...
    print('success is $success');
  } catch (e) {
    print('Caught an error in Send us an e-mail!');
    print('e is: ${e.toString()}');
  }
  return success;
}

But now, I get a warning saying launch() is deprecated! I should use launchUrl() instead. But launchUrl() doesn't take a String argument, it takes a Uri argument... and I don't know how to write this Uri correctly, so that it does what I want! I tried:

  success = await url.launchUrl(Uri(path: 'mailto:our.email@gmail.com'));

but that throws an error, because it can't interpret the ":" character. I've tried:

  success = await url.launchUrl(
    Uri.https('mailto:our.email@gmail.com', ''),
  );

and that launches the link, but in the browser... and it doesn't start up an e-mail to the pre-printed address. I tried adding:

  success = await url.launchUrl(
    Uri.https('mailto:our.email@gmail.com', ''),
    mode: url.LaunchMode.externalApplication,
  );

and that gives me an option of which external app to open the link with, but unfortunately, only browser apps are listed... not the email app!

How should I write my command to make the launchUrl() just do exactly what the old launch() did?? Most grateful for help!


Edit:

After that question was satisfactorily answered below, I now have a follow-up qn:

In another part of the app, there is a place where the user can type in a link, and I used to launch it with launch()... Is there a simple way to do that, as well?

Because in that case, I don't know if the link is gonna be a http or a https or indeed a mailto:!... and I would prefer not having to write lots of code to find that out! I just want it to try and launch the link exactly the way it's written, and so long as it's written correctly, it will work.

Karolina Hagegård
  • 1,180
  • 5
  • 26

2 Answers2

7

Try this:

void _sendEmail(){
   final Uri emailLaunchUri = Uri(
     scheme: 'mailto',
     path: 'our.email@gmail.com',
     queryParameters: {
      'subject': 'CallOut user Profile',
      'body': widget.userModel?.username ?? ''
     },
    );
   launchUrl(emailLaunchUri);
}
Xuuan Thuc
  • 2,340
  • 1
  • 5
  • 22
  • Looks good!... I wasn't planning to add any subject or body, but then I guess I can just use this without the whole `query:` part? – Karolina Hagegård Jun 30 '22 at 09:51
  • remove if you don't need it – Xuuan Thuc Jun 30 '22 at 10:03
  • 1
    Uh, queryParameters can be given a Map and it just does the right thing. Your whole "encodeQueryParameters" is completely redundant, and partially wrong. Please remove. See https://api.dart.dev/stable/2.17.5/dart-core/Uri/queryParameters.html for details. – Randal Schwartz Jul 01 '22 at 03:26
  • @RandalSchwartz , what is this "queryParameters" you're talking about? My AS doesn't find it in the `url_laucher` package or elsewhere! And the "query" property of the Uri above takes a String argument, and not a Map... – Karolina Hagegård Jul 01 '22 at 18:15
  • And PS, the `encodeQueryParameters()` sub method in @XuannThucc's answer above works fine... – Karolina Hagegård Jul 01 '22 at 18:20
  • See my answer. It's an argument to Uri! – Randal Schwartz Jul 01 '22 at 19:59
  • I've seen it, and accepted it. You should change the wording, though! No need to refer to an "other answer" in your answer. People are only supposed to have to read ONE answer. @RandalSchwartz – Karolina Hagegård Jul 13 '22 at 18:45
3

No need for the other answer's pointless redundant subroutine when it's already built in to Uri!

void _sendEmail(){
    final Uri emailLaunchUri = Uri(
        scheme: 'mailto',
        path: 'our.email@gmail.com',
        queryParameters: {
            'subject': 'CallOut user Profile',
            'body': widget.userModel?.username ?? ''
        },
    );
    launchUrl(emailLaunchUri);
}
Muhammad Vaid
  • 125
  • 2
  • 9
Randal Schwartz
  • 39,428
  • 4
  • 43
  • 70
  • Ooooh, now I get it! Nice work, thank you! If only you had been a bit clearer a bit earlier, I wouldn't have marked that other answer as the correct one. (Although it also did the job!) – Karolina Hagegård Jul 03 '22 at 15:04
  • But now, I have a follow-up qn!: In another part of the app, there is a place where the user can type in a link, and I used to launch it with `launch()`... Do you have a simple way to do that, as well? Because in that case, I don't know if the link is gonna be a `http` or a `https` or indeed a `mailto:`!... and I would prefer not having to write lots of code to find that out! – Karolina Hagegård Jul 03 '22 at 15:08
  • 1
    You can certainly Uri.parse(aString) to get the components. – Randal Schwartz Jul 03 '22 at 17:46
  • That is a wonderful, universal solution to all my problems! Let's update question and answer with this. – Karolina Hagegård Jul 05 '22 at 07:46