Подтвердить что ты не робот

Перехват и переопределение HTTP-запросов из WebView

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

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

Можно ли это сделать?

EDIT: текущее состояние вопроса...

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

  • shouldOverrideUrlLoading
  • onLoadResource

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

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

4b9b3361

Ответ 2

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

webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("foo://")) {
            // magic
            return true;
        }
        return false;
    }
});

Ответ 3

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

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

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

Ответ 4

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

У меня есть папка с файлами 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;
        }

Ответ 5

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

Возможно, это может помочь?

Ответ 6

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

Ответ 7

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

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