【问题标题】:Clipboard API call throws NotAllowedError without invoking onPermissionRequest()剪贴板 API 调用抛出 NotAllowedError 而不调用 onPermissionRequest()
【发布时间】:2020-07-29 07:16:42
【问题描述】:

我有一个带有按钮的简单页面,当按下该按钮时,它使用异步剪贴板 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 应用可能需要额外的权限才能访问剪贴板,但根据https://developer.android.com/about/versions/10/privacy/changes#clipboard-data,我的应用在获得焦点时应该有权限。确实,以下代码有效:

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" />

这什么也没做。

所以这可能不是应用级别权限的问题。


发生了什么?

如何让异步剪贴板 API 调用在 Webview 中工作?


操作系统:Android 10 Q

Webview:诉 81.0.4044.111

【问题讨论】:

  • 类似问题,也没有答案:stackoverflow.com/questions/61429649/…
  • 可能是一个错误。
  • @hereticMonkey 感谢链接,但我认为它不会改变任何东西。它指出“尝试读取或写入剪贴板数据将自动提示用户如果尚未授予权限”,这意味着除了尝试使用剪贴板之外,在 JS 中没有明确的方法来请求此权限,我相信是真的。如问题中所述,当我在 Webview 环境中执行此操作时,onPermissionRequest() 实际上从未被调用过。

标签: javascript android android-webview clipboard


【解决方案1】:

剪贴板 API 的 writeText 方法文档说,我们需要使用 Permissions API 获得 clipboard-write 权限,但 navigator.permission 在 WebView 中未定义,可能是因为他们不想将 Web 权限与 Android 操作系统权限混合。

还有另一种方法可以将文本从 Android WebView 复制到剪贴板:从 WebView JavaScript (JS) 代码调用本机 Java 方法。

在 WebView 中启用 JS:

myWebView.getSettings().setJavaScriptEnabled(true);

添加JS接口:

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");
}

【讨论】:

  • 我很惊讶Android Webview 没有实现navigator.permission。嗯,真可惜。我会暂时使用你的解决方法。谢谢。
  • 是的,这很令人惊讶,因为摄像头、麦克风等其他权限正在 webview 中通过PermissionRequest 工作。
  • @NihthiyaAlthaf 在您的网页 html/js 文件中,您要将文本复制到剪贴板。
  • @AnkitMakwana 我从网页中的 sdk 获得了复制按钮
  • 剪贴板是Android WebView中没有实现的权限之一,详见Chromium源码中的this line及其周边。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
相关资源
最近更新 更多