剪贴板 API 调用抛出 NotAllowedError 而不调用 onPermissionRequest()

cyq*_*mon 67 javascript clipboard android android-webview

我有一个带有按钮的简单页面,按下该按钮时,使用异步剪贴板 API 写入剪贴板。

<body>
  <button type="button" onclick="testClipboard();">
    Test Clipboard
  </button>
</body>
Run Code Online (Sandbox Code Playgroud)
function testClipboard() {
  navigator.clipboard.writeText("Clipboard API Test").then(
    v => alert("Success"),
    e => alert("Fail\n" + e));
}
Run Code Online (Sandbox Code Playgroud)

这适用于 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());
}
Run Code Online (Sandbox Code Playgroud)

我仍然收到相同的错误:

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);
Run Code Online (Sandbox Code Playgroud)

我还声明了以下内容,AndroidManifest.xml以防请求许可的操作需要许可:

<uses-permission android:name="android.webkit.PermissionRequest" />
Run Code Online (Sandbox Code Playgroud)

这没有任何作用。

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


怎么了?

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


操作系统:Android 10 Q

网络视图:诉 81.0.4044.111

Ank*_*ana 52

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

我们还可以通过另一种方式将文本从 Android WebView 复制到剪贴板:通过从 WebView JavaScript (JS) 代码调用原生 Java 方法。

在 WebView 中启用 JS:

myWebView.getSettings().setJavaScriptEnabled(true);
Run Code Online (Sandbox Code Playgroud)

添加JS接口:

myWebView.addJavascriptInterface(new WebAppInterface(), "NativeAndroid");
Run Code Online (Sandbox Code Playgroud)

创建一个使用以下方法将文本复制到剪贴板的方法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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用testClipboard以下方法调用上述方法:

function testClipboard() {
  navigator.clipboard.writeText("Clipboard API Test").then(
    v => alert("Success"),
    e => alert("Fail\n" + e));
    
  NativeAndroid.copyToClipboard("Clipboard API Test");
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,这很令人惊讶,因为其他权限(例如相机、麦克风)是通过 webview 中的“PermissionRequest”来工作的。 (6认同)
  • 我很惊讶“Android Webview”没有实现“navigator.permission”。嗯,这太可惜了。我暂时使用您的解决方法。谢谢。 (2认同)
  • 对于仅更改客户端代码有什么解决方案吗? (2认同)