Перехват и переопределение HTTP-запросов от WebView - PullRequest
57 голосов
/ 24 января 2011

У меня в приложении есть WebView, в котором открыт какой-то сайт (всегда один и тот же, это моя собственная страница). На сайте есть некоторый код JS, который загружает некоторые изображения с удаленного хоста.

Я хочу перехватывать запросы к таким изображениям (по шаблону URL) и возвращать свой собственный контент (то есть другое изображение) или оставить запрос без изменений в зависимости от внутренней логики приложения.

Возможно ли это сделать?

РЕДАКТИРОВАТЬ : текущее состояние вопроса ...

WebView имеет возможность установить WebViewClient (как отмечено Axarydax). WebViewClient есть два полезных метода

  • shouldOverrideUrlLoading
  • onLoadResource

shouldOverrideUrlLoading может перехватить любую загрузку URL, если загрузка инициируется взаимодействием страницы (т. Е. Нажата ссылка на странице, WebView.loadURL ("") не вызывает этот метод). Он также может отменить загрузку URL, вернув false. Этот подход непригоден для использования, потому что он не может перехватить загрузку ресурсов страницы (а изображения, которые мне нужно перехватить, являются таким ресурсом страницы).

onLoadResource запускается каждый раз, когда загружается ресурс страницы (и изображения! Thx to jessyjones), но отменить это невозможно. Это также делает этот метод не подходящим для моей задачи.

Ответы [ 7 ]

68 голосов
/ 26 января 2011

Попробуйте, я использовал это в личном вики-подобном приложении:

webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("foo://")) {
            // magic
            return true;
        }
        return false;
    }
});
48 голосов
/ 03 марта 2011

Похоже, API уровня 11 поддерживает то, что вам нужно.См. WebViewClient.shouldInterceptRequest().

10 голосов
/ 26 января 2011

Насколько я знаю, shouldOverrideUrlLoading вызывается не для изображений, а для гиперссылок ... Я думаю, что соответствующий метод -

@Override public void onLoadResource(WebView view, String url)

Этот метод вызывается для каждого ресурса (изображения, таблицы стилей, скрипта), который загружен веб-представлением, но, поскольку он является пустым, я не нашел способа изменить этот URL-адрес и заменить его, чтобы он загружал локальный ресурс ...

9 голосов
/ 27 января 2016

Вот мое решение, которое я использую для своего приложения.

У меня есть несколько папок с файлами шрифтов css / js / img и anf.

Приложение получает все имена файлов и проверяет, запрошен ли файл с этим именем. Если да, он загружает его из папки активов.

//get list of files of specific asset folder
        private ArrayList listAssetFiles(String path) {

            List myArrayList = new ArrayList();
            String [] list;
            try {
                list = getAssets().list(path);
                for(String f1 : list){
                    myArrayList.add(f1);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return (ArrayList) myArrayList;
        }

        //get mime type by url
        public String getMimeType(String url) {
            String type = null;
            String extension = MimeTypeMap.getFileExtensionFromUrl(url);
            if (extension != null) {
                if (extension.equals("js")) {
                    return "text/javascript";
                }
                else if (extension.equals("woff")) {
                    return "application/font-woff";
                }
                else if (extension.equals("woff2")) {
                    return "application/font-woff2";
                }
                else if (extension.equals("ttf")) {
                    return "application/x-font-ttf";
                }
                else if (extension.equals("eot")) {
                    return "application/vnd.ms-fontobject";
                }
                else if (extension.equals("svg")) {
                    return "image/svg+xml";
                }
                type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
            }
            return type;
        }

        //return webresourceresponse
        public WebResourceResponse loadFilesFromAssetFolder (String folder, String url) {
            List myArrayList = listAssetFiles(folder);
            for (Object str : myArrayList) {
                if (url.contains((CharSequence) str)) {
                    try {
                        Log.i(TAG2, "File:" + str);
                        Log.i(TAG2, "MIME:" + getMimeType(url));
                        return new WebResourceResponse(getMimeType(url), "UTF-8", getAssets().open(String.valueOf(folder+"/" + str)));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return null;
        }

        //@TargetApi(Build.VERSION_CODES.LOLLIPOP)
        @SuppressLint("NewApi")
        @Override
        public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
            //Log.i(TAG2, "SHOULD OVERRIDE INIT");
            //String url = webResourceRequest.getUrl().toString();
            String extension = MimeTypeMap.getFileExtensionFromUrl(url);
            //I have some folders for files with the same extension
            if (extension.equals("css") || extension.equals("js") || extension.equals("img")) {
                return loadFilesFromAssetFolder(extension, url);
            }
            //more possible extensions for font folder
            if (extension.equals("woff") || extension.equals("woff2") || extension.equals("ttf") || extension.equals("svg") || extension.equals("eot")) {
                return loadFilesFromAssetFolder("font", url);
            }

            return null;
        }
4 голосов
/ 08 августа 2012

Вы не упоминаете версию API, но начиная с API 11 есть метод WebViewClient.shouldInterceptRequest

Может быть, это может помочь?

3 голосов
/ 01 октября 2011

Конечным решением было бы встроить простой http-сервер, прослушивающий ваш «секретный» порт в режиме loopback. Затем вы можете заменить URL-адрес сопоставленного изображения на что-то вроде http://localhost:123/.../mypic.jpg

2 голосов
/ 25 марта 2016

Это может помочь:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
    String url = request.getUrl().toString();
    WebResourceResponse response = super.shouldInterceptRequest(view, request);
    // load native js
    if (url != null && url.contains(INJECTION_TOKEN/* scheme define */)) {

        response = new WebResourceResponse(
                "text/javascript",
                "utf-8",
                loadJsInputStream(url, JsCache.getJsFilePath(path) /* InputStream */));
    }
    return response;
}
...