Android - Webview HTML 代码提取不起作用 (Javascript)
Android - Webview HTML code extraction doesn't work (Javascript)
我正在编写一个应用程序:
- 在 Webview 中加载 URL;
- 通过 javascript 代码提取 HTML;
- 在日志中显示提取的 HTML 代码。
因为我需要在不启用 Java 脚本的情况下加载页面(以避免页面的某些行为),我尝试了下面的代码:
- 我在禁用 Java 脚本的情况下在 webview 中加载页面;
- 加载页面后,我启用 Java 脚本;
- 然后,应用程序执行提取 HTML 代码所需的 Java 脚本。
不幸的是,当代码在 Android 4.0.4 上以调试模式执行时,出现错误:
01-22 22:37:56.575: E/Web Console(7605): Uncaught TypeError: Cannot call method 'processHTML' of undefined at null:1
如果我删除 myBrowserSettings.setJavaScriptEnabled(false);
声明,在 loadurl 调用之后,一切正常。
我该怎么做才能让下面的代码正常工作?
package com.stefano.formfiller;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebSettings.PluginState;
public class MainActivity extends Activity {
WebView myBrowser;
String urlToBrowse = "http://www.mywebsite.com";
String htmlCode = null;
StringBuffer buffer = new StringBuffer();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myBrowser = (WebView)findViewById(R.id.webView1);
//Browser settings
WebSettings myBrowserSettings = myBrowser.getSettings();
//Prevent cache to be used
myBrowserSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
myBrowserSettings.setAppCacheEnabled(false);
//General settings
myBrowserSettings.setJavaScriptEnabled(true);
Log.d("Stefano", "JS enabled");
//FIREFOX user agent
myBrowserSettings.setUserAgentString("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
myBrowser.setWebChromeClient(new WebChromeClient());
myBrowser.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url)
{
WebSettings myBrowserSettings = myBrowser.getSettings();
myBrowserSettings.setJavaScriptEnabled(true);
Log.d("Stefano", "JS enabled");
Log.d("Stefano", "OnPageFinished running");
} });
//Start the delayed HTML code extraction
delayedStartHtmlExtractor(16000);
Log.d("Stefano", "DelayedStart HTML Extractor launched");
//Prepare Javascript to extract the HTML code from the webview
myBrowser.addJavascriptInterface(new LoadListener(), "HTMLOUT");
myBrowser.loadUrl(urlToBrowse);
Log.d("Stefano", "Main URL requested");
myBrowserSettings.setJavaScriptEnabled(false);
Log.d("Stefano", "JS disabled");
}
//Delayed HTML extraction
public void delayedStartHtmlExtractor(final int delay){
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
@Override
public void run()
{
myBrowser.loadUrl("javascript:window.HTMLOUT.processHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
Log.d("Stefano", "HTML extraction launched");
}
}, delay);
}
//Insert the HTML code in the log information
class LoadListener{
public void processHTML(String html)
{
Log.d("Stefano", "HTML Extraction in progress...");
Log.e("HTML CODE",html);
}
}
更新:
我有一个疑问:代码在 Java 脚本启用时实例化 Java 脚本接口(通过 myBrowser.addJavascriptInterface(new LoadListener(), "HTMLOUT"););然后,我在 URL 调用后禁用 javascript,以便在页面完全加载时重新启用 Java 脚本。
可能是当我用实例化接口禁用 Java 脚本时,我 "cut-off the communication channel" 在 Javascipt 和 Java 代码之间?
当您实例化 LoadListener 对象时,请尝试以下操作:
this.new LoadListener();
首先,您应该将正确的注释 @JavascriptInterface
附加到将通过Javascript interface调用的方法;在你的情况下:
//..
@JavascriptInterface
public void processHTML(String html) {
Log.d("Stefano", "HTML Extraction in progress...");
Log.e("HTML CODE",html);
}
//..
"请注意,在加载页面之前,注入的对象不会出现在 JavaScript 中"
我想用 setJavaScriptEnabled(false)
加载页面根本不会注入任何 Javascript 对象,这就是您遇到此问题的方式。
可能的解决方法(未经测试)可能是这样的:
- 始终使用 setJavaScriptEnabled(true)
加载页面
- 加载通过http://www.google.com/gwt/n的网页(将加载无JS或Flash的页面)
- 做你的处理
在界面设置后添加myBrowser.loadData(...)
,像这样
myBrowser.addJavascriptInterface(new LoadListener(), "HTMLOUT");
myBrowser.loadData("", "text/html", null);
myBrowser.loadUrl(urlToBrowse);
此外,由于您将在 oncreate 方法结束时禁用 js,因此无需在首次亮相时启用它:)
希望对您有所帮助
我正在编写一个应用程序: - 在 Webview 中加载 URL; - 通过 javascript 代码提取 HTML; - 在日志中显示提取的 HTML 代码。
因为我需要在不启用 Java 脚本的情况下加载页面(以避免页面的某些行为),我尝试了下面的代码: - 我在禁用 Java 脚本的情况下在 webview 中加载页面; - 加载页面后,我启用 Java 脚本; - 然后,应用程序执行提取 HTML 代码所需的 Java 脚本。
不幸的是,当代码在 Android 4.0.4 上以调试模式执行时,出现错误:
01-22 22:37:56.575: E/Web Console(7605): Uncaught TypeError: Cannot call method 'processHTML' of undefined at null:1
如果我删除 myBrowserSettings.setJavaScriptEnabled(false);
声明,在 loadurl 调用之后,一切正常。
我该怎么做才能让下面的代码正常工作?
package com.stefano.formfiller;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebSettings.PluginState;
public class MainActivity extends Activity {
WebView myBrowser;
String urlToBrowse = "http://www.mywebsite.com";
String htmlCode = null;
StringBuffer buffer = new StringBuffer();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myBrowser = (WebView)findViewById(R.id.webView1);
//Browser settings
WebSettings myBrowserSettings = myBrowser.getSettings();
//Prevent cache to be used
myBrowserSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
myBrowserSettings.setAppCacheEnabled(false);
//General settings
myBrowserSettings.setJavaScriptEnabled(true);
Log.d("Stefano", "JS enabled");
//FIREFOX user agent
myBrowserSettings.setUserAgentString("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
myBrowser.setWebChromeClient(new WebChromeClient());
myBrowser.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url)
{
WebSettings myBrowserSettings = myBrowser.getSettings();
myBrowserSettings.setJavaScriptEnabled(true);
Log.d("Stefano", "JS enabled");
Log.d("Stefano", "OnPageFinished running");
} });
//Start the delayed HTML code extraction
delayedStartHtmlExtractor(16000);
Log.d("Stefano", "DelayedStart HTML Extractor launched");
//Prepare Javascript to extract the HTML code from the webview
myBrowser.addJavascriptInterface(new LoadListener(), "HTMLOUT");
myBrowser.loadUrl(urlToBrowse);
Log.d("Stefano", "Main URL requested");
myBrowserSettings.setJavaScriptEnabled(false);
Log.d("Stefano", "JS disabled");
}
//Delayed HTML extraction
public void delayedStartHtmlExtractor(final int delay){
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
@Override
public void run()
{
myBrowser.loadUrl("javascript:window.HTMLOUT.processHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
Log.d("Stefano", "HTML extraction launched");
}
}, delay);
}
//Insert the HTML code in the log information
class LoadListener{
public void processHTML(String html)
{
Log.d("Stefano", "HTML Extraction in progress...");
Log.e("HTML CODE",html);
}
}
更新: 我有一个疑问:代码在 Java 脚本启用时实例化 Java 脚本接口(通过 myBrowser.addJavascriptInterface(new LoadListener(), "HTMLOUT"););然后,我在 URL 调用后禁用 javascript,以便在页面完全加载时重新启用 Java 脚本。
可能是当我用实例化接口禁用 Java 脚本时,我 "cut-off the communication channel" 在 Javascipt 和 Java 代码之间?
当您实例化 LoadListener 对象时,请尝试以下操作:
this.new LoadListener();
首先,您应该将正确的注释 @JavascriptInterface
附加到将通过Javascript interface调用的方法;在你的情况下:
//..
@JavascriptInterface
public void processHTML(String html) {
Log.d("Stefano", "HTML Extraction in progress...");
Log.e("HTML CODE",html);
}
//..
"请注意,在加载页面之前,注入的对象不会出现在 JavaScript 中"
我想用 setJavaScriptEnabled(false)
加载页面根本不会注入任何 Javascript 对象,这就是您遇到此问题的方式。
可能的解决方法(未经测试)可能是这样的:
- 始终使用 setJavaScriptEnabled(true) 加载页面
- 加载通过http://www.google.com/gwt/n的网页(将加载无JS或Flash的页面)
- 做你的处理
在界面设置后添加myBrowser.loadData(...)
,像这样
myBrowser.addJavascriptInterface(new LoadListener(), "HTMLOUT");
myBrowser.loadData("", "text/html", null);
myBrowser.loadUrl(urlToBrowse);
此外,由于您将在 oncreate 方法结束时禁用 js,因此无需在首次亮相时启用它:)
希望对您有所帮助