Android WebView使用与JavaScript使用
WebView基本使用
? WebView是View的一個(gè)子類,可以讓你在activity中顯示網(wǎng)頁(yè)。
可以在布局文件中寫入WebView:比如下面這個(gè)寫了一個(gè)填滿整個(gè)屏幕的WebView:
<?xml version="1.0" encoding="utf-8"?> <WebView xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/webview"android:layout_width="fill_parent"android:layout_height="fill_parent" />
?
加載一個(gè)網(wǎng)頁(yè),使用loadUrl():
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.loadUrl(http://www.example.com);
?
注意要在manifest中加上訪問(wèn)網(wǎng)絡(luò)的權(quán)限:
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
設(shè)置WebView要顯示的網(wǎng)頁(yè)
設(shè)置WevView要顯示的網(wǎng)頁(yè)方法有很多:
互聯(lián)網(wǎng)頁(yè)面直接用:
myWebView.loadUrl(“http://www.google.com“);
本地文件用:
myWebView.loadUrl(“file:///android_asset/XX.html“);
本地文件存放在:assets文件中。
還可以直接載入html的字符串,如:
String htmlString = "<h1>Title</h1><p>This is HTML text<br /><i>Formatted in italics</i><br />Anothor Line</p>"; // 載入這個(gè)html頁(yè)面 myWebView.loadData(htmlString, "text/html", "utf-8");
在WebView中使用JavaScript
如果你想要載入的頁(yè)面中用了JavaScript,你必須為你的WebView使能JavaScript。
一旦使能之后,你也可以自己創(chuàng)建接口在你的應(yīng)用和JavaScript代碼間進(jìn)行交互。
使能JavaScript
可以通過(guò)getSettings()獲得WebSettings,然后用setJavaScriptEnabled()使能JavaScript:
WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);
WebSettings中提供了很多有用的設(shè)置。
處理頁(yè)面瀏覽
當(dāng)用戶點(diǎn)擊了你的WebView中的一個(gè)鏈接,默認(rèn)的行為是Android啟動(dòng)一個(gè)處理URL的應(yīng)用,通常,默認(rèn)的瀏覽器打開并下載目標(biāo)URL。
但是,你可以在你的WebView中覆蓋這一行為,使得連接仍在你的WebView中打開。
之后,根據(jù)在WebView中維護(hù)的網(wǎng)頁(yè)瀏覽歷史,你可以允許用戶向前或向后瀏覽他們的網(wǎng)頁(yè)。
在WebView中打開所有鏈接
要打開用戶點(diǎn)擊的鏈接,只需要用setWebViewClient()方法向你的WebView提供一個(gè)WebViewClient?比如:
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.setWebViewClient(new WebViewClient());
此時(shí)就OK了, 就可以在你的WebView中打開鏈接了。
關(guān)于打開鏈接位置的更多控制
如果你對(duì)在哪里打開鏈接需要更多的控制,你可以創(chuàng)建自己的類,繼承?WebViewClient,然后覆寫shouldOverrideUrlLoading()?方法。
比如下面這個(gè):
private class MyWebViewClient extends WebViewClient{@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url){
if(Uri.parse(url).getHost().equals(www.example.com))
{ // This is my web site, so do not override; let my WebView load // the page return false; } // Otherwise, the link is not for a page on my site, so launch // another Activity that handles URLs Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; } } 將特定的鏈接用自己的WebView打開,其他鏈接用瀏覽器(intent啟動(dòng)了默認(rèn)的處理URL的Activity)。
定義完之后把這個(gè)類的對(duì)象傳入setWebViewClient()方法即可。
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.setWebViewClient(new MyWebViewClient());
實(shí)踐驗(yàn)證:在直接設(shè)置setWebViewClient(new WebViewClient());時(shí)驗(yàn)證正確,即所有鏈接都是在WebView中打開。
在設(shè)置為自定義的WebViewClient子類對(duì)象時(shí),發(fā)現(xiàn)鏈接仍然都是從默認(rèn)瀏覽器中打開。
瀏覽網(wǎng)頁(yè)歷史回退
當(dāng)你的WebView覆寫了URL載入的行為,它會(huì)自動(dòng)地對(duì)訪問(wèn)過(guò)的網(wǎng)頁(yè)積累一個(gè)歷史,你可以利用?goBack()?和?goForward()方法在這個(gè)歷史中前進(jìn)或后退。
比如說(shuō)使用后退鍵進(jìn)行網(wǎng)頁(yè)后退:
/*** 按鍵響應(yīng),在WebView中查看網(wǎng)頁(yè)時(shí),按返回鍵的時(shí)候按瀏覽歷史退回,如果不做此項(xiàng)處理則整個(gè)WebView返回退出*/@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event){// Check if the key event was the Back button and if there's historyif ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()){// 返回鍵退回myWebView.goBack();return true;}// If it wasn't the Back key or there's no web page history, bubble up// to the default// system behavior (probably exit the activity)return super.onKeyDown(keyCode, event);} ?
canGoBack()?方法在網(wǎng)頁(yè)可以后退時(shí)返回true。
類似的,canGoForward()方法可以檢查是否有可以前進(jìn)的歷史記錄。
如果你不執(zhí)行這種檢查,一旦?goBack()?和?goForward()方法到達(dá)歷史記錄頂端,它們將什么也不做。
如果不加這種設(shè)置,在用戶按下Back鍵時(shí),如果是WebView顯示網(wǎng)頁(yè),則會(huì)將WebView作為整體返回。
程序?qū)嵗?/h2>
附上完整的程序:
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;@SuppressLint("SetJavaScriptEnabled")
public class WebActivity extends Activity
{private WebView myWebView = null;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_web);// 打開網(wǎng)頁(yè)myWebView = (WebView) findViewById(R.id.webview);//// myWebView.loadUrl("http://www.cnblogs.com/mengdd/");// 博客鏈接myWebView.loadUrl("http://www.baidu.com/");// 百度鏈接// JavaScript使能(如果要加載的頁(yè)面中有JS代碼,則必須使能JS)WebSettings webSettings = myWebView.getSettings();webSettings.setJavaScriptEnabled(true);// 在WebView中打開鏈接(默認(rèn)行為是使用瀏覽器,設(shè)置此項(xiàng)后都用WebView打開)// myWebView.setWebViewClient(new WebViewClient());// 這樣設(shè)置后所有的鏈接都會(huì)在當(dāng)前WebView中打開// 更強(qiáng)的打開鏈接控制:自己覆寫一個(gè)WebViewClient類:除了指定鏈接從WebView打開,其他的鏈接默認(rèn)打開myWebView.setWebViewClient(new MyWebViewClient());}@Overridepublic boolean onCreateOptionsMenu(Menu menu){getMenuInflater().inflate(R.menu.activity_web, menu);return true;}/*** 自定義的WebViewClient類,將特殊鏈接從WebView打開,其他鏈接仍然用默認(rèn)瀏覽器打開* * @author 1* */private class MyWebViewClient extends WebViewClient{@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url){if (Uri.parse(url).getHost().equals("http://www.cnblogs.com/mengdd/archive/2013/02/27/2935811.html")|| Uri.parse(url).getHost().equals("http://music.baidu.com/")){// This is my web site, so do not override; let my WebView load// the page// 這是官網(wǎng)上的例子,但是我點(diǎn)擊特定鏈接的時(shí)候仍然是用瀏覽器而不是用自己的WebView打開,加上下面這句view.loadUrl(url)仍然是用瀏覽器,無(wú)解,不知道哪里出了問(wèn)題// view.loadUrl(url);return false;}// Otherwise, the link is not for a page on my site, so launch// another Activity that handles URLsIntent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));startActivity(intent);return true;}}/*** 按鍵響應(yīng),在WebView中查看網(wǎng)頁(yè)時(shí),按返回鍵的時(shí)候按瀏覽歷史退回,如果不做此項(xiàng)處理則整個(gè)WebView返回退出*/@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event){// Check if the key event was the Back button and if there's historyif ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()){// 返回鍵退回myWebView.goBack();return true;}// If it wasn't the Back key or there's no web page history, bubble up// to the default// system behavior (probably exit the activity)return super.onKeyDown(keyCode, event);}
} 綁定JavaScript與Android代碼
當(dāng)你為你的Android應(yīng)用中的WebView專門開發(fā)一個(gè)網(wǎng)頁(yè)應(yīng)用時(shí),你可以創(chuàng)建你的JavaScript代碼和你的客戶端的Android代碼之間的接口。
比如,你可以用JavaScript代碼調(diào)用Android代碼中的方法,來(lái)展現(xiàn)一個(gè)對(duì)話框之類,而不是使用alert()方法(JS中的對(duì)話框方法)。
在JS和Android代碼間綁定一個(gè)新的接口,需要調(diào)用?addJavascriptInterface()方法。
方法參數(shù)傳入一個(gè)Java對(duì)象實(shí)例和一個(gè)字符串,該字符串是一個(gè)名字(interface name,注意此接口不是通常所說(shuō)的那個(gè)用來(lái)實(shí)現(xiàn)的接口,而是傳入的這個(gè)對(duì)象在JS中的別名),在JS代碼中用此名字調(diào)用該Java對(duì)象的方法。
注意這個(gè)方法可以讓JS代碼控制宿主程序,這是一個(gè)非常有力的特性,但是同時(shí)也存在一些安全問(wèn)題,因?yàn)檫M(jìn)一步JS代碼可以通過(guò)反射訪問(wèn)到注入對(duì)象的公有域。攻擊者可能會(huì)在HTML和JavaScript中包含了有威脅性的代碼。
所以Android 4.1,API 17,也就是JELLY_BEAN?開始,只有被JavascriptInterface?注解標(biāo)識(shí)的公有方法可以被JS代碼訪問(wèn)。
另外,因?yàn)镴S代碼和Java對(duì)象在這個(gè)WebView所私有的后臺(tái)線程交互,所以還需要注意線程安全性問(wèn)題。
注意,與JS代碼綁定的的這個(gè)Java對(duì)象運(yùn)行在另一個(gè)線程中,與創(chuàng)建它的線程不是一個(gè)線程。
注意,這個(gè)Java對(duì)象的域是不可訪問(wèn)的。
?
綁定JavaScript與Android代碼的例子
比如可以定義這么一個(gè)類:
/*** 自定義的Android代碼和JavaScript代碼之間的橋梁類* * @author 1* */public class WebAppInterface{Context mContext;/** Instantiate the interface and set the context */WebAppInterface(Context c){mContext = c;}/** Show a toast from the web page */// 如果target 大于等于API 17,則需要加上如下注解// @JavascriptInterfacepublic void showToast(String toast){// Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();Toast.makeText(mContext, toast, Toast.LENGTH_LONG).show();}} ?
然后將這個(gè)類和你的WebView中的JS代碼綁定:
WebView webView = (WebView) findViewById(R.id.webview); webView.addJavascriptInterface(new WebAppInterface(this), "Android");
給這個(gè)對(duì)象起的別名叫“Android”。
這個(gè)就創(chuàng)立了一個(gè)接口名,叫“Android”,運(yùn)行在WebView中的JS代碼可以通過(guò)這個(gè)名字調(diào)用WebAppInterface類中的showToast()方法:
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /><script type="text/javascript">function showAndroidToast(toast) {Android.showToast(toast);}
</script> ?
特別注意:需要設(shè)置chrome handler
這個(gè)問(wèn)題讓我納悶了好久,因?yàn)殚_始的時(shí)候我寫的程序,JS代碼中的按鈕會(huì)出現(xiàn)在WebView中,但是點(diǎn)擊下去后,不會(huì)彈出相應(yīng)的對(duì)話框之類。
也就是說(shuō)JS代碼調(diào)用自己也沒(méi)有執(zhí)行?
同樣的代碼在別的地方執(zhí)行可以正常彈出啊。所以我還提問(wèn)來(lái)著:http://q.cnblogs.com/q/47060/
后來(lái)找了半天原因,才發(fā)現(xiàn)兩個(gè)問(wèn)題:
1.網(wǎng)頁(yè)按鈕按下后不出現(xiàn)JS對(duì)話框是因?yàn)闆](méi)有設(shè)置chrome handler,需要設(shè)置如下:
// 如果不設(shè)置這個(gè),JS代碼中的按鈕會(huì)顯示,但是按下去卻不彈出對(duì)話框// Sets the chrome handler. This is an implementation of WebChromeClient// for use in handling JavaScript dialogs, favicons, titles, and the// progress. This will replace the current handler.myWebView.setWebChromeClient(new WebChromeClient(){@Overridepublic boolean onJsAlert(WebView view, String url, String message,JsResult result){// TODO Auto-generated method stubreturn super.onJsAlert(view, url, message, result);}}); 2.調(diào)用Android代碼的那個(gè)按鈕也沒(méi)有出現(xiàn)Toast是因?yàn)槲野褎e名寫錯(cuò)了(大小寫沒(méi)有注意)。(這個(gè)錯(cuò)誤可以忽略,但是大家也要引以為戒。。Orz。。。)
Android調(diào)用JavaScript代碼
? 這個(gè)還比較簡(jiǎn)單,需要調(diào)用的時(shí)候只需要一行代碼:
myWebView.loadUrl("javascript:myFunction()"); 其中myFunction()是JS函數(shù)。
這里要補(bǔ)充一下,如果JavaScript函數(shù)是帶參數(shù)的,那么調(diào)用時(shí)要特別注意。
比如下面這個(gè)JS函數(shù),在原來(lái)內(nèi)容上加入一行:
function writeLine(string){console.log("Write a new Line");//調(diào)試信息document.getElementById("content").innerHTML += string + "<br />";//在content標(biāo)簽段落加入新行} 注:其中content是自定義的標(biāo)簽,html中有一個(gè)段落是:
<p id="content"></p>
那么在Android代碼中調(diào)用這個(gè)writeLine()函數(shù)時(shí),需要傳入一個(gè)字符串參數(shù),比如,想要傳入一個(gè)叫name的String:
myWebView.loadUrl("javascript:writeLine('"+name+"')");//JS代碼要是帶參數(shù) 還有就是要注意雙引號(hào)中的函數(shù)名一定不要寫錯(cuò)。
?
程序?qū)嵗?/h2>
做了一個(gè)程序:
界面中包含一個(gè)TextView,旁邊一個(gè)Button,下面整個(gè)是一個(gè)WebView。
在WebView中載入了一個(gè)本地html文件,本地文件存放在assets文件夾中。
網(wǎng)頁(yè)中前四個(gè)按鈕調(diào)用的是JavaScript函數(shù),顯示各種對(duì)話框。
SayHello按鈕調(diào)用Android代碼中的一個(gè)方法,顯示一個(gè)Toast,如圖中所示。
為了證明Android也可以調(diào)用JS代碼,最上方的Android Button按下后和“點(diǎn)擊這里”那個(gè)按鈕的效果一致,都是出現(xiàn)JS的對(duì)話框。
Activity代碼:
package com.example.hellowebjs;import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.Toast;public class WebJSActivity extends Activity
{private WebView myWebView = null;private Button myButton = null;@SuppressLint("SetJavaScriptEnabled")@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_web_js);myWebView = (WebView) findViewById(R.id.myWebView);// 得到設(shè)置屬性的對(duì)象WebSettings webSettings = myWebView.getSettings();// 使能JavaScriptwebSettings.setJavaScriptEnabled(true);// 支持中文,否則頁(yè)面中中文顯示亂碼webSettings.setDefaultTextEncodingName("GBK");// 限制在WebView中打開網(wǎng)頁(yè),而不用默認(rèn)瀏覽器myWebView.setWebViewClient(new WebViewClient());// 如果不設(shè)置這個(gè),JS代碼中的按鈕會(huì)顯示,但是按下去卻不彈出對(duì)話框// Sets the chrome handler. This is an implementation of WebChromeClient// for use in handling JavaScript dialogs, favicons, titles, and the// progress. This will replace the current handler.myWebView.setWebChromeClient(new WebChromeClient(){@Overridepublic boolean onJsAlert(WebView view, String url, String message,JsResult result){// TODO Auto-generated method stubreturn super.onJsAlert(view, url, message, result);}});// 用JavaScript調(diào)用Android函數(shù):// 先建立橋梁類,將要調(diào)用的Android代碼寫入橋梁類的public函數(shù)// 綁定橋梁類和WebView中運(yùn)行的JavaScript代碼// 將一個(gè)對(duì)象起一個(gè)別名傳入,在JS代碼中用這個(gè)別名代替這個(gè)對(duì)象,可以調(diào)用這個(gè)對(duì)象的一些方法myWebView.addJavascriptInterface(new WebAppInterface(this),"myInterfaceName");// 載入頁(yè)面:本地html資源文件myWebView.loadUrl("file:///android_asset/sample.html");// 這里用一個(gè)Android按鈕按下后調(diào)用JS中的代碼myButton = (Button) findViewById(R.id.button1);myButton.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v){// 用Android代碼調(diào)用JavaScript函數(shù):myWebView.loadUrl("javascript:myFunction()");// 這里實(shí)現(xiàn)的效果和在網(wǎng)頁(yè)中點(diǎn)擊第一個(gè)按鈕的效果一致}});}/*** 自定義的Android代碼和JavaScript代碼之間的橋梁類* * @author 1* */public class WebAppInterface{Context mContext;/** Instantiate the interface and set the context */WebAppInterface(Context c){mContext = c;}/** Show a toast from the web page */// 如果target 大于等于API 17,則需要加上如下注解// @JavascriptInterfacepublic void showToast(String toast){// Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();Toast.makeText(mContext, toast, Toast.LENGTH_LONG).show();}}} HTML文件:
<html>
<head>
<h1>
This is a HTML Page
</h1>
<!-- JavaScript腳本,主要包括了按鈕要執(zhí)行的函數(shù),顯示對(duì)話框等 -->
<script type="text/javascript">//JavaScript方法,彈出對(duì)話框顯示信息function myFunction(){alert("Hello World!");}function onAlert(){console.log("onAlert method");//顯示調(diào)試信息alert("This is a alert sample from html");}function onConfirm(){console.log("onConfirm method");var b = confirm("are you sure to login?");alert("your choice is " + b);}function onPrompt(){console.log("onPrompt method");var b = prompt("please input your password", "aaa");alert("your input is " + b);}//調(diào)用綁定的Java對(duì)象的方法,即調(diào)用Android代碼顯示對(duì)話框function showAndroidToast(toast){console.log("showAndroidToast method");myInterfaceName.showToast(toast);//注意此處的myInterfaceName要和外部傳入的名字一致,大小寫正確}
</script>
</head>
<body><p><!-- 前四個(gè)按鈕調(diào)用JS函數(shù) -->JavaScript函數(shù)調(diào)用 <br /><button οnclick="myFunction()">點(diǎn)擊這里!</button><br /> <input type="button" value="alert" οnclick="onAlert()" /> <br /><input type="button" value="confirm" οnclick="onConfirm()" /> <br /><input type="button" value="prompt" οnclick="onPrompt()" /><br /><!-- 上面用了兩種定義按鈕的方式,效果一樣的 --></p><p><!-- 這個(gè)Say hello 按鈕調(diào)用Android代碼中的方法 -->用JavaScript按鈕調(diào)用Android代碼 <br /> <input type="button"value="Say hello" onClick="showAndroidToast('Hello Android!')" /></p><a href="http://www.google.com" />Google</a></body>
</html> Activity布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/myRelativeLayout"android:layout_width="match_parent"android:layout_height="match_parent" ><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="@dimen/padding_medium"android:text="@string/hello_world"tools:context=".WebJSActivity" /><Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_toRightOf="@id/textView1"android:text="@string/btn1_text" /><WebViewandroid:id="@+id/myWebView"android:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_below="@id/textView1" /></RelativeLayout>
轉(zhuǎn)載于:https://www.cnblogs.com/chenxibobo/p/6136664.html
總結(jié)
以上是生活随笔為你收集整理的Android WebView使用与JavaScript使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 周易中好听的名字
- 下一篇: 一套伊璇补水美白价格多少钱?