2010-03-04 7 views
71

Su Android, ho un WebView che sta visualizzando una pagina.Come si ottiene il contenuto della pagina Web da una WebView?

Come ottengo l'origine della pagina senza richiedere nuovamente la pagina?

Sembra che WebView dovrebbe avere una sorta di metodo getPageSource() che restituisce una stringa, ma purtroppo non è così.

Se abilito JavaScript, qual è il codice JavaScript appropriato da inserire in questa chiamata per ottenere i contenuti?

webview.loadUrl("javascript:(function() { " + 
    "document.getElementsByTagName('body')[0].style.color = 'red'; " + 
    "})()"); 
+0

uso di script jQuery e l'interfaccia js per ottenere contenuti HTML da WebView window.interface.processHTML ($ (\ "corpo \") html().); – DroidBot

+0

http://stackoverflow.com/questions/8200945/how-to-get-html-content-from-a-webview?rq=1 – trante

+0

Puoi ovviamente ottenere la risposta in HTML usando le richieste HTTP, ma se qualche pagina richiede che i dati del post siano caricati (come ad esempio le credenziali dell'utente ecc.), questo approccio semplicemente fallisce. Penso che sia così che dovrebbe essere perché se potessi farlo, probabilmente puoi creare la tua app Android per qualsiasi sito web e questo farebbe schifo! –

risposta

134

So che questa è una risposta tardiva, ma ho trovato questa domanda perché ho avuto lo stesso problema. Penso di aver trovato la risposta in this post su lexandera.com. Il seguente codice è fondamentalmente un taglia-e-incolla dal sito. Sembra fare il trucco.

final Context myApp = this; 

/* An instance of this class will be registered as a JavaScript interface */ 
class MyJavaScriptInterface 
{ 
    @JavascriptInterface 
    @SuppressWarnings("unused") 
    public void processHTML(String html) 
    { 
     // process the html as needed by the app 
    } 
} 

final WebView browser = (WebView)findViewById(R.id.browser); 
/* JavaScript must be enabled if you want it to work, obviously */ 
browser.getSettings().setJavaScriptEnabled(true); 

/* Register a new JavaScript interface called HTMLOUT */ 
browser.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT"); 

/* WebViewClient must be set BEFORE calling loadUrl! */ 
browser.setWebViewClient(new WebViewClient() { 
    @Override 
    public void onPageFinished(WebView view, String url) 
    { 
     /* This call inject JavaScript into the page which just finished loading. */ 
     browser.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');"); 
    } 
}); 

/* load a web page */ 
browser.loadUrl("http://lexandera.com/files/jsexamples/gethtml.html"); 
+4

Attenzione che questo potrebbe non essere il grezzo HTML della pagina; il contenuto della pagina potrebbe essere cambiato dinamicamente tramite JavaScript prima che fosse eseguito 'onPageFinished()'. –

+1

È grandioso, ma chiamare il metodo 'browser.loadUrl' in' onPageFinished' causerà la chiamata di 'onPageFinished'. Potresti voler verificare se è la prima chiamata di 'onPageFinished' o meno prima di chiamare' browser.loadUrl'. –

+0

Grazie @Blundell Ha funzionato per me. Mi piacerebbe sapere come potrebbe essere ** implementato come servizio **. Poiché è un servizio senza un layout e una webview per archiviare i risultati. C'è un modo per mettere i dati in qualche altro oggetto diverso dal webView in modo che possiamo mettere il javascript per ottenere il codice html risultante? – Totalys

31

Per issue 12987, la risposta di Blundell si blocca (almeno sulla mia macchina virtuale 2.3). Invece, ho intercettare una chiamata a console.log con un prefisso speciale:

// intercept calls to console.log 
web.setWebChromeClient(new WebChromeClient() { 
    public boolean onConsoleMessage(ConsoleMessage cmsg) 
    { 
     // check secret prefix 
     if (cmsg.message().startsWith("MAGIC")) 
     { 
      String msg = cmsg.message().substring(5); // strip off prefix 

      /* process HTML */ 

      return true; 
     } 

     return false; 
    } 
}); 

// inject the JavaScript on page load 
web.setWebViewClient(new WebViewClient() { 
    public void onPageFinished(WebView view, String address) 
    { 
     // have the page spill its guts, with a secret prefix 
     view.loadUrl("javascript:console.log('MAGIC'+document.getElementsByTagName('html')[0].innerHTML);"); 
    } 
}); 

web.loadUrl("http://www.google.com"); 
+1

Thx, questo funziona su 2.3.6 – Snicolas

17

Questa è una risposta basata su jluckyiv's, ma penso che sia migliore e più semplice per cambiare Javascript come segue.

browser.loadUrl("javascript:HTMLOUT.processHTML(document.documentElement.outerHTML);"); 
+0

Hai salvato il mio lavoro !! :) – gior91

6

Avete preso in considerazione il recupero dell'HTML separatamente e il caricamento in una visualizzazione Web?

String fetchContent(WebView view, String url) throws IOException { 
    HttpClient httpClient = new DefaultHttpClient(); 
    HttpGet get = new HttpGet(url); 
    HttpResponse response = httpClient.execute(get); 
    StatusLine statusLine = response.getStatusLine(); 
    int statusCode = statusLine.getStatusCode(); 
    HttpEntity entity = response.getEntity(); 
    String html = EntityUtils.toString(entity); // assume html for simplicity 
    view.loadDataWithBaseURL(url, html, "text/html", "utf-8", url); // todo: get mime, charset from entity 
    if (statusCode != 200) { 
     // handle fail 
    } 
    return html; 
} 
+1

Questo non porterà i cookie. –

+0

questo approccio attiva la finestra di dialogo CAPTCHA – Hector

4

sono riuscito a ottenere questo lavoro utilizzando il codice da @ di jluckyiv risposta, ma ho dovuto aggiungere in @JavascriptInterface annotazioni al metodo processHTML nel MyJavaScriptInterface.

class MyJavaScriptInterface 
{ 
    @SuppressWarnings("unused") 
    @JavascriptInterface 
    public void processHTML(String html) 
    { 
     // process the html as needed by the app 
    } 
} 
0

È inoltre necessario annotare il metodo con @JavascriptInterface se il targetSdkVersion è> = 17 - perché c'è nuovi requisiti di sicurezza in SDK 17, vale a dire tutti i javascript metodi devono essere annotati con @JavascriptInterface. In caso contrario, si vedrà di errore del tipo: TypeError Uncaught: Object [object Object] non ha un metodo 'processHTML' a nulla: 1

Problemi correlati