无法发送WhatsApp消息?net::ERR_UNKNOWN_URL_SCHEME错误排查
问题描述
点击Contact with seller按钮后,移动端控制台抛出以下错误:
Web page not available
The web page at whatsapp://send/?phone=923424627671&text=Hi%2C%20I%20am%20interested%20in%20the%20product%3A%0A%0AProduct%20Name%3A%20Electric%20%0AProduct%20Image%3A%20https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fecommerce-1b43e.appspot.com%2Fo%2Fimages1677497513119374%3Falt%3Dmedia&type=phone_number&app_absent=0 could not be loaded because:net::ERR_UNKNOWN_URL_SCHEME
- 网页端点击链接可正常跳转至WhatsApp网页版,点击
Continue to chat能发送消息 - 物理移动端触发上述URL协议错误
- APP内点击
Back键时会短暂显示WhatsApp网页但无法停留 - 疑问:是否必须添加WebView?如何解决上述错误?
现有实现代码
消息构建与跳转逻辑
String buildWhatsAppMessage() { String message = 'Hi, I am interested in the product:\n\n'; message += 'Product Name: ${widget.productName}\n'; message += 'Product Image: ${widget.url}\n'; message += 'Product Price: ${widget.productPrice}\n\n'; message += 'Please let me know more about it.'; return Uri.encodeFull(message); } void launchWhatsApp() async { String phoneNumber = 'https://wa.me/${widget.phonenumber}?text=${buildWhatsAppMessage()}'; if (await canLaunchUrl(Uri.parse(phoneNumber))){ launchUrl(Uri.parse(phoneNumber)); } else { showDialog(context: context, builder: (BuildContext context) { return AlertDialog( title: Text('Seller has no WhatsApp number'), content: Text('Unfortunately, the seller does not have a WhatsApp account.'), actions: [ ElevatedButton( child: Text('OK'), onPressed: () { Navigator.of(context).pop(); }, ), ], ); } ); } }
按钮组件代码
RoundedLoadingButton( child: Text( 'Contact with seller', style: TextStyle(color: Colors.white), ), controller: contact, resetDuration: Duration(seconds: 3), resetAfterDuration: true, width: 200, height: 50, color: Colors.blue, successColor: Colors.blue, borderRadius: 10, elevation: 3, onPressed: _isAddToContactLoading ? null : () async { setState(() { _isAddToContactLoading = true; }); launchWhatsApp(); setState(() { _isAddToContactLoading = false; }); _addCartController.success(); }, ),
解决方案
1. 修复URL协议错误
移动端报错是因为系统尝试用WebView解析whatsapp://私有协议,该协议仅能由WhatsApp原生APP处理。调整逻辑优先调用原生APP,失败时 fallback到网页版:
void launchWhatsApp() async { // 优先尝试原生APP协议 String nativeUrl = 'whatsapp://send?phone=${widget.phonenumber}&text=${buildWhatsAppMessage()}'; Uri nativeUri = Uri.parse(nativeUrl); if (await canLaunchUrl(nativeUri)) { await launchUrl(nativeUri, mode: LaunchMode.externalApplication); } else { // 原生APP不存在时跳转网页版 String webUrl = 'https://wa.me/${widget.phonenumber}?text=${buildWhatsAppMessage()}'; Uri webUri = Uri.parse(webUrl); if (await canLaunchUrl(webUri)) { await launchUrl(webUri, mode: LaunchMode.externalApplication); } else { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('无法打开WhatsApp'), content: const Text('请确保已安装WhatsApp或检查网络连接'), actions: [ ElevatedButton( child: const Text('确定'), onPressed: () { Navigator.of(context).pop(); }, ), ], ); }, ); } } }
2. 解决Back键短暂显示网页的问题
通过指定LaunchMode.externalApplication,让链接在外部应用(浏览器或WhatsApp)中打开,而非APP内置WebView,这样返回时就不会出现网页短暂闪现的问题。
3. 无需强制添加WebView
只要正确处理跳转优先级和打开模式,优先调用原生APP、失败时跳转网页版,就不需要额外添加WebView。
额外优化建议
- 确保
widget.phonenumber是带国家码的完整号码(如+923424627671),避免格式错误导致跳转失败 - 使用
url_launcher包的最新版本,提升跨平台兼容性
内容的提问来源于stack exchange,提问作者Muhammad Zohaib

