标签:
WebView是Android中一个非常实用的组件,它和Safai、Chrome一样都是基于Webkit网页渲染引擎,可以通过加载HTML数据的方式便捷地展现软件的界面。使用WebView开发软件有一下几个优点:
1.可以打开远程URL页面,也可以加载本地HTML数据;
2.可以无缝的在java和javascript之间进行交互操作;
3.高度的定制性,可根据开发者的需要进行多样性定制。
下面就通过例子来介绍一下WebView的使用方法。
我们先建一个webview项目,项目结构如左图:
在这个项目中,我们会先进入MainActivity这个导航界面(上边右图),通过点击不同按钮转向不同的Activity,下面分别简单介绍一下这几个Activity的所要演示的功能:
LoadActivity:主要演示加载网络页面和WebView的一些基本设置;
CaptureActivity:主要演示WebView的截图的功能;
FileActivity:主要演示访问本地文件的功能;
JSActivity:主要演示WebView对JS的支持以及JS和Java之间的互相调用;
接下来,我们会逐一分析各个Activity的相关信息:
LoadActivity:
与之对应的布局文件为load.xml,演示效果如下:
我们在文本框中输入URL,然后点击“load”按钮,然后由WebView加载相应的页面,在加载过程中,根据加载进度更新窗口的进度条。由于布局相对简单,我们主要来看一下LoadActivity.java的代码:
-
package com.scott.webview;
-
-
import android.app.Activity;
-
import android.os.Bundle;
-
import android.view.KeyEvent;
-
import android.view.View;
-
import android.view.Window;
-
import android.webkit.WebChromeClient;
-
import android.webkit.WebSettings;
-
import android.webkit.WebView;
-
import android.webkit.WebViewClient;
-
import android.widget.Button;
-
import android.widget.EditText;
-
-
public class LoadActivity extends Activity {
-
-
private WebView webView;
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
-
-
getWindow().requestFeature(Window.FEATURE_PROGRESS);
-
-
setContentView(R.layout.load);
-
-
webView = (WebView) findViewById(R.id.webView);
-
-
WebSettings settings = webView.getSettings();
-
settings.setSupportZoom(true);
-
settings.setBuiltInZoomControls(true);
-
settings.setJavaScriptEnabled(true);
-
-
webView.setWebViewClient(new WebViewClient() {
-
-
@Override
-
public boolean shouldOverrideUrlLoading(WebView view, String url) {
-
view.loadUrl(url);
-
return true;
-
}
-
});
-
-
-
webView.setOnKeyListener(new View.OnKeyListener() {
-
@Override
-
public boolean onKey(View v, int keyCode, KeyEvent event) {
-
if (event.getAction() == KeyEvent.ACTION_DOWN) {
-
if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
-
webView.goBack();
-
return true;
-
}
-
}
-
return false;
-
}
-
});
-
-
webView.setWebChromeClient(new WebChromeClient() {
-
-
@Override
-
public void onProgressChanged(WebView view, int newProgress) {
-
-
LoadActivity.this.setProgress(newProgress * 100);
-
}
-
});
-
-
final EditText url = (EditText) findViewById(R.id.url);
-
-
Button loadURL = (Button) findViewById(R.id.loadURL);
-
loadURL.setOnClickListener(new View.OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
webView.loadUrl(url.getText().toString());
-
webView.requestFocus();
-
}
-
});
-
}
-
}
可以看到,我们使用loadUrl方法加载一个url页面,然后重写WebChromeClient的onProgressChanged方法更新进度条。loadUrl方法除了能加载远程页面,还能加载本地的文件:
-
-
webView.loadUrl("file:///android_asset/index.html");
-
-
webView.loadUrl("file:///mnt/sdcard/index.html");
这些都会在后边的示例中使用到。
CaptureActivity:
与之对应的布局文件为capture.xml,也比较简单,它的演示效果如下:
记得在AndroidManifest.xml中加入对sdcard的写权限:
-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
截图成功后,在/mnt/sdcard目录下会生成一个当前网页的截图,如图:
我们导出一下,看看是不是当前的网页界面:
整个过程操作已经完成了,让我们来看一下CaptureActivity.java的代码:
-
package com.scott.webview;
-
-
import java.io.FileOutputStream;
-
-
import android.app.Activity;
-
import android.graphics.Bitmap;
-
import android.graphics.Canvas;
-
import android.graphics.Picture;
-
import android.os.Bundle;
-
import android.util.Log;
-
import android.view.View;
-
import android.webkit.WebView;
-
import android.widget.Button;
-
import android.widget.Toast;
-
-
public class CaptureActivity extends Activity {
-
-
private static final String TAG = "CAPTURE";
-
-
private WebView webView;
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
-
setContentView(R.layout.capture);
-
-
webView = (WebView) findViewById(R.id.webView);
-
webView.loadUrl("http://www.baidu.com");
-
-
Button capture = (Button) findViewById(R.id.capture);
-
capture.setOnClickListener(new View.OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
-
Picture picture = webView.capturePicture();
-
int width = picture.getWidth();
-
int height = picture.getHeight();
-
if (width > 0 && height > 0) {
-
-
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-
-
Canvas canvas = new Canvas(bitmap);
-
-
picture.draw(canvas);
-
try {
-
String fileName = "/sdcard/webview_capture.jpg";
-
FileOutputStream fos = new FileOutputStream(fileName);
-
-
bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
-
fos.close();
-
Toast.makeText(CaptureActivity.this, "CAPTURE SUCCESS", Toast.LENGTH_LONG).show();
-
} catch (Exception e) {
-
Log.e(TAG, e.getMessage());
-
}
-
}
-
}
-
});
-
}
-
}
FileActivity:
这个界面没有布局文件,在代码中完成,它将演示如何加载一段html代码,并应用刚才生成的网页截图,效果如下图:
在这个过程中,我们加载了截图,并给图加上了红色的边框,CaptureActivity.java代码如下:
-
package com.scott.webview;
-
-
import android.app.Activity;
-
import android.os.Bundle;
-
import android.webkit.WebView;
-
-
public class FileActivity extends Activity {
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
WebView webView = new WebView(this);
-
webView.getSettings().setAllowFileAccess(true);
-
String baseURL = "file:///mnt/sdcard/"; //根URL
-
String html = "<html><body>"
-
+ "<h3>image from sdcard:<h3><br/>"
-
+ "<img src=‘webview_capture.jpg‘ style=‘border:2px solid #FF0000;‘/>"
-
+ "</body></html>";
-
-
webView.loadDataWithBaseURL(baseURL, html, "text/html", "utf-8", null);
-
-
setContentView(webView);
-
}
-
}
如果将html文本保存成.html文件,放于/mnt/sdcard目录下,然后用以下方式加载也能达到相同的效果:
-
webView.loadUrl("file:///mnt/sdcard/index.html");
接下来是最后一个示例:JSActivity,也是最精彩的示例,演示如何在JS和Java之间通信,我们来看一下演示过程,如图:
然后谈谈我们的执行过程,我们需要在Java代码中设置WebView的一些事件的响应,比如alert、confirm以及prompt这些JS事件,让它们按照我们的要求呈现给用户,然后我们需要定义一个Java和JS之间的接口对象,当我们加载完一个html文档后,根据这个对象的接口名称就可以在文档的JS代码中轻松的调用这个接口对象的方法,执行Java代码,我们也可以在Java端执行html文档中的JS代码。下面我们将通过代码来证实这一过程:
JSActivity.java代码如下:
-
package com.scott.webview;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
-
import android.app.Activity;
-
import android.app.AlertDialog;
-
import android.content.DialogInterface;
-
import android.os.Bundle;
-
import android.os.Handler;
-
import android.os.Message;
-
import android.util.Log;
-
import android.view.LayoutInflater;
-
import android.view.View;
-
import android.view.Window;
-
import android.webkit.JsPromptResult;
-
import android.webkit.JsResult;
-
import android.webkit.WebChromeClient;
-
import android.webkit.WebView;
-
import android.widget.EditText;
-
import android.widget.Toast;
-
-
public class JSActivity extends Activity {
-
-
private static final String TAG = "JSActivity";
-
-
private WebView webView;
-
-
private Handler handler = new Handler() {
-
public void handleMessage(android.os.Message msg) {
-
int index = msg.arg1;
-
JSActivity.this.setProgress(index * 1000);
-
};
-
};
-
-
@Override
-
public void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
-
getWindow().requestFeature(Window.FEATURE_PROGRESS);
-
-
webView = new WebView(this);
-
-
webView.getSettings().setJavaScriptEnabled(true);
-
-
webView.addJavascriptInterface(new Object() {
-
@SuppressWarnings("unused")
-
public List<String> getList() {
-
List<String> list = new ArrayList<String>();
-
for (int i = 0; i <= 10; i++) {
-
try {
-
Thread.sleep(200);
-
} catch (InterruptedException e) {
-
Log.e(TAG, "error:" + e.getMessage());
-
}
-
list.add("current index is: " + i);
-
-
-
-
Message msg = handler.obtainMessage();
-
msg.arg1 = i;
-
handler.sendMessage(msg);
-
}
-
success();
-
return list;
-
}
-
-
public void success() {
-
-
webView.loadUrl("javascript:success(‘congratulations‘)");
-
}
-
}, "bridge");
-
-
webView.setWebChromeClient(new WebChromeClient() {
-
@Override
-
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
-
new AlertDialog.Builder(JSActivity.this)
-
.setTitle("alert")
-
.setMessage(message)
-
.setPositiveButton("YES", new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
-
result.confirm();
-
}
-
}).create().show();
-
return true;
-
}
-
-
@Override
-
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
-
new AlertDialog.Builder(JSActivity.this)
-
.setTitle("confirm")
-
.setMessage(message)
-
.setPositiveButton("YES", new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
Toast.makeText(JSActivity.this, "you clicked yes", 0).show();
-
result.confirm();
-
}
-
})
-
.setNegativeButton("NO", new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
-
result.cancel();
-
}
-
}).create().show();
-
return true;
-
}
-
-
@Override
-
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
-
final JsPromptResult result) {
-
LayoutInflater inflater = getLayoutInflater();
-
View prompt = inflater.inflate(R.layout.prompt, null);
-
final EditText text = (EditText) prompt.findViewById(R.id.prompt_input);
-
text.setHint(defaultValue);
-
-
new AlertDialog.Builder(JSActivity.this)
-
.setTitle("prompt")
-
.setView(prompt)
-
.setPositiveButton("YES", new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
-
result.confirm(text.getText().toString());
-
}
-
})
-
.setNegativeButton("NO", new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
result.cancel();
-
}
-
}).create().show();
-
return true;
-
}
-
});
-
-
-
webView.loadUrl("file:///android_asset/index.html");
-
-
setContentView(webView);
-
}
-
}
需要注意的是,在重写onJsAlert、onJsConfirm、onJsPrompt这几个方法中,不要忘了用JsResult.confirm()或JsResult.cancel()处理结果,否则页面就不能再响应接下的事件了,关于这一点,我们可以看一下JsResult的代码:
-
-
-
-
public final void confirm() {
-
mResult = true;
-
wakeUp();
-
}
-
-
-
-
-
public final void cancel() {
-
mResult = false;
-
wakeUp();
-
}
可以看到confirm和cancel方法都涉及到了一个wakeUp方法,这个方法主要作用是唤醒WebCore线程,定义如下:
-
-
protected final void wakeUp() {
-
if (mReady) {
-
synchronized (mProxy) {
-
mProxy.notify();
-
}
-
} else {
-
mTriedToNotifyBeforeReady = true;
-
}
-
}
所以朋友们如果要重写这几个方法时要切记处理JsResult这个对象实例。
我们在处理onJsPrompt时,使用了自定义的界面,加载的是/res/layout/prompt.xml,定义如下:
-
<?xml version="1.0" encoding="utf-8"?>
-
<LinearLayout
-
xmlns:android="http://schemas.android.com/apk/res/android"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content">
-
<EditText
-
android:id="@+id/prompt_input"
-
android:layout_width="fill_parent"
-
android:layout_height="wrap_content"/>
-
</LinearLayout>
在JSActivity.java代码中,我们注意到WebView组件加载了assets中的index.html,它包含与Java交互的JS代码,如下:
-
<html>
-
<head>
-
<script type="text/javascript">
-
function doAlert() {
-
alert("hello!");
-
}
-
-
function doConfirm() {
-
confirm("are you sure?");
-
}
-
-
function doPrompt() {
-
var val = prompt("what‘s your name?");
-
if (val) {
-
alert("your name is:" + val);
-
}
-
}
-
-
function getList() {
-
//使用java和javascript的接口bridge的方法获取集合
-
var list = window.bridge.getList();
-
var result = document.getElementById("result");
-
for (var i = 0; i < list.size(); i++) {
-
var div = document.createElement("div");
-
div.innerHTML = list.get(i).toString();
-
result.appendChild(div);
-
}
-
}
-
-
function success(msg) {
-
alert(msg);
-
}
-
</script>
-
</head>
-
<body background="black">
-
<input type="button" value="alert" onclick="doAlert()"/><br/>
-
<input type="button" value="confirm" onclick="doConfirm()"/><br/>
-
<input type="button" value="prompt" onclick="doPrompt()"/><br/>
-
<input type="button" value="getList" onclick="getList()"/><br/>
-
<div id="result"></div>
-
</body>
-
</html>
WebView的优点还不止这些,希望在今后的时间里,再和大家分享WebView的相关技术,也希望这篇文章能够对初识WebView的朋友们带来帮助。
android浅谈WebView的使用
标签:
原文地址:http://blog.csdn.net/xiaopihaierletian/article/details/51479475