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
相关产品推荐
相关产品推荐

