当前位置: 首页 > 知识库问答 >
问题:

剪贴板API调用在不调用onPermissionRequest()的情况下抛出NotAllowedError

狄峰
2023-03-14

我有一个带有按钮的简单页面,当按下时,使用异步剪贴板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:拒绝写入权限。

我想我需要重写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:拒绝写入权限。

Logcat也没有记录任何信息。

我怀疑可能我的Android应用程序需要额外的权限才能访问剪贴板,但根据https://developer.android.com/about/versions/10/privacy/changes#clipboard-数据,我的应用程序应该有权限时,它有重点。实际上,以下代码有效:

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

网络视图:v.81.0.4044.111

共有1个答案

昌琪
2023-03-14

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

还有一种方法可以将文本从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");
}
 类似资料:
  • 问题内容: 我正在尝试制作一个小的桌面应用程序,该应用程序应显示剪贴板的内容(如果它是字符串)。我已经完成了一个构造函数,并且构造函数运行良好,现在,我只想在将文本复制到OS的剪贴板中时调用类似的方法。我对此很陌生,因此不胜感激!告诉我应该以某种方式使用中断… 问题答案: 您可以调用Clipboard.addFlavorListener来侦听来自操作系统的剪贴板更新: 一些注意事项: 要启动您的应

  • 问题内容: 我正试图从这样打电话: 该代码可以正常编译,但是会失败。我不知道为什么我无法得到。有人可以帮我吗? 问题答案: 是输入输出参数。进行呼叫时,必须将其设置为缓冲区()的大小。它的类型也是,所以在Go中使用。Windows 类型是指向的指针(具有)。参见来源。 还返回3个值: 存储返回并打印。完成此操作后,您会更早发现错误: 印刷品: 这意味着更多的数据比什么适合入缓冲区您传递可用- 或者

  • 在系统剪贴板上执行复制和剪贴操作 进程: 主进程, 渲染进程​ 复制字符串例子: 1 const {clipboard} = require('electron') 2 clipboard.writeText('Example String') Copied! 在X Window系统上,还有一个选择剪贴板。要操作它,你需要传递selection到每个方法: 1 const {clipboard}

  • 在系统剪贴板上执行复制和粘贴操作。 进程: Main, Renderer 下面的示例演示如何将字符串写入剪贴板: const { clipboard } = require('electron') clipboard.writeText('Example String') On Linux, there is also a selection clipboard. To manipulate it

  • 我正在尝试编写一个函数,它将“解包装”,返回包含的值。该函数假设optional已被使用,因此不对执行任何运行时检查。 下面是我对此的实现,以及编译后的程序集以供参考。关于编译器输出,我有几个问题: > 为什么这会导致分支代码?允许对包含的值进行未经检查的访问,因此我不希望看到任何分支。 为什么调用的析构函数?请注意程序集中对的调用。如何在不调用析构函数的情况下将包含的值移出可选值? Godbol