Der API-Aufruf der Zwischenablage löst NotAllowedError aus, ohne onPermissionRequest () aufzurufen.

10

Ich habe eine einfache Seite mit einer Schaltfläche, die beim Drücken die Async-Zwischenablage-API verwendet, um in die Zwischenablage zu schreiben.

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

Dies funktioniert sowohl auf Chrome als auch auf Firefox, Desktop und Mobile. In Android Webview wird jedoch der folgende Fehler ausgegeben:

NotAllowError: Write permission denied.


Ich dachte, ich muss überschreiben WebChromeClient.onPermissionRequest(), um die Erlaubnis zu erteilen, onPermissionRequest()scheint aber seltsamerweise nicht aufgerufen worden zu sein, und der gleiche Fehler wird immer noch ausgegeben.

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

Ich bekomme immer noch den gleichen Fehler:

NotAllowError: Write permission denied.

Auch Logcat hat nichts protokolliert.


Ich vermutete, dass meine Android-App möglicherweise zusätzliche Berechtigungen für den Zugriff auf die Zwischenablage benötigt, aber laut https://developer.android.com/about/versions/10/privacy/changes#clipboard-data sollte meine App über Berechtigungen verfügen, wenn sie den Fokus hat . In der Tat funktioniert der folgende Code:

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

Ich habe auch Folgendes erklärt, AndroidManifest.xmlfalls die Aktion zum Anfordern einer Erlaubnis eine Erlaubnis erfordert:

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

Das hat nichts getan.

Es ist also wahrscheinlich kein Problem mit der Berechtigung auf App-Ebene.


Was ist los?

Wie kann ich Async Clipboard API-Aufrufe in Webview zum Laufen bringen?


Betriebssystem: Android 10 Q.

Webview: v. 81.0.4044.111

Cyqsimon
quelle
Ähnliche Frage, auch keine Antwort: stackoverflow.com/questions/61429649/…
BDL
Könnte ein Fehler sein.
Travis J
@hereticMonkey Danke für den Link, aber ich denke, es ändert nichts. Es heißt, "der Versuch, Daten aus der Zwischenablage zu lesen oder zu schreiben, fordert den Benutzer automatisch zur Erlaubnis auf, wenn diese noch nicht erteilt wurde", was bedeutet, dass es keine explizite Möglichkeit gibt, diese Erlaubnis in JS anzufordern, außer nur zu versuchen, die Zwischenablage zu verwenden, die ich glauben ist wahr Wie in der Frage erwähnt, wurde, wenn ich das in einer Webview-Umgebung mache, onPermissionRequest()tatsächlich nie aufgerufen.
Cyqsimon

Antworten:

2

In den writeTextMethodendokumenten der Zwischenablage-API heißt es, dass wir die clipboard-writeBerechtigung mithilfe der Berechtigungs-API erhalten müssen. ist aber navigator.permissionin der Webansicht undefiniert, vielleicht weil sie keine Webberechtigungen mit Android OS-Berechtigungen mischen wollen.

Es gibt noch eine weitere Möglichkeit, Text aus Android Webview in die Zwischenablage zu kopieren (indem wir die native Java-Methode aus Webview-Javascript-Code aufrufen).

Aktivieren Sie zunächst Javascript in der Webansicht:

myWebView.getSettings().setJavaScriptEnabled(true);

Fügen Sie dann die Javascript-Oberfläche hinzu:

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

Erstellen Sie eine Methode, mit der der Text mit in die Zwischenablage kopiert wird 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);
    }
}

Jetzt können Sie einfach die obige Methode von der testClipboardMethode aufrufen :

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

  NativeAndroid.copyToClipboard("Clipboard API Test");
}
Ankit Makwana
quelle