Android WebView: загрузка, когда типом содержимого является приложение/pdf, и отображение веб-страницы, если нет

У меня есть конкретный сценарий, когда я делаю запрос POST с уникальным билетом в теле, чтобы вернуть результирующую страницу.

В результате получается страница либо Content-Type: application/pdf, либо text/html. Билет действителен только один раз, поэтому страницу можно загрузить только один раз.

Проблема в том, что Android WebView не поддерживает отрисовку pdf (как это делается в iOS).

Я пробовал следующее:

  1. Проверьте заголовки ответа http с помощью основного запроса, а затем загрузите файл со вторым запросом, если это PDF-файл, и откройте его в приложении PDF (работает). А вот для загрузки html страниц второй запрос не проходит, так как тикет уже недействителен.

  2. Загрузите как pdf, так и html-страницу, а затем откройте ее в приложении pdf/WebView локально. Это работает, обе относительные ссылки на веб-страницах не работают. Есть ли хороший способ скачать их?

Икс. Можно ли прервать запрос в WebView, чтобы прочитать заголовки ответа и запустить загрузку, если это PDF-файл, иначе просто продолжите рендеринг? Не могу найти хороший ответ для этого.


person likebobby    schedule 24.03.2015    source источник


Ответы (2)


Вы можете использовать встроенный метод URLConnection.getContentType() для конкретной цели. Как только вы получите тип контента, продолжите загрузку или перейдите к файлу WebView.

Импорт:

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

Вот пример перехвата URL-адреса перед загрузкой:

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 используется для запуска задачи в фоновом режиме.

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

Чтобы загрузить файл, проверьте Загрузить файл с Android и показ прогресса в диалоговом окне ProgressDialog

person Prokash Sarkar    schedule 05.11.2019
comment
Он написан на Котлине. Вам нужна Java-версия кода? - person Prokash Sarkar; 05.11.2019
comment
О, хорошо, я вижу. Да, пожалуйста, я использую Java. - person Black; 05.11.2019
comment
Было бы лучше, если бы вы предоставили оба решения на случай, если кто-то еще использует Kotlin. - person Black; 05.11.2019
comment
Спасибо, я добавил код для загрузки файла. Единственная проблема в том, что файл не открывается в приложении... он загружается молча, а браузер открывается и показывает наш сайт. - person Black; 06.11.2019
comment
WebView по умолчанию не поддерживает файлы PDF. Вам нужно открыть его с помощью сторонней библиотеки или использовать документы Google, чтобы загрузить его через mWebView.loadUrl(docs.google.com/gview?embedded=true&url=+ webUrl); - person Prokash Sarkar; 06.11.2019
comment
хорошо, но я предполагаю, что это также означает, что Google будет получать копию каждого документа, загруженного из приложения, что не отвечает нашим интересам безопасности данных. Но это другая проблема... спасибо! - person Black; 06.11.2019
comment
Не за что. Google использует веб-представление для отображения PDF-файла и не хранит ваш файл постоянно. Однако в этом случае открытие документа, связанного с безопасностью, может быть не идеальным решением. - person Prokash Sarkar; 06.11.2019

После того, как вы установите WebViewClient, у него есть несколько интерфейсов для перехвата запросов, наиболее широко используемым является shouldOverrideUrlLoading(), но вы также можете переопределить shouldInterceptRequest() и перехватить его там.

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;
    }
}
person Elkdor    schedule 30.09.2015
comment
а что, если в URL-адресе нет расширения файла? - person Black; 31.10.2019