Wywołanie API schowka wywołuje NotAllowedError bez wywoływania onPermissionRequest ()

12

Mam prostą stronę z przyciskiem, który po naciśnięciu używa Async Clipboard API do pisania w schowku.

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

Działa to zarówno w Chrome, jak i Firefox, na komputerach i urządzeniach mobilnych. Jednak w Android Webview wyświetla następujący błąd:

NotAllowError: Write permission denied.


Uznałem, że muszę przeskoczyć, WebChromeClient.onPermissionRequest()aby udzielić pozwolenia, ale dziwnie onPermissionRequest()nie wydaje się, że został wywołany, a ten sam błąd jest nadal zgłaszany.

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

Nadal pojawia się ten sam błąd:

NotAllowError: Write permission denied.

Również Logcat nic nie zarejestrował.


Podejrzewałem, że może moja aplikacja na Androida wymaga dodatkowych uprawnień, aby uzyskać dostęp do schowka, ale zgodnie z https://developer.android.com/about/versions/10/privacy/changes#clipboard-data moja aplikacja powinna mieć uprawnienia, gdy jest skupiona . Rzeczywiście działa następujący kod:

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

Oświadczyłem również, że AndroidManifest.xmlw przypadku, gdy działanie w celu uzyskania pozwolenia wymaga pozwolenia:

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

To nic nie zrobiło.

Prawdopodobnie nie jest to problem z uprawnieniami na poziomie aplikacji.


Co się dzieje?

Jak mogę uzyskać wywołania interfejsu API schowka Async do pracy w Widoku sieci?


System operacyjny: Android 10 Q

Webview: v. 81.0.4044.111

cyqsimon
źródło
Podobne pytanie, również bez odpowiedzi: stackoverflow.com/questions/61429649/…
BDL
Może to być błąd.
Travis J
@hereticMonkey thx za link, ale nie sądzę, żeby coś to zmieniło. Stwierdza, że ​​„próba odczytu lub zapisu danych ze schowka automatycznie poprosi użytkownika o zgodę, jeśli jeszcze nie została udzielona”, co oznacza, że ​​nie ma wyraźnego sposobu zażądania tego uprawnienia w JS poza próbą korzystania ze schowka, co ja wierzyć jest prawdą. Jak wspomniano w pytaniu, kiedy robię to w środowisku Webview, onPermissionRequest()w rzeczywistości nigdy nie został wywołany.
cyqsimon

Odpowiedzi:

4

Dokumentacja writeTextmetody API schowka mówi, że musimy uzyskać clipboard-writepozwolenie za pomocą interfejsu API uprawnień. ale navigator.permissionjest niezdefiniowany w widoku internetowym, być może dlatego, że nie chcą mieszać uprawnień internetowych z uprawnieniami systemu Android.

Jest jeszcze jeden sposób, w jaki możemy skopiować tekst do schowka z Androida webview (przez wywołanie natywnej metody Java z kodu javascript webview).

Przede wszystkim włącz javascript na webview:

myWebView.getSettings().setJavaScriptEnabled(true);

Następnie dodaj interfejs javascript:

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

Utwórz metodę, która skopiuje tekst do schowka za pomocą 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);
    }
}

Teraz możesz po prostu wywołać powyższą metodę z testClipboardmetody:

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

  NativeAndroid.copyToClipboard("Clipboard API Test");
}
Ankit Makwana
źródło
Dziwię się, że Android Webviewto nie wdrożyło navigator.permission. Cóż, szkoda. Na razie skorzystam z twojego obejścia. Dziękuję Ci.
cyqsimon
1
Tak, to zaskakujące, ponieważ inne uprawnienia, takie jak kamera, mikrofon, działają przez przeglądarkę PermissionRequestinternetową.
Ankit Makwana