Clipboard API call throws NotAllowedError without invoking onPermissionRequest()

喜欢而已 提交于 2020-05-14 17:31:23

问题


I have a simple page with a button, that when pressed, uses the Async Clipboard API to write to the clipboard.

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

This works on both Chrome and Firefox, desktop and mobile. However on Android Webview it throws the following error:

NotAllowError: Write permission denied.


I figured I need to override WebChromeClient.onPermissionRequest() to grant the permission, but strangely onPermissionRequest() does not seem to have been invoked, and the same error is still thrown.

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

I still get the same error:

NotAllowError: Write permission denied.

Also Logcat logged nothing.


I suspected maybe my Android App requires additional permissions to access the clipboard, but according to https://developer.android.com/about/versions/10/privacy/changes#clipboard-data, my App should have permission when it has focus. Indeed, the following code works:

ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("MyLbl", "I have permission");
clipboard.setPrimaryClip(clip);

I also declared the following in AndroidManifest.xml in case the action of requesting permission requires permission:

<uses-permission android:name="android.webkit.PermissionRequest" />

This did nothing.

So it is probably not an issue with App level permission.


What is happening?

How can I get Async Clipboard API calls to work in Webview?


OS: Android 10 Q

Webview: v. 81.0.4044.111


回答1:


Clipboard API's writeText method docs says, we need to obtain clipboard-write permission using Permissions api. but navigator.permission is undefined in webview, maybe because they don't want to mix web permissions with android os permissions.

There is one more way by which we can copy text to clipboard from android webview (by calling native java method from webview javascript code).

First of all enable javascript on webview:

myWebView.getSettings().setJavaScriptEnabled(true);

Then add javascript interface:

myWebView.addJavascriptInterface(new WebAppInterface(), "NativeAndroid");

Create method which will copy the text to clipboard using 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);
    }
}

Now you can just call above method from testClipboard method:

function testClipboard() {
  navigator.clipboard.writeText("Clipboard API Test").then(
    v => alert("Success"),
    e => alert("Fail\n" + e));

  NativeAndroid.copyToClipboard("Clipboard API Test");
}


来源:https://stackoverflow.com/questions/61243646/clipboard-api-call-throws-notallowederror-without-invoking-onpermissionrequest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!