likebobby
likebobby

Reputation: 1379

Android WebView: Download when content-type is application/pdf and render web page if not

I have a specific scenario where I make a POST request with a unique ticket in the body to get a resulting page back.

The resulting page is either Content-Type: application/pdfor text/html. The ticket is only valid once, so the page can only be loaded once.

Problem is that Android WebView does not support rendering of pdf (as the equivalent on iOS do).

I've tried the following:

  1. Check http response headers with a primary request and then download the file with a second request if it's a pdf and open it in a PDF app (works). But for loading html pages, the second request fails, since the ticket is no longer valid.

  2. Download both the pdf and the html page and then open in pdf app/WebView locally. This works, both relative links in the web pages is broken. Is there a nice way to download them as well?

x. Is it possible to interrupt the request in the WebView to read the response headers and trigger a download if it's a pdf otherwise just continue rendering? Can't find a good answer for this.

Upvotes: 1

Views: 3020

Answers (2)

Prokash Sarkar
Prokash Sarkar

Reputation: 11873

You can use the built in method URLConnection.getContentType() for the exact purpose. Once you get the content type proceed with downloading or pass to the WebView.

Imports:

import java.net.URL;
import java.net.URLConnection;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

Here's a sample to intercept the URL before loading:

webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                String requestedUrl = request.getUrl().toString();

                boolean isDownloadableFile = false;

                try {
                    isDownloadableFile = new FetchContentTypeAsync(requestedUrl).execute().get();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // downloadable file / dont load it in webview
                if (isDownloadableFile) {
                    // download the file here
                    return false;
                } else {
                    // non downloadable file / load it in webview
                    view.loadUrl(requestedUrl);
                    return super.shouldOverrideUrlLoading(view, request);
                }
            }
        });

FetchContentTypeAsync is used for running the task in background

private static class FetchContentTypeAsync extends AsyncTask<Void, Void, Boolean> {

        private String requestedUrl;

        FetchContentTypeAsync(String requestedUrl) {
            this.requestedUrl = requestedUrl;
        }

        @Override
        protected Boolean doInBackground(Void... voids) {
            boolean isDownloadableFile = false;
            try {
                URL url = new URL(requestedUrl);
                URLConnection urlConnection = url.openConnection();
                String contentType = urlConnection.getContentType();
                isDownloadableFile = contentType.equalsIgnoreCase("application/pdf");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return isDownloadableFile;
        }
    }

To download a file check Download a file with Android, and showing the progress in a ProgressDialog

Upvotes: 4

Elkdor
Elkdor

Reputation: 121

After you set the WebViewClient it has some interfaces to intercept the requests the most widely used is shouldOverrideUrlLoading() but you can also override shouldInterceptRequest() and intercept it there.

webView.setWebViewClient(new WebViewClient() {
    @Override public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // Check the URL here - if it is a file, 
        // then initiate the download
        return false;
    }
}

Upvotes: 0

Related Questions