Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Window.Print Doesn't Work in Android WebView (API 23) but Works in default Browser and Chrome

The following example code from here works fine in both the default browser "Internet" and "Chrome" browser on Galaxy Tab S2.

<!DOCTYPE html>
<html>
<body>

<p>Click the button to print the current page.</p>

<button onclick="myFunction()">Print this page</button>

<script>
function myFunction() {
    window.print();
}
</script>

</body>
</html>

However when hosted inside a WebView, nothing happens when clicking "Print this page"

My view XML:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.company.MainActivity"
    tools:showIn="@layout/activity_main">

    <WebView
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

MainActivity.Java has the following:

@Override
protected void onCreate(Bundle savedInstanceState) {
    WebViewClient mWebClient = new WebViewClient(){
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url)
        {
            view.loadUrl(url);
            return true;
        }
    };
    WebView myWebView = (WebView) findViewById(R.id.webview);
    myWebView.setWebViewClient(mWebClient);
    WebSettings webSettings = myWebView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webSettings.setDomStorageEnabled(true);
    webSettings.setGeolocationEnabled(true);
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    myWebView.loadUrl("https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_print");
}

The WebView developer documentation here explicitly calls out:

You cannot use JavaScript in a HTML document to trigger printing.

How can I host a webpage and allow JavaScript printing to work.

Alternatives I've thought of but haven't found a way to implement:

  • Intercept button clicks, if Print button is been clicked trigger my own printing code
  • Replace the "Print" button HTML on the fly with some other code that would allow me to handle it in my application

So far to workaround this limitation I've added "Print" button to my application and run my own printing code. It works fine, but is confusing user experience as "Print" button in web page does nothing.

like image 309
Malcolm McCaffery Avatar asked Aug 22 '17 06:08

Malcolm McCaffery


People also ask

Does Android WebView use Chromium?

Android WebView is one of the six supported platforms for Chromium.

Is Android WebView same as Chrome?

No, Chrome for Android is separate from WebView. They're both based on the same code, including a common JavaScript engine and rendering engine.

How do I enable JavaScript on Android WebView?

Enable JavaScript JavaScript is disabled in a WebView by default. You can enable it through the WebSettings attached to your WebView . You can retrieve WebSettings with getSettings() , then enable JavaScript with setJavaScriptEnabled() . WebView myWebView = (WebView) findViewById(R.

What can I use instead of WebView?

Alternatives to WebView If you want to send users to a mobile site, build a progressive web app (PWA). If you want to display third-party web content, send an intent to installed web browsers. If you want to avoid leaving your app to open the browser, or if you want to customize the browser's UI, use Custom Tabs.


1 Answers

Maybe this will answer to your question: https://bugs.chromium.org/p/chromium/issues/detail?id=322303

This is the answer from Android WebView team:

Hi,

We (Android WebView team) are planning to port this API to Android Q (lower versions are possible too via support lib, but TBD). We want to understand the possible use cases of it.

The API will be a blocking callback as we want to freeze the DOM/layout tree for printing rendering, this is the same behavior with Chrome.

Once we have the callback, we can imagine to get a |PrintDocumentAdapter| from WebView#getPrintDocumentAdapter() in the callback, and apps can either 1) use the |PrintDocumentAdapter| with |PrintManager| to let user choose printing settings or 2) use it to generate a PDF file directly. We probably want to unblock when PrintDocumentAdapter#onFinish() get called.

This callback will only benefit the case that when loading contents you have no control to WebView, the app still needs to support printing feature. Otherwise the app can use |PrintDocumentAdapter| directly.

We also want to know if you think window.print() from an iframe (to print only content in that iframe) is important for you or not. Supporting of this is tentative as there is no obvious way for getPrintDocumentAdapter() to know the current window.print() is from main frame or an iframe.

Questions, thoughts? Please give your feedback, thanks!

like image 119
MrVasilev Avatar answered Oct 04 '22 10:10

MrVasilev