У меня в приложении есть WebView, в котором открыт некоторый сайт (всегда один и тот же, это моя собственная страница). Сайт содержит некоторый JS-код, который загружает некоторые изображения с удаленного хоста.
Я хочу перехватывать запросы к таким изображениям (по шаблону URL) и возвращать собственное содержимое (т.е. другое изображение), либо оставлять запрос нетронутым в зависимости от внутренней логики приложения.
Возможно ли это сделать?
EDIT: Текущее состояние вопроса...
У WebView
есть возможность установить WebViewClient
(как отметил Axarydax). У WebViewClient
есть два полезных метода
shouldOverrideUrlLoading
onLoadResource
shouldOverrideUrlLoading
способен перехватить загрузку любого url, если загрузка вызвана взаимодействием со страницей (т.е. на странице щелкнули по ссылке, а WebView.loadURL("") не вызывает этот метод). Он также способен отменить загрузку URL, вернув false. Этот подход не подходит, так как не позволяет перехватить загрузку ресурсов страницы (а изображения, которые мне нужно перехватить, являются именно таким ресурсом страницы).
onLoadResource
срабатывает каждый раз, когда загружается ресурс страницы (и изображения! спасибо jessyjones), но отменить это никак нельзя. Поэтому данный метод также не подходит для моей задачи.
Попробуйте это, я использовал это в личном приложении, похожем на вики:
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("foo://")) {
// magic
return true;
}
return false;
}
});
Похоже, что API уровня 11 поддерживает то, что вам нужно. Смотрите WebViewClient.shouldInterceptRequest()
.
Насколько я знаю, shouldOverrideUrlLoading вызывается не для изображений, а для гиперссылок... Я думаю, что подходящим методом будет
@Override public void onLoadResource(WebView view, String url)
.
Этот метод вызывается для каждого ресурса (изображения, таблицы стилей, скрипта), который загружается веб-вью, но поскольку это void, я не нашел способа изменить этот url и заменить его так, чтобы он загружал локальный ресурс ...
Вот мое решение я использую для моего приложения.
У меня есть несколько папок активов с CSS / шрифты в JS / ИМГ файлов 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;
}
Вы Don'т учтите, версия API, но с API 11, там'ы метод WebViewClient.shouldInterceptRequest
Может быть, это поможет?
Окончательное решение будет для размещения простой HTTP-сервер прослушивающего ваш 'секрет' порт замыкания на себя. Затем вы можете заменить совпавшие изображения в src Url-адрес что-то вроде http://localhost:123/.../mypic.jpg
Это может поможет:
@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;
}