2010-06-28 8 views
32

Gibt es eine Möglichkeit, die HTTP-Antwortheader in einer Aktivität anzuzeigen, nachdem eine Webseite in ein WebView geladen wurde? Scheint so, dass das möglich sein sollte, aber ich kann keine Methoden finden, die die Header verfügbar machen.Zugriff auf die HTTP-Response-Header in einem WebView?

+1

Nein. Was genau möchten Sie tun? Wenn Sie sich die Anfrage/Antwort ansehen möchten, müssen Sie die Anfrage mit HttpClient stellen. –

+0

Ich versuche, einen HTTP-Antwortheader von der in meinem WebView geladenen Seite zu lesen. Ich hatte das Gefühl, ich müsste HttpClient benutzen und dann die Antwort zurück an die WebView senden. Mehr Arbeit als erforderlich sein sollte, um eine Header-Antwort zu lesen ... – tronman

Antwort

32

Weder WebView noch WebViewClient bieten Methoden, das zu tun, obwohl Sie versuchen können, das manuell zu implementieren. Sie können etwas tun:

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(); 
    } 
} 

Ich kann es jetzt nicht testen, aber das ist im Grunde, was Sie tun können (es ist sehr verrückt aber :).

+2

Das einzige Problem mit dieser Methode ist, dass sumoUrideUrlLoading() nicht aufgerufen wird, wenn das WebView-Dienstprogramm loadUrl() aufgerufen wird. Das ist ein großes Problem für mich. – tronman

+1

Nun ... in diesem Fall müssen Sie nur die 'loadUrl()' Methode überschreiben;) – Cristian

+0

Sie haben Recht. Das ist verrückt! –

1

Sie sollten in der Lage sein, alle Ihre Header zu steuern, indem Sie loadUrl überspringen und Ihre eigene loadPage mit Java's HttpURLConnection schreiben. Dann sehen Sie sich die Header an, machen Sie Ihre Sache und verwenden Sie die loadData der Webansicht, um die Antwort anzuzeigen.

+1

Würden Sie bitte Ihre Antwort ausarbeiten? Seit 4 Jahren hoffe ich, dass es einen besseren Weg gibt. –

+2

@MW Offensichtlich nicht. Vielleicht in den nächsten 4 Jahren – Arthur

2

inspiriert von Cristiananswer Ich musste AJAX-Aufrufe abfangen, die webview macht, wo ich Antwortheader abfangen musste, um einige Informationen zu erhalten (Warenkorb Artikelanzahl in E-Commerce-App), die ich in der Anwendung nutzen musste. Da die App verwendet okhttp Ich habe dies zu tun ende und es funktioniert:

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

Ich hoffe, dass dies für andere hilfreich sein kann, und wenn jemand einen Verbesserungsvorschlag hat, würde ich dankbar. Leider ist es nur mit LOLLIPOP und höher kompatibel, da ab dieser Version auf Header zugegriffen werden kann, die WebResourceRequest verwenden, die für meinen Fall benötigt wurde.

+0

Gibt es keine Alternative zu WebResourceRequest für ältere Android-Versionen? Ist es nicht möglich, Ajax-Anfragen in älteren Android-Versionen zu erfassen? – Sohaib

+0

alternativ können Sie http://developer.android.com/guide/webapps/webview.html#BindingJavaScript verwenden, wenn Sie ändern können, was Website/Webapp macht – ursimon

+0

Ich versuche, dies auch auf älteren Versionen von Android zu tun. Irgendeine Möglichkeit, dies zu tun? – clu

-2

Da die akzeptierte Antwort nur mit HttpGet arbeiten, hier ist ein Trick Thet zur Zeit verwende ich (zu dieser Zeit zu arbeiten, wie es scheint)

In onPageFinished Handler, wenn ein Fehler ist, der Titel Die Seite wird wie "ERROR_NUM - ERROR_DESCRIPTION" aussehen, wie "500 - Interner Serverfehler", also muss ich nur einen Titel aus webview in die Funktion holen und dann den Titel überprüfen.

view.getTitle()

+0

Das hat nichts mit dem Abrufen der Antwortheader zu tun. –

Verwandte Themen