如何使用Flutter的URL_launcher包发送短信?

13

您好,我在寻找一个简单的例子(适用于Android和iOS),来使用此软件包发送短信。

https://pub.dartlang.org/packages/url_launcher

在插件页面上,我只看到如何打开带有电话号码的短信本机应用程序,但没有额外的消息。

sms:<phone number>, e.g. sms:5550101234 Send an SMS message to <phone 
number> using the default messaging app

你不能在没有用户交互的情况下自动发送短信。在Android上,你可以预填充文本框的正文,但在iOS上不行。请查看我的回答。 - shadowsheep
1
那么,如果有人真的想发送短信,而不仅仅是打开手机的默认短信应用程序,该怎么办呢? - undefined
5个回答

29

在 Android 上,完整的 sms: URI 受支持,您可以发送像这样带有正文的消息 (RFC5724):

 _textMe() async {
    // Android
    const uri = 'sms:+39 348 060 888?body=hello%20there';
    if (await canLaunch(uri)) {
      await launch(uri);
    } else {
      // iOS
      const uri = 'sms:0039-222-060-888?body=hello%20there';
      if (await canLaunch(uri)) {
        await launch(uri);
      } else {
        throw 'Could not launch $uri';
      }
    }
  }

enter image description here

官方文档显示,在 iOS 上你只能使用 URI 的电话号码字段。

但正如Konstantine所指出的,如果你使用一个非标准的URI,并且不是以?开头的查询字符串,而是用&代替,它仍然可以正常工作。这似乎是一个未记录在案的功能。

sms方案用于启动“信息”应用。此类URL的格式为“sms:”,其中参数<phone-number>是SMS消息的目标手机号码的可选参数。该参数可以包含数字0到9和加号(+),短横线(-)和句点(.)字符。 URL字符串不得包含任何消息文本或其他信息

PS:要检查平台,您可以使用dart.io库的Platform

 _textMe() async {
    if (Platform.isAndroid) {
      const uri = 'sms:+39 348 060 888?body=hello%20there';
      await launch(uri);
    } else if (Platform.isIOS) {
      // iOS
      const uri = 'sms:0039-222-060-888&body=hello%20there';
      await launch(uri);
    }
  }

谢谢您的快速回复,您知道如何添加一个变量吗?我尝试了这个方法,但是它不起作用:const uri = 'sms:$Phone_Number?body=hello%20there';其中“Phone_Number”是一个字符串变量。 - Nitneuq
@QuentinGuichot 奇怪...它应该可以工作。请参考这个,并在dartpad上尝试。 - shadowsheep
1
这是不正确的。在iOS上添加正文只需将问号?替换为和号&即可。因此,URL必须像这样:sms:898908098&body=text_to_send。在Android上,您可以使用带有问号的普通URL。 - Konstantin
@Konstantine 这很奇怪,因为在官方文档中你读到了“URL字符串不能包含任何消息文本或其他信息。”但如果它能工作,那就好了解了。我会尝试并相应地更新我的答案。 - shadowsheep
1
我正在尝试这个,但它无法识别正文。就像它正在重定向到短信,但它没有显示正文。 - Arslan Kaleem
显示剩余2条评论

8
你可以尝试在Android和iOS上使用这个:
sendMessage() async {
    if(Platform.isAndroid){
        //FOR Android
        url ='sms:+6000000000?body=message';
        await launch(url);
    } 
    else if(Platform.isIOS){
        //FOR IOS
        url ='sms:+6000000000&body=message';
    }
}

6

这篇回答是为寻找答案的新人准备的。

之前的回答是正确的,但它们在iOS上不起作用。该应用程序可能会在iOS上崩溃,但在Android上可以正常运行。

因此,我们需要按照以下方式实现发送短信来解决这个问题。

  String? encodeQueryParameters(Map<String, String> params) {
    return params.entries
        .map((e) => '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}')
        .join('&');
  }
  
Uri smsUri = Uri(
      scheme: 'sms',
      path: '$phoneNumber',
      query: encodeQueryParameters(<String, String>{
        'body':
            'Hey this is message body'
      }),
    );

    try {
      if (await canLaunch(smsUri.toString())) {
        await launch(smsUri.toString());
      }
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('Some error occured'),
        ),
      );
    }

5

这里是根据设备操作系统发送短信的更新答案。我之前尝试过之前的答案,但在IOS设备上遇到了正文文本问题。

_launchSms() async {
    try {
      if (Platform.isAndroid) {
        String uri = 'sms:$phoneNumber?body=${Uri.encodeComponent("Hello there")}';
        await launchUrl(Uri.parse(uri));
      } else if (Platform.isIOS) {
        String uri = 'sms:$phoneNumber&body=${Uri.encodeComponent("Hello there")}';
        await launchUrl(Uri.parse(uri));
      }
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('Some error occurred. Please try again!'),
        ),
      );
    }
  }

1
这是在iOS中对我有效的唯一方法。 - Ivan Santos

2

在Flutter 3和最新的URL Launcher包发布后,更新了最终答案。

smsUri = Uri(scheme: 'sms', path: phoneNumber);

try {
  print(smsUri.toString());
  if (await canLaunchUrl(
    smsUri,
  )) {
    await launchUrl(smsUri);
  }
} catch (e) {
  ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(
      content: const Text('Some error occured'),
    ),
  );
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接