Comment puis-je obtenir le contenu de la page Web à partir d'un WebView?
-
24-09-2019 - |
Question
Sur Android, j'ai une WebView
qui affiche une page.
Comment puis-je obtenir la source de la page sans demander à nouveau la page?
Il semble WebView
devrait avoir une sorte de méthode getPageSource()
qui retourne une chaîne, mais hélas il ne fonctionne pas.
Si j'activer JavaScript, ce qui est le JavaScript approprié pour mettre dans cet appel pour obtenir le contenu?
webview.loadUrl("javascript:(function() { " +
"document.getElementsByTagName('body')[0].style.color = 'red'; " +
"})()");
La solution
Je sais que c'est une réponse tardive, mais je trouve cette question parce que j'ai eu le même problème. Je pense avoir trouvé la réponse dans ce poste sur lexandera. com. Le code ci-dessous est en fait un coupe-coller à partir du site. Il semble faire l'affaire.
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");
Autres conseils
Par 12987 , les accidents de réponse de Blundell (au moins sur ma machine virtuelle 2.3) . Au lieu de cela, j'intercepter un appel à console.log avec un préfixe spécial:
// 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");
Ceci est une réponse basée sur jluckyiv, mais je pense qu'il est mieux et plus simple de changer Javascript comme suit.
browser.loadUrl("javascript:HTMLOUT.processHTML(document.documentElement.outerHTML);");
Avez-vous envisagé aller chercher le code HTML séparément, puis de le charger dans un WebView?
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;
}
Je réussi à obtenir ce travail en utilisant le code de la réponse de @ jluckyiv mais je devais ajouter une annotation de @JavascriptInterface à la méthode processHTML dans le MyJavaScriptInterface.
class MyJavaScriptInterface
{
@SuppressWarnings("unused")
@JavascriptInterface
public void processHTML(String html)
{
// process the html as needed by the app
}
}
Vous devez également annoter la méthode avec @JavascriptInterface si votre targetSdkVersion est> = 17 - parce qu'il ya de nouvelles exigences en matière de sécurité dans SDK 17, à savoir toutes les javascript méthodes doivent être annotés avec @JavascriptInterface. Sinon, vous verrez comme erreur: Uncaught TypeError: Object [object Object] n'a pas de méthode 'processHTML' à null: 1
Si vous travaillez sur KitKat et au-dessus, vous pouvez utiliser les outils de débogage à distance chrome pour trouver toutes les demandes et les réponses qui entrent et sortent de votre WebView et aussi le code source HTML de la page affichée.