1,WebViewClient与WebChromeClient的区别
2,WebView是如何做到让java和javaScript进行互调的。
public class WebViewDemo extends Activity {
private WebView mWebView;
private Handler mHandler = new Handler();
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.webviewdemo);
mWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new Object() {
public void clickOnAndroid() {
mHandler.post(new Runnable() {
public void run() {
mWebView.loadUrl("javascript:wave()");
}
});
}
}, "demo");
mWebView.loadUrl("file:///android_asset/demo.html");
}
}
这里的重点是addJavascriptInterface(Object obj,String interfaceName)方法,该方法将一个java对象绑定到一个javas
<html>
<script language="javascript">
function wave() {
document.getElementById("droid").src="android_waving.png";
}
</script>
<body>
<a onClick="window.demo.clickOnAndroid()">
<img id="droid" src="android_normal.png"/><br>
Click me!
</a>
</body>
</html>
这样在javas
这里还有几个知识点:
1)为了让WebView从apk文件中加载assets,Android SDK提供了一个schema,前缀为"file:///android_asset/"。WebView遇到这样的schema,就去当前包中的assets目录中找内容。如上面的"file:///android_asset/demo.html"
2)addJavascriptInterface方法中要绑定的Java对象及方法要运行另外的线程中,不能运行在构造他的线程中,这也是使用Handler的目的
3,腾讯微博认证获取验证码即采用了上述的方法。(干你妹的腾讯,看人家新浪搞得多简洁!)
if (!intent.equals(null))
{
Bundle bundle = intent.getExtras();
if (bundle != null)
{
if (bundle.containsKey("urlStr"))
{
String urlStr = bundle.getString("urlStr");
WebSettings webSettings = webView.getSettings();
// 支持JavScript
webSettings.setJavaScriptEnabled(true);
webSettings.setSaveFormData(true);
webSettings.setSavePassword(true);
webSettings.setSupportZoom(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setCacheMode( WebSettings.LOAD_NO_CACHE );
webView.setOnTouchListener(new OnTouchListener()
{
public boolean onTouch(View v, MotionEvent event) {
webView.requestFocus();
return false;
}
});
webView.loadUrl(urlStr);
webView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress)
{
setTitle("加载中,请稍后..." + progress + "%");
setProgress(progress * 100);
if (progress == 100) setTitle(R.string.app_name);
}
});
}
}
}
//绑定java对象到JavaScript中,这样就能在JavaScript中调用java对象,实现通信。
//这种方法第一个参数就是java对象,第二个参数表示java对象的别名,在JavaScript中使用
webView.addJavascriptInterface(new JavaScriptInterface(), "Methods");
WebViewClient client = new WebViewClient()
{
/**
* 回调方法,当页面加载完毕后执行
*/
public void onPageFinished(WebView view, String url)
{
//执行获取授权码的JavaScript
view.loadUrl("javascript:window.Methods.getHTML('<head>'+document.getElementsByTagName('body')[0].innerHTML+'</head>');");
super.onPageFinished(view, url);
}
};
webView.setWebViewClient(client);
}
class JavaScriptInterface
{
public void getHTML(String html)
{
String verifier = getVerifier(html);
if (!StringUtils.isBlank(verifier))
{
Intent intent = new Intent();
intent.setClass(TencentWebViewActivity.this, MainActivity.class);
intent.putExtra("verifier", verifier);
setResult(RESULT_CODE, intent);
finish();
}
}
/**
* 根据正则表达式获取验证码
* @param html
* @return
*/
public String getVerifier(String html)
{
String ret = "";
String regEx = "授权码:[0-9]{6}"; //匹配模式
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(html);
boolean result = m.find();
if (result)
{
//获取验证码
ret = m.group(0).substring(4);
}
return ret;
}
}
给子ViewGroup设定参数时,参数类型应该是父ViewGroup的参数类型,切记!