Toegang tot de http-antwoordheaders in een WebView?

Is er een manier om de http-responsheaders in een activiteit te bekijken nadat een webpagina in een WebView is geladen? Het lijkt erop dat dit mogelijk zou moeten zijn, maar ik kan geen methode vinden die de headers blootlegt.


Antwoord 1, autoriteit 100%

Noch WebViewnoch WebViewClientbieden methoden om dat te doen, hoewel u kunt proberen dat handmatig te implementeren. Je kunt zoiets als dit doen:

private WebView webview;
public void onCreate(Bundle icicle){
    // bla bla bla
    // here you initialize your webview
    webview = new WebView(this);
    webview.setWebViewClient(new YourWebClient());
}
// this will be the webclient that will manage the webview
private class YourWebClient extends WebViewClient{
    // you want to catch when an URL is going to be loaded
    public boolean  shouldOverrideUrlLoading  (WebView  view, String  urlConection){
        // here you will use the url to access the headers.
        // in this case, the Content-Length one
        URL url;
        URLConnection conexion;
        try {
            url = new URL(urlConection);
            conexion = url.openConnection();
            conexion.setConnectTimeout(3000);
            conexion.connect();
            // get the size of the file which is in the header of the request
            int size = conexion.getContentLength();
        }
        // and here, if you want, you can load the page normally
        String htmlContent = "";
        HttpGet httpGet = new HttpGet(urlConection);
        // this receives the response
        HttpResponse response;
        try {
            response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == 200) {
                // la conexion fue establecida, obtener el contenido
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    InputStream inputStream = entity.getContent();
                    htmlContent = convertToString(inputStream);
                }
            }
         } catch (Exception e) {}
         webview.loadData(htmlContent, "text/html", "utf-8");
         return true;
    }
    public String convertToString(InputStream inputStream){
        StringBuffer string = new StringBuffer();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                string.append(linea + "\n");
            }
        } catch (IOException e) {}
        return string.toString();
    }
}

Ik kan het nu niet testen, maar dat is eigenlijk wat je zou kunnen doen (het is echter heel gek :).


Antwoord 2, autoriteit 14%

geïnspireerd door CristianantwoordIk moest AJAX-oproepen onderscheppen die webview aan het doen is, waarbij ik responsheaders moest onderscheppen om wat informatie te krijgen (aantal winkelwagenitems in e-commerce-app), die ik in de app moest gebruiken. Omdat de app okhttp gebruikt, heb ik dit uiteindelijk gedaan en het werkt:

       @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
            Log.i(TAG,"shouldInterceptRequest path:"+request.getUrl().getPath());
            WebResourceResponse returnResponse = null;
            if (request.getUrl().getPath().startsWith("/cart")) { // only interested in /cart requests
                returnResponse = super.shouldInterceptRequest(view, request);
                Log.i(TAG,"cart AJAX call - doing okRequest");
                Request okRequest = new Request.Builder()
                        .url(request.getUrl().toString())
                        .post(null)
                        .build();
                try {
                    Response okResponse = app.getOkHttpClient().newCall(okRequest).execute();
                    if (okResponse!=null) {
                        int statusCode = okResponse.code();
                        String encoding = "UTF-8";
                        String mimeType = "application/json";
                        String reasonPhrase = "OK";
                        Map<String,String> responseHeaders = new HashMap<String,String>();
                        if (okResponse.headers()!=null) {
                            if (okResponse.headers().size()>0) {
                                for (int i = 0; i < okResponse.headers().size(); i++) {
                                    String key = okResponse.headers().name(i);
                                    String value = okResponse.headers().value(i);
                                    responseHeaders.put(key, value);
                                    if (key.toLowerCase().contains("x-cart-itemcount")) {
                                        Log.i(TAG,"setting cart item count");
                                        app.setCartItemsCount(Integer.parseInt(value));
                                    }
                                }
                            }
                        }
                        InputStream data = new ByteArrayInputStream(okResponse.body().string().getBytes(StandardCharsets.UTF_8));
                        Log.i(TAG, "okResponse code:" + okResponse.code());
                        returnResponse = new WebResourceResponse(mimeType,encoding,statusCode,reasonPhrase,responseHeaders,data);
                    } else {
                        Log.w(TAG,"okResponse fail");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return returnResponse;
        }

Ik hoop dat dit voor anderen nuttig kan zijn en als iemand suggesties heeft voor verbetering, zou ik u dankbaar zijn. Helaas is het alleen compatibel met LOLLIPOP en hoger. Vanaf deze versie kun je headers openen/retourneren met WebResourceRequest, wat nodig was voor mijn geval.


Antwoord 3, autoriteit 2%

Je zou al je headers moeten kunnen beheren door loadUrl over te slaan en je eigen loadPage te schrijven met Java’s HttpURLConnection. Bekijk vervolgens de headers, doe je ding en gebruik de loadData van de webview om het antwoord weer te geven.


Antwoord 4, autoriteit 2%

Er is een alternatieve oplossing als u ten minste Kit-Kat target, ook al worden de kopteksten niet weergegeven in Activiteit, maar eerder in Chrome. U kunt deze korte handleidingvolgen over hoe u op afstand debuggen van webviews.

De 2 belangrijkste punten zijn, ten eerste, om WebView-foutopsporing in uw app in te schakelen

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    WebView.setWebContentsDebuggingEnabled(true);
}

En open vervolgens chrome://inspectop een Chrome-tabblad op een computer. Zodra u uw telefoon via USB op de computer aansluit, ziet u de WebView van uw app in de lijst met foutopsporingsapparaten


Antwoord 5

u kunt OkHttp gebruiken:

private fun handleRequestViaOkHttp(url: String) {
            var httpClient = OkHttpClient()
            thread {
                try {
                    val request = Request.Builder().url(url).build()
                    print("Request: $request")
                    val response = httpClient.newCall(request).execute()
                    println("Response: " + response.headers().toString())
                } catch (e: Exception) {}
            }
        }

je zou het binnen deze methode moeten aanroepen:

override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
                handleRequestViaOkHttp(webViewUrl.value.toString())
                return super.shouldInterceptRequest(view, request)
        }

Other episodes