- 我們先來了解一下WebView
- 1 添加權(quán)限:AndroidManifest.xml中設(shè)置權(quán)限"android.permission.INTERNET",否則會出Web page not available錯誤第晰。
- 2 在要Activity中生成一個WebView組件:WebView webView = new WebView(this);或者可以在activity的layout文件里添加webview控件
- 3 設(shè)置WebView基本信息:
mWebView = (WebView) findViewById(R.id.wb);
mWebView.getSettings().setJavaScriptEnabled(true);//支持javascript
mWebView.requestFocus();//觸摸焦點起作用mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);//取消滾動條
mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);//設(shè)置允許js彈出alert對話框
//load本地
mWebView.loadUrl("file:///android_asset/hellotest.html");
//load在線
//mWebView.loadUrl("http://www.google.com");
//js訪問android羡亩,定義接口
mWebView.addJavascriptInterface(new JsInteration(), "control");
//設(shè)置了Alert才會彈出供填,重新onJsAlert()方法return true可以自定義處理信息
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
//return super.onJsAlert(view, url, message, result);
Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
return true;
}});
- 4 設(shè)置WevView要顯示的網(wǎng)頁:互聯(lián)網(wǎng)用:webView.loadUrl("http://www.google.com"); 本地文件用:webView.loadUrl("file:///android_asset/XX.html"); 本地文件存放在:assets文件中**
- 5 如果希望點擊鏈接由自己處理南吮,而不是新開Android的系統(tǒng)browser中響應(yīng)該鏈接。給WebView添加一個事件監(jiān)聽對象(WebViewClient)并重寫其中的一些方法: shouldOverrideUrlLoading:對網(wǎng)頁中超鏈接按鈕的響應(yīng)仍翰。當按下某個連接時WebViewClient會調(diào)用這個方法蒂窒,并傳遞參數(shù)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
view.loadUrl("");
return true;
}
- 6 處理https請求
webView默認是不處理https請求的棠众,頁面顯示空白,需要進行如下設(shè)置:
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
super.onReceivedSslError(view, handler, error);
handler.proceed(); // 表示等待證書響應(yīng)
// handler.cancel(); //表示掛起連接粪般,為默認方式
// handler.handleMessage(null); //可做其他處理
1拼余,接收到Http請求的事件onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)
2,載入頁面完成的事件public void onPageFinished(WebView view, String url){ }
同樣道理亩歹,我們知道一個頁面載入完成姿搜,于是我們可以關(guān)閉loading條,切換程序動作捆憎。
3舅柜,載入頁面開始的事件public void onPageStarted(WebView view, String url, Bitmap favicon) { }
這個事件就是開始載入頁面調(diào)用的,通常我們可以在這設(shè)定一個loading的頁面躲惰,告訴用戶程序在等待網(wǎng)絡(luò)響應(yīng)致份。 通過這幾個事件,我們可以很輕松的控制程序操作础拨,一邊用著瀏覽器顯示內(nèi)容氮块,一邊監(jiān)控著用戶操作實現(xiàn)我們需要的各種顯示方式,同時可以防止用戶產(chǎn)生誤操作诡宗。
- 如果用webview點鏈接看了很多頁以后滔蝉,如果不做任何處理,點擊系統(tǒng)“Back”鍵塔沃,整個瀏覽器會調(diào)用finish()而結(jié)束自身蝠引,如果希望瀏覽的網(wǎng)頁回退而不是退出瀏覽器,需要在當前Activity中處理并消費掉該Back事件。 覆蓋Activity類的onKeyDown(int keyCoder,KeyEvent event)方法螃概。
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK &&IdWebView.canGoBack()){
IdWebView.goBack(); //返回前一個頁面
return true;
}
return super.onKeyDown(keyCode, event);
}
二. webview與js的交互(相互調(diào)用參數(shù)矫夯、傳值)
<!DOCTYPE html><html><head> <meta charset="utf-8">
<title>jaydenxiao遇上了webview</title>
<script>
function sayHello() {
alert("我是無參無返回toast")
}
function alertMessage(message) {
alert(message)
}
function toastMessage(message) {
window.control.toastMessage(message)
}
function sumToJava(number1, number2){
window.control.onSumResult(number1 + number2)
}
function sumToJava2(number1, number2) {
return number1 + number2;
}
</script>
</head><body>
<button type="button" id="button" onclick="toastMessage('js調(diào)用了android方法')">js訪問android中方法</button>
</body>
</html>
調(diào)用示例
js調(diào)用java
調(diào)用格式為window.jsInterfaceName.methodName(parameterValues)
此例中我們使用的是control作為注入接口名稱
function toastMessage(message){
window.control.toastMessage(message)
}
function sumToJava(number1 ,number2){
window.control.onSumResult(number1 +number2)
}
Java調(diào)用JS
webview調(diào)用js的基本格式為
webview.loadUrl("javascript:methodName(paraameterValues)")
- 1 android調(diào)用js無參無返回值函數(shù)
final String call = "javacript:sayHello()";
mWebView.post(new Runnable(){
public void run(){
mWebView.loadurl(call);
}
});
- 2.android調(diào)用js有參無返回值函數(shù)
final String call = "javascript:alertMessage(\""+"我是android傳過來的內(nèi)容,hey,man"+"\")"
mWebView.post(new Runnable(){
public void run(){
mWebView.loadUrl(call);
}
})
-3.android調(diào)用js有參有返回值函數(shù)((4.4以上)
Android 4.4以上使用evaluateJavascript即可吊洼。這里展示一個簡單的交互示例 具有返回值的js方法
js代碼如下:
function sumToJava2(number1, number2) {
return number1 + number2;
}
android代碼如下:
@TargetApi(Build.VERSION_CODES.KITKAT)
public void Android2JsHaveParmHaveResult2(View view) {
mWebView.evaluateJavascript("sumToJava2(3,4)", new ValueCallback<String>() {
@Override
public void onReceiveValue(String Str) {
Toast.makeText(getApplicationContext(), "我是android調(diào)用js方法(4.4后)训貌,入?yún)⑹?和4,js返回結(jié)果是" + Str, Toast.LENGTH_LONG).show();
}
});}
最后冒窍,我們講一下我們的webview的內(nèi)存泄露問題
public void releaseAllWebViewCallback() {
if (android.os.Build.VERSION.SDK_INT < 16) {
try {
Field field = WebView.class.getDeclaredField("mWebViewCore");
field = field.getType().getDeclaredField("mBrowserFrame");
field = field.getType().getDeclaredField("sConfigCallback");
field.setAccessible(true);
field.set(null, null);
} catch (NoSuchFieldException e) {
if (BuildConfig.DEBUG) {
e.printStackTrace();
}
} catch (IllegalAccessException e) {
if (BuildConfig.DEBUG) {
e.printStackTrace();
}
}
} else {
try {
Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback");
if (sConfigCallback != null) {
sConfigCallback.setAccessible(true);
sConfigCallback.set(null, null);
}
} catch (NoSuchFieldException e) {
if (BuildConfig.DEBUG) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
if (BuildConfig.DEBUG) {
e.printStackTrace();
}
} catch (IllegalAccessException e) {
if (BuildConfig.DEBUG) {
e.printStackTrace();
}
}
}
}
在webview的 destroy方法里 調(diào)用這個方法就行了递沪。
public class WithPhotoWebActivity extends AppCompatActivity{
private ProgressBar pg;
private WebView mWebView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_with_photo_webview);
initView();
}
private void initView() {
pg = (ProgressBar) findViewById(R.id.pg);
pg.setVisibility(View.VISIBLE);
mWebView = (WebView) findViewById(R.id.wb);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl("http://m.3gbizhi.com/");
mWebView.addJavascriptInterface(this,"imagelistner");
mWebView.setWebViewClient(new MyWebViewClient());
mWebView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
WebView.HitTestResult result = mWebView.getHitTestResult();
if(result!=null){
int type = result.getType();
if(type == WebView.HitTestResult.IMAGE_TYPE ||type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE){
String imgurl = result.getExtra();
Toast.makeText(WithPhotoWebActivity.this, imgurl, Toast.LENGTH_SHORT).show();
}
}
return true;
}
});
}
@JavascriptInterface
public void openImage(String img) {
System.out.println(img);
//ShowWebImageActivity.startAction(this,img);
System.out.println(img);
}
private void addImageClickListner(){
// 這段js函數(shù)的功能就是,遍歷所有的img幾點综液,并添加onclick函數(shù)区拳,在還是執(zhí)行的時候調(diào)用本地接口傳遞url過去
mWebView.loadUrl(
"javascript:(function(){"+
" var objs = document.getElementsByTagName(\"img\");"+
" for(var i=0;i<objs.length;i++)"+
" {"+
" objs[i].onclick=function()"+
" {"+
" window.imagelistner.openImage(this.src);"+
" }"+
" }"+
" })()"
);
}
private class MyWebViewClient extends WebViewClient{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
pg.setVisibility(View.GONE);
view.getSettings().setJavaScriptEnabled(true);
super.onPageFinished(view,url);
// html加載完成之后,添加監(jiān)聽圖片的點擊js函數(shù)
addImageClickListner();
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
view.getSettings().setJavaScriptEnabled(true);
super.onPageStarted(view, url, favicon);
}
}
}