我有一个简单的页面,上面有一个按钮,当按下这个按钮时,会使用Async Clipboard API来写入剪贴板。
<body>
<button type="button" onclick="testClipboard();">
Test Clipboard
</button>
</body>
function testClipboard() {
navigator.clipboard.writeText("Clipboard API Test").then(
v => alert("Success"),
e => alert("Fail\n" + e));
}
这在Chrome和Firefox、桌面和移动设备上都能工作。然而在Android Webview上,它却抛出了以下错误。
NotAllowError: Write permission denied.
我想我需要覆盖 WebChromeClient.onPermissionRequest()
但奇怪的是 onPermissionRequest()
似乎并没有被调用,仍然出现同样的错误。
public class WebChromeController extends WebChromeClient {
@Override
public void onPermissionRequest(PermissionRequest request) {
Log.d("myTag", "Permission request");
Log.d("myTag", request.getResources().toString());
request.grant(request.getResources());
}
}
protected void initWebView() {
// ...
myWebView.setWebChromeClient(new WebChromeController());
}
我仍然得到同样的错误。
NotAllowError: Write permission denied.
Logcat也没有任何记录
我怀疑可能我的Android App需要额外的权限才能访问剪贴板,但根据 https:/developer.android.comaboutversions10privacychanges#clipboard-data。,我的App在有焦点的时候应该有权限。事实上,下面的代码是可行的。
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("MyLbl", "I have permission");
clipboard.setPrimaryClip(clip);
我还在下面声明了 AndroidManifest.xml
以防请求许可的行动需要许可。
<uses-permission android:name="android.webkit.PermissionRequest" />
这没有任何作用.
所以这可能不是App级权限的问题。
到底发生了什么?
如何让Async Clipboard API调用在Webview中工作?
操作系统:Android 10 Q
Webview: v. 81.0.4044.111
剪贴板API writeText
方法文档中说,我们需要获得 clipboard-write
使用Permissions api的权限,但 navigator.permission
在webview中是未定义的,也许是因为他们不想把web权限和android操作系统的权限混在一起。
还有一种方法,我们可以从android webview中复制文本到剪贴板(通过从webview的javascript代码中调用本地java方法)。
首先在webview上启用javascript。
myWebView.getSettings().setJavaScriptEnabled(true);
然后添加javascript接口。
myWebView.addJavascriptInterface(new WebAppInterface(), "NativeAndroid");
创建一个方法,将文本复制到剪贴板,使用的是 android.content.ClipboardManager
public class WebAppInterface {
@JavascriptInterface
public void copyToClipboard(String text) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("demo", text);
clipboard.setPrimaryClip(clip);
}
}
现在你可以从 testClipboard
方法。
function testClipboard() {
navigator.clipboard.writeText("Clipboard API Test").then(
v => alert("Success"),
e => alert("Fail\n" + e));
NativeAndroid.copyToClipboard("Clipboard API Test");
}