Interceptar y anular las solicitudes HTTP de WebView
Tengo un WebView en mi aplicación en la que se abre algún sitio (siempre lo mismo, es mi propia página). El sitio tiene algún código JS que carga algunas imágenes del host remoto.
Quiero interceptar peticiones a dichas imágenes (por patrón de URL) y devolver mi propio contenido (es decir, otra imagen), o dejar la solicitud sin tocar dependiendo de la lógica interna de la aplicación.
- Cómo obtener URL de enlace en Android WebView con HitTestResult para una imagen vinculada (y no la URL de imagen) con Longclick
- Deje de cargar en webViewClient
- Cómo establecer un título diferente para el cuadro de diálogo de alerta cuando se carga la página WebView?
- ShouldOverrideUrlLoading no funciona / captura los clics del enlace mientras la página se está cargando
- ¿WebViewClient y WebChromeClient se excluyen mutuamente?
¿Es posible hacer eso?
EDIT : El estado actual de la pregunta …
WebView
tiene la capacidad de establecer un WebViewClient
(como se ha señalado por Axarydax). WebViewClient
tiene dos métodos útiles
-
shouldOverrideUrlLoading
-
onLoadResource
shouldOverrideUrlLoading
es capaz de interceptar cualquier carga url, si la carga se dispara por la interacción de la página (es decir, el enlace en una página se hace clic, WebView.loadURL ("") no está desencadenando este método). También puede cancelar la carga de URL devolviendo false. Este enfoque no es utilizable, porque 'no es capaz de interceptar la carga de los recursos de la página (y las imágenes, lo que necesito para interceptar, es un recurso de esa página).
onLoadResource
está activando cada vez que el recurso de la página (y las imágenes! Thx a jessyjones) se están cargando, pero no hay manera de cancelar eso. Eso hace que este método no sea adecuado para mi tarea también.
- Android 4.4 dando ERR_CACHE_MISS error en onReceivedError para WebView volver
- Deshabilitar Android WebView / WebViewClient Iniciado favicon.ico Solicitar
- ¿Qué se considera onPageFinished en el WebViewClient para Android?
- Sube la foto de la cámara y el archivador de archivos desde el campo INPUT de la vista web
- WebView de Android ignorando target = "_ blank" cuando se agrega WebViewClient
- Habilitación de JavaScript general en WebViewClient
- WebView loadUrl sólo funciona una vez
- Android: comprueba si la solicitud es GET o POST
Parece que el nivel 11 de la API tiene soporte para lo que necesita. Vea WebViewClient.shouldInterceptRequest()
.
Pruebe esto, lo he usado en una aplicación personal similar a wiki:
webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("foo://")) { // magic return true; } return false; } });
Por lo que sé, shouldOverrideUrlLoading no se llama para las imágenes, sino más bien para los hipervínculos … Creo que el método apropiado es
@Override public void onLoadResource(WebView view, String url)
Este método se llama para cada recurso (imagen, styleesheet, script) que se carga por la webview, pero ya que es un vacío, no he encontrado una manera de cambiar esa url y reemplazarla para que cargue un recurso local …
Esta es mi solución que utilizo para mi aplicación.
Tengo varias carpeta de activos con css / js / img anf archivos de fuentes.
La aplicación obtiene todos los nombres de archivo y busca si se solicita un archivo con este nombre. En caso afirmativo, se carga desde la carpeta de activos.
//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; }
Usted no menciona la versión de la API, pero desde la API 11 está el método WebViewClient.shouldInterceptRequest
Tal vez esto podría ayudar?
Una solución definitiva sería incrustar un servidor HTTP simple escuchando en su puerto 'secreto' en loopback. A continuación, puede sustituir la imagen coincidente src URL con algo como http: // localhost: 123 /…/ mypic.jpg
Esto puede ayudar:
@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; }
- Android Studio Gradle BuildTools Revisión
- Cómo obtener la ubicación actual latitud y longitud en android