一、基础
现在Android应用 层开发的方向有两种:客户端开发和HTML5移动端开发!
所谓的HTML5端就是:HTML5 + CSS + JS来构建 一个网页版的应用,而这中间的媒介就是这个WebView。
Web和网页端可以通过JS来进行交互,比如, 网页读取手机联系人,调用手机相关的API等!
- WebChromeClient:辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等,如onJsAlert处理Js中的Alert对话框;
- WebViewClient:辅助WebView处理各种通知与请求事件,如onPageFinished通知主程序,网页加载完毕 ;
- WebSettings:WebView相关配置的设置,比如setJavaScriptEnabled()设置是否允许JS脚本执行; demo: java改写js里的alert方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wView = (WebView) findViewById(R.id.wView);
//获得WebSetting对象,支持js脚本,可访问文件,支持缩放,以及编码方式
WebSettings webSettings = wView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setDefaultTextEncodingName("UTF-8");
//设置WebChromeClient,处理网页中的各种js事件
wView.setWebChromeClient(new MyWebChromeClient());
wView.setWebViewClient(new MyWebViewClient());
wView.loadUrl("file:///android_asset/demo2.html");
}
//自定义回调
class MyWebViewClient extends BridgeWebViewClient {
public MyWebViewClient(BridgeWebView webView) {
super(webView);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
//DialogShow.showRoundProcessDialog();
}
@Override
public void onPageFinished(WebView view, String url) {
DialogShow.closeDialog();
addImageClickListner();
llContent.setVisibility(View.VISIBLE);
if (ScrollY != 0) {
webView.scrollTo(ScrollX, ScrollY);
}
//这个是一定要加上那个的,配合scrollView和WebView的height=wrap_content属性使用
int w = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
//重新测量
webView.measure(w, h);
super.onPageFinished(view, url);
}
}
//这里需要自定义一个类实现WebChromeClient类,并重写三种不同对话框的处理方法
//分别重写onJsAlert,onJsConfirm,onJsPrompt方法
class MyWebChromeClient extends WebChromeClient {
@Override
public boolean onJsAlert(WebView view, String url, String message,
final JsResult result) {
//创建一个Builder来显示网页中的对话框
new Builder(MainActivity.this).setTitle("Alert对话框").setMessage(message)
.setPositiveButton("确定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
}).setCancelable(false).show();
return true;
}
}
java调用js
- 通过
WebView的loadUrl() - 通过
WebView的evaluateJavascript()
- webView.loadUrl
webView.loadUrl("javascript:methodName(parameterValues)");
String call = "javascript:alertMessage(\"" + "content" + "\")";
webView.loadUrl(call);
- evaluateJavascript 从Android 4.4开始,Android中的WebView不再是基于WebKit的,而是开始基于Chromium
webView.evaluateJavascript("getYourCar()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("findCar",s);
}
});
js调用java
- 通过
WebView的addJavascriptInterface()进行对象映射 - 通过
WebViewClient的shouldOverrideUrlLoading ()方法回调拦截 url - 通过
WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt()消息
addJavascriptInterface 2个步骤:
1,webview.getSettings().setJavaScriptEnabled(true);
2,webview.addJavascriptInterface(object,"name");
wView = (WebView) findViewById(R.id.wView);
wView.loadUrl("file:///android_asset/demo1.html");
WebSettings webSettings = wView.getSettings();
//①设置WebView允许调用js
webSettings.setJavaScriptEnabled(true);
webSettings.setDefaultTextEncodingName("UTF-8");
//②将object对象暴露给Js,调用addjavascriptInterface
wView.addJavascriptInterface(new MyObject(MainActivity.this), "myObj");
更多见: www.runoob.com/w3cnote/and…
二、Android webkit
- skia : android于chrome 共同使用的图形库,图形文字绘制
- chromium-net:chrome源码中抽离出的网络库
- wtf:web template framework公共基础库
- v8:js引擎,js脚本执行
- webcore:html/css解析、排版及js的dom绑定
- webkit:封装c++层,提供与java交互的接口
- framework: 对外提供java的webkit api;
webkit线程结构
- messageQueue:主线程入口一个循环loop,waitForMessage,没有消息队列则挂起,有消息则循环处理消息;
- task传递:异步回调js的接口,调用callOnMainThread将消息放入主线程的执行队列;
资源加载
- 主资源:载入frame的html文档。产生: java层的loadUrl和页面链接发出的请求;
- 派生资源:js、css、image等
- page cache:页面缓存。浏览器页面dom树、render树临时保存,加速页面返回;
- memory cache:内存缓存。浏览器内部的缓存机制,相同的url直接返回;
- disk cache:磁盘缓存。资源加载与服务器进行交互
webkit
- webview:ui线程、主线程
- webviewcore:工作线程
- callbackProxy:为工作线程向ui线程发起事件消息回调
- broserFrame:webcode中frame对象上层封装
网页加载
- ui线程 setWebViewClient设置回调,然后webview.loadUrl加载网页;
- loadUrl方法发送消息给webviewcore对象
- webviewcore调用broserFrame,broserFrame调用jni函数nativeLoadUrl在c++层加载网页
- c++ webframe 调用webcore加载网页 工作线程触发回调
- webframe 收到调用
- 通过jni调用broserFrame
- broserFrame 的函数触发 callbackProxy 的onPageStarted回调
- callbackProxy生成消息,发送给handleMassage消息处理函数
- webviewClient回调被触发
js扩展接口
- v8 binding:webcore中的dom、css等操作接口通过
web IDL暴露给v8,js就可以操作dom了 - extension
v8 api见
推荐阅读: 《JSBridge 的原理》
欢迎关注我的前端自检清单,我和你一起成长