webview_flutter Android端无法通过JS navigator.clipboard.writeText复制文本
Android Flutter WebView 剪贴板复制权限问题解决方案
问题背景
在Android设备上使用Flutter的webview_flutter组件加载含JS剪贴板复制功能的页面时,点击复制按钮会触发NotAllowedError: Write permission denied错误,iOS端无此问题。官方明确表示不会修复该问题,建议通过JavaScript Channel结合Flutter原生剪贴板API实现。
可行解决方案
通过桥接Web页面的JS逻辑与Flutter原生剪贴板功能,绕过WebView的JS权限限制。以下是完整可运行的实现代码:
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:flutter/services.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { late WebViewController _webViewController; @override Widget build(BuildContext context) { return MaterialApp( home: SafeArea( child: WebView( initialUrl: "https://www.w3schools.com/howto/howto_js_copy_clipboard.asp", javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (controller) { _webViewController = controller; // 注册JavaScript Channel,用于Web与Flutter的通信 _webViewController.addJavaScriptChannel( 'FlutterClipboard', onMessageReceived: (message) async { // 接收Web页面传递的文本,调用Flutter原生剪贴板API完成复制 await Clipboard.setData(ClipboardData(text: message.message)); // 可选:给Web页面返回复制成功提示 _webViewController.runJavascript('alert("文本已复制到剪贴板")'); }, ); }, onPageFinished: (url) { // 页面加载完成后,注入JS重写原页面的复制函数 _webViewController.runJavascript(''' function copyText() { var copyText = document.getElementById("myInput"); copyText.select(); copyText.setSelectionRange(0, 99999); // 将文本传递给Flutter端处理 FlutterClipboard.postMessage(copyText.value); } '''); }, ), ), ); } }
实现说明
- 注册JavaScript Channel:通过
addJavaScriptChannel创建名为FlutterClipboard的通信通道,Web页面可通过该通道向Flutter传递要复制的文本。 - 重写Web页面复制逻辑:页面加载完成后注入JS代码,替换原有的
copyText函数,保留原页面选中文本的视觉反馈,将复制操作转交给Flutter原生处理。 - Flutter原生复制:通过
Clipboard.setData调用系统剪贴板API,不受WebView的JS权限限制,确保复制操作成功执行。
注意事项
- 必须将
javascriptMode设置为JavascriptMode.unrestricted,否则无法启用JavaScript Channel和注入JS代码。 - 若为自定义Web页面,可直接在页面的复制逻辑中调用
FlutterClipboard.postMessage(text),无需重写函数。 - 无需额外权限依赖包,Flutter的
ClipboardAPI无需申请系统权限。
内容的提问来源于stack exchange,提问作者Hunter ISMob
相关产品推荐
相关产品推荐

