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.

¿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.

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; } 
  • Cómo buscar Android ViewFlipper Ejemplo con varias WebViews
  • Habilitación de protocolos SSL específicos con Android WebViewClient
  • Android: EventHub.removeMessages (int what = 107) no es compatible antes de que se configure WebViewCore
  • ShouldOverrideUrlLoading en WebView para Android no se está ejecutando
  • SaveState de Webview no maneja WebViewClient personalizado
  • Android - Utilice OkHttp con Webview
  • Cómo obtener la página en blanco en Android WebViewClient
  • Proguard warning biblioteca clase android.webkit.WebView depende de la clase del programa android.webkit.WebViewClien
  • Android: abra los vínculos _blank de destino en WebView con un navegador externo
  • ¿Qué hace stopLoading () realmente hacer?
  • Android WebView para Facebook como botón
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.