Sur Android, j'ai un WebView
qui affiche une page.
Comment obtenir la source de la page sans demander à nouveau la page?
Il semble qu'il WebView
devrait avoir une sorte de getPageSource()
méthode qui renvoie une chaîne, mais hélas ce n'est pas le cas.
Si j'active JavaScript, quel est le JavaScript approprié à mettre dans cet appel pour obtenir le contenu?
webview.loadUrl("javascript:(function() { " +
"document.getElementsByTagName('body')[0].style.color = 'red'; " +
"})()");
android
android-webview
Gregm
la source
la source
Réponses:
Je sais que c'est une réponse tardive, mais j'ai trouvé cette question parce que j'avais le même problème. Je pense avoir trouvé la réponse dans ce post sur lexandera.com. Le code ci-dessous est essentiellement un copier-coller du site. Cela 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");
la source
onPageFinished()
son exécution.browser.loadUrl
enonPageFinished
feraonPageFinished
à nouveau appelé. Vous voudrez peut-être vérifier s'il s'agit du premier appelonPageFinished
ou non avant d'appelerbrowser.loadUrl
.String html = new Scanner(new DefaultHttpClient().execute(new HttpGet("www.the url")).getEntity().getContent(), "UTF-8").useDelimiter("\\A").next();
(abrégé pour tenir dans un commentaire :-))Par numéro 12987 , la réponse de Blundell plante (au moins sur ma machine virtuelle 2.3). Au lieu de cela, j'intercepte 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");
la source
C'est une réponse basée sur jluckyiv , mais je pense qu'il est préférable et plus simple de changer Javascript comme suit.
browser.loadUrl("javascript:HTMLOUT.processHTML(document.documentElement.outerHTML);");
la source
Avez-vous envisagé de récupérer le code HTML séparément, puis de le charger dans une vue 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; }
la source
J'ai réussi à faire fonctionner cela en utilisant le code de la réponse de @ jluckyiv mais j'ai dû ajouter l'annotation @JavascriptInterface à la méthode processHTML dans MyJavaScriptInterface.
class MyJavaScriptInterface { @SuppressWarnings("unused") @JavascriptInterface public void processHTML(String html) { // process the html as needed by the app } }
la source
Vous devez également annoter la méthode avec @JavascriptInterface si votre targetSdkVersion est> = 17 - car il y a de nouvelles exigences de sécurité dans le SDK 17, c'est-à-dire que toutes les méthodes javascript doivent être annotées avec @JavascriptInterface. Sinon, vous verrez une erreur comme: Uncaught TypeError: Object [object Object] n'a pas de méthode 'processHTML' à null: 1
la source
Si vous travaillez sur kitkat et au-dessus, vous pouvez utiliser les outils de débogage à distance Chrome pour trouver toutes les demandes et réponses entrant et sortant de votre vue Web ainsi que le code source html de la page consultée.
https://developer.chrome.com/devtools/docs/remote-debugging
la source