You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter升级url_launcher 6.1.3后发短信报Uri类型不匹配错误

问题说明

将url_launcher插件升级至6.1.3版本后,向号码31003发送内容格式为「LS 用户驾照编号」的短信时,在拼接URI调用launchUrl方法的位置抛出类型错误:

The argument type 'String' can't be assigned to the parameter type 'Uri'

除该错误外其余业务逻辑运行正常,原有业务代码如下:

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:url_launcher/url_launcher.dart';

final Uri _url1 = Uri.parse('sms:31003?body=LC%20');
final textFieldController = TextEditingController();

class SeeSms extends StatelessWidget {
  const SeeSms({Key? key}) : super(key: key);
  

  @override
  Widget build(BuildContext context) {
    return GridView.count(
      crossAxisCount: 2,
      primary: false,
      padding: const EdgeInsets.all(20),
      crossAxisSpacing: 5,
      mainAxisSpacing: 5,
      childAspectRatio: 1,
      children: <Widget>[
        InkWell(
          onTap: _launchURL1,
          child: Container(
            padding: const EdgeInsets.only(top: 20),
            decoration: BoxDecoration(
              image: const DecorationImage(
                image: AssetImage('assets/images/ntc.png'),
                fit: BoxFit.cover,
              ),
              borderRadius: BorderRadius.circular(10),
              boxShadow: const [
                BoxShadow(
                  color: Color(0x19000000),
                  blurRadius: 20,
                  offset: Offset(0, 1),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }

  _launchURL1() async {
    // 弹窗获取用户输入的驾照编号
    String licenseNumber = await Get.defaultDialog(
      radius: 3,
      titlePadding: const EdgeInsets.only(top: 20, bottom: 20),
      contentPadding: const EdgeInsets.only(left: 20, right: 20),
      title: 'Enter License Number',
      content: TextField(
        controller: textFieldController,
        autofocus: true,
        decoration: const InputDecoration(
          hintText: 'Example: 01-01-00012345',
        ),
      ),
      confirm: Padding(
        padding: const EdgeInsets.only(bottom: 20.0, top: 20.0),
        child: ElevatedButton(
          child: const Text('Send SMS '),
          onPressed: () {
            Get.back();
            launchUrl(_url1 + textFieldController.text);
          },
        ),
      ),
    );
  }
}
错误原因

url_launcher 6.x及以上版本做了API破坏性变更:launchUrl方法强制要求入参为Uri类型,不再支持直接传入字符串格式的地址。
原有代码中_url1是提前解析好的Uri对象,使用+运算符拼接字符串后,整个表达式的返回值会变成String类型,不符合方法的入参类型要求,因此抛出编译错误。

修复方法

不要直接对Uri对象做字符串拼接,先拼接完整的短信协议字符串,对用户输入的内容做URL编码避免特殊字符解析异常,最后再将完整字符串解析为Uri类型传入方法即可,修复后的按钮点击逻辑如下:

onPressed: () async {
  Get.back();
  final inputText = textFieldController.text.trim();
  // 拼接完整短信地址,对内容做URL编码后转Uri
  final smsUri = Uri.parse(
    'sms:31003?body=${Uri.encodeComponent("LS $inputText")}'
  );
  // 增加可用性判断,避免设备无短信应用时崩溃
  if (await canLaunchUrl(smsUri)) {
    await launchUrl(smsUri);
  }
  // 用完清空输入框,避免下次打开残留上次输入内容
  textFieldController.clear();
},

修复点说明:

  • 移除提前定义的_url1常量,改为拿到用户输入后动态生成完整Uri,从根源避免类型不匹配问题
  • 使用Uri.encodeComponent对短信内容做编码,防止输入内容带特殊字符(比如空格、&、=)时出现短信内容截断
  • 增加canLaunchUrl校验,兼容无法打开短信应用的异常场景
  • 发送后清空输入框,优化交互体验

内容的提问来源于stack exchange,提问作者Mohammad Zakir Raza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 21:45:34