Flutter WebView无法打开社交平台链接及Android端无法唤起外部WhatsApp应用问题咨询
兄弟,我来帮你搞定这俩头疼的问题!用的是flutter_webview_plugin 2.3.1是吧?咱直接上干货:
一、处理Telegram/WhatsApp/Facebook/Twitter等链接无法打开的问题
核心思路是拦截这些外部应用的Scheme或专属域名,不让WebView自己加载,而是直接唤起对应的外部App。具体步骤如下:
1. 添加依赖
首先在pubspec.yaml里加上url_launcher(用来唤起外部应用),选个和你Flutter版本兼容的版本就行:
dependencies: flutter: sdk: flutter flutter_webview_plugin: ^2.3.1 url_launcher: ^6.1.12 # 版本可根据你的Flutter环境调整
2. 拦截URL并唤起外部应用
初始化WebView的时候,监听URL变化,判断是否是外部应用的链接,如果是就拦截并唤起对应App:
import 'package:flutter/material.dart'; import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'; import 'package:url_launcher/url_launcher.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { final FlutterWebviewPlugin _webviewPlugin = FlutterWebviewPlugin(); final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>(); MyApp() { // 监听URL变化,拦截外部应用链接 _webviewPlugin.onUrlChanged.listen((String url) async { // 定义需要拦截的外部应用Scheme和专属域名 const externalSchemes = [ 'whatsapp:', 'tg:', 'telegram:', 'fb:', 'facebook:', 'twitter:', 'x:' ]; const externalDomains = [ 'wa.me', 'api.whatsapp.com', 't.me', 'telegram.me', 'facebook.com', 'twitter.com', 'x.com' ]; // 判断是否是外部应用链接 bool isExternalLink = externalSchemes.any((scheme) => url.startsWith(scheme)) || externalDomains.any((domain) => url.contains(domain)); if (isExternalLink) { // 先阻止WebView加载这个链接 _webviewPlugin.stopLoading(); // 尝试唤起外部应用 if (await canLaunch(url)) { await launch(url); } else { // 唤起失败就提示用户安装对应App if (_navigatorKey.currentContext != null) { ScaffoldMessenger.of(_navigatorKey.currentContext!).showSnackBar( const SnackBar(content: Text('请先安装对应的应用哦')), ); } } } }); } @override Widget build(BuildContext context) { return MaterialApp( navigatorKey: _navigatorKey, home: WebviewScaffold( url: '你的网页地址', // 替换成你的实际网页URL appBar: const AppBar(title: Text('我的WebView应用')), // 开启必要的WebView配置 withJavascript: true, withLocalStorage: true, ), ); } }
3. 配置AndroidManifest.xml(关键!)
Android 11及以上版本需要声明允许查询外部应用,不然canLaunch会返回false。在android/app/src/main/AndroidManifest.xml里添加以下内容:
<manifest ...> <!-- 其他内容 --> <queries> <!-- 允许查询WhatsApp --> <package android:name="com.whatsapp" /> <!-- 允许查询Telegram --> <package android:name="org.telegram.messenger" /> <!-- 允许查询Facebook --> <package android:name="com.facebook.katana" /> <!-- 允许查询Twitter/X --> <package android:name="com.twitter.android" /> </queries> <application ...> <!-- 其他内容 --> </application> </manifest>
如果不想逐个指定包名,也可以用<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />,但这个权限在Google Play上架需要说明用途,所以更推荐上面的方式。
二、解决WhatsApp分享按钮无法唤起外部应用的问题
这个问题本质和上面一样——网页里的分享链接(比如https://wa.me/xxx?text=xxx)被WebView当成普通网页加载了,咱只要把它也加入拦截列表就行。
上面的代码已经把wa.me和api.whatsapp.com加入了externalDomains,所以点击分享按钮时,WebView会自动拦截这个链接,调用url_launcher唤起WhatsApp,不会再跳转到“页面未找到”了。
如果你的分享链接是自定义的(比如网页内的JavaScript触发的分享),也可以让前端同事把分享链接改成whatsapp://send?text=xxx这种Scheme格式,拦截起来更直接。
内容的提问来源于stack exchange,提问作者prakash Mp

