web-dev-qa-db-de.com

HTTP-Anforderungen von WebView abfangen und überschreiben

Ich habe eine WebView in meiner Anwendung, in der eine Site geöffnet ist (immer dieselbe, es ist meine eigene Seite). Die Site verfügt über einen JS-Code, der einige Bilder vom Remote-Host lädt.

Ich möchte Anforderungen an solche Bilder abfangen (nach URL-Muster) und meinen eigenen Inhalt (d. H. Ein anderes Bild) zurückgeben oder die Anforderung je nach interner Anwendungslogik unberührt lassen.

Ist das möglich?

EDIT : Der aktuelle Status der Frage ...

WebView kann ein WebViewClient setzen (wie von Axarydax angegeben). WebViewClient hat zwei nützliche Methoden

  • shouldOverrideUrlLoading
  • onLoadResource

shouldOverrideUrlLoading kann das Laden von URLs abfangen, wenn das Laden durch Seiteninteraktion ausgelöst wird (d. h. wenn auf einen Link auf einer Seite geklickt wird, löst WebView.loadURL ("") diese Methode nicht aus). Das Laden von URLs kann auch abgebrochen werden, indem false zurückgegeben wird. Dieser Ansatz ist nicht verwendbar, da das Laden von Seitenressourcen nicht abgefangen werden kann (und Bilder, die ich abfangen muss, eine solche Seitenressource sind).

onLoadResource wird jedes Mal ausgelöst, wenn Seitenressourcen (und Bilder! thx bis jessyjones) geladen werden, aber es gibt keine Möglichkeit, dies abzubrechen. Das macht diese Methode auch für meine Aufgabe nicht geeignet.

60
Olegas

Es sieht so aus, als ob API Level 11 Unterstützung für Ihre Anforderungen bietet. Siehe WebViewClient.shouldInterceptRequest() .

48
dkneller

Versuchen Sie dies, ich habe es in einer persönlichen Wiki-ähnlichen App verwendet:

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

Nach meinem Kenntnisstand wird shouldOverrideUrlLoading nicht für Bilder, sondern für Hyperlinks aufgerufen ... Ich denke, das ist die geeignete Methode

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

Diese Methode wird für jede Ressource (Bild, Stylesheet, Skript) aufgerufen, die von der Webansicht geladen wird. Da es sich jedoch um eine leere Ressource handelt, habe ich keine Möglichkeit gefunden, diese URL zu ändern und zu ersetzen, sodass eine lokale Ressource geladen wird.

10
jessyjones

Hier ist meine Lösung, die ich für meine App verwende.

Ich habe mehrere Asset-Ordner mit CSS/JS/IMG und Font-Dateien.

Die Anwendung ruft alle Dateinamen ab und prüft, ob eine Datei mit diesem Namen angefordert wird. Wenn ja, wird es aus dem Asset-Ordner geladen.

//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;
        }
9
EscapeNetscape

Sie erwähnen die API-Version nicht, aber seit API 11 gibt es die Methode WebViewClient.shouldInterceptRequest

Vielleicht könnte das helfen?

4
user484261

Eine ultimative Lösung wäre, einen einfachen HTTP-Server einzubetten, der Ihren "geheimen" Port im Loopback überwacht. Dann können Sie die übereinstimmende Bild-Quell-URL durch etwas wie http: // localhost: 123 /.../ mypic.jpg ersetzen

3

Dies kann helfen:

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