¿Cómo consigo los contenidos de la página web desde un WebView?
-
24-09-2019 - |
Pregunta
En Android, tengo una WebView
que está mostrando una página.
¿Cómo consigo la fuente de la página sin solicitar de nuevo la página?
Parece WebView
debe tener algún tipo de método getPageSource()
que devuelve una cadena, pero por desgracia no es así.
Si habilito JavaScript, lo que es el código JavaScript apropiada para poner en esta convocatoria para obtener el contenido?
webview.loadUrl("javascript:(function() { " +
"document.getElementsByTagName('body')[0].style.color = 'red'; " +
"})()");
Solución
Yo sé que esto es una respuesta tardía, pero me encontré con esta pregunta porque tenía el mismo problema. Creo que he encontrado la respuesta en este post en lexandera. com. El código siguiente es básicamente un cortar y pegar desde el sitio. Parece que hacer el truco.
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");
Otros consejos
tema 12987 , la respuesta de Blundell bloquea (al menos en mi máquina virtual 2.3) . En su lugar, interceptar una llamada a CONSOLE.LOG con un prefijo especial:
// 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");
Esta es una respuesta basada en de jluckyiv , pero creo que es mejor y más fácil de cambiar Javascript como sigue.
browser.loadUrl("javascript:HTMLOUT.processHTML(document.documentElement.outerHTML);");
¿Ha pensado en ir a buscar el código HTML por separado, y luego cargarlo en una vista 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;
}
He conseguido este trabajo utilizando el código de respuesta de @ jluckyiv pero tenía que añadir en la anotación @JavascriptInterface al método processHTML en el MyJavaScriptInterface.
class MyJavaScriptInterface
{
@SuppressWarnings("unused")
@JavascriptInterface
public void processHTML(String html)
{
// process the html as needed by the app
}
}
También es necesario anotar el método con @JavascriptInterface si su targetSdkVersion es> = 17 - porque hay nuevos requisitos de seguridad en SDK de 17, es decir, todos los métodos JavaScript debe ser anotado con @JavascriptInterface. De lo contrario, verá error como: no detectada TypeError: Object [object Object] tiene ningún método 'processHTML' en nulo: 1
Si usted está trabajando en KitKat y por encima, se puede utilizar el cromo depuración remota herramientas para encontrar todas las peticiones y las respuestas que entran y salen de su vista web y también el código fuente HTML de la página vista.