android与html5之间可以相互交互,即android中的类可以调用javascript中的函数,javascript可以调用android中的类的方法。
这个例子中,html5完成数据库的操作,包括数据库的创建、表的创建、数据的增删查改等,还有html5的定位功能。
先看效果图:
布局文件:main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button android:id="@+id/button" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Send To JavaScript" />
<TextView android:id="@+id/textview" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="android itme"/>
<WebView
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
</LinearLayout>
html5文件:index.html
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd ">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script language="javascript" type="text/javascript">
//初始化数据库
function initDatabase() {
try {
if (!window.openDatabase) {
alert('Databases are not supported by your browser');
} else {
var shortName = 'YARINDB';
var version = '1.0';
var displayName = 'yarin db';
var maxSize = 100000; // in bytes
YARINDB = openDatabase(shortName, version, displayName, maxSize);
createTables();
selectAll();
}
} catch(e) {
if (e == 2) {
// Version mismatch.
console.log("Invalid database version."); //调试用,在控制台输出字符串
} else {
console.log("Unknown error "+ e +".");
}
return;
}
}
function createTables(){
YARINDB.transaction(
function (transaction) {
transaction.executeSql('CREATE TABLE IF NOT EXISTS yarin(id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL,desc TEXT NOT NULL);', [], nullDataHandler, errorHandler);
}
);
insertData();
}
function insertData(){
YARINDB.transaction(
function (transaction) {
//Starter data when page is initialized
var data = ['1','yarin yang','I am yarin'];
var data1 = ['2','Jason Choi','I am a graduate student!'];
transaction.executeSql("INSERT INTO yarin(id, name, desc) VALUES (?, ?, ?)", [data[0], data[1], data[2]]);
transaction.executeSql("INSERT INTO yarin(id, name, desc) VALUES (?, ?, ?)", [data1[0], data1[1], data1[2]]);
}
);
}
function errorHandler(transaction, error){
if (error.code==1){
// DB Table already exists
} else {
// Error is a human-readable string.
console.log('Oops. Error was '+error.message+' (Code '+error.code+')');
}
return false;
}
function nullDataHandler(){
console.log("SQL Query Succeeded");
}
function selectAll(){
YARINDB.transaction(
function (transaction) {
transaction.executeSql("SELECT * FROM yarin;", [], dataSelectHandler, errorHandler);
}
);
}
function dataSelectHandler(transaction, results){
// Handle the results
for (var i=0; i<results.rows.length; i++) {
var row = results.rows.item(i);
var newFeature = new Object();
newFeature.name = row['name'];
newFeature.decs = row['desc'];
document.getElementById("name").innerHTML="name:"+newFeature.name;
document.getElementById("desc").innerHTML="desc:"+newFeature.decs;
}
}
function updateData(){
YARINDB.transaction(
function (transaction) {
var data = ['xiaoming huang','not at all'];
transaction.executeSql("UPDATE yarin SET name=?, desc=? WHERE id = 2", [data[0], data[1]]);
}
);
selectAll();
}
function ddeleteTables(){
YARINDB.transaction(
function (transaction) {
transaction.executeSql("DROP TABLE yarin;", [], nullDataHandler, errorHandler);
}
);
console.log("Table 'page_settings' has been dropped.");
}
//定位
function get_location() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(show_map,handle_error,{enableHighAccuracy:false,maximumAge:1000,timeout:15000});
} else {
alert("Your browser does not support HTML5 geoLocation");
}
}
function show_map(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var city = position.coords.city;
//telnet localhost 5554
//geo fix -82.411629 28.054553
//geo fix -121.45356 46.51119 4392
//geo nmea $GPGGA,001431.092,0118.2653,N,10351.1359,E,0,00,,-19.6,M,4.1,M,,0000*5B
document.getElementById("Latitude").innerHTML="latitude:"+latitude;
document.getElementById("Longitude").innerHTML="longitude:"+longitude;
document.getElementById("City").innerHTML="city:"+city;
}
function handle_error(err) {
switch (err.code) {
case 1:
alert("permission denied");
break;
case 2:
alert("the network is down or the position satellites can't be contacted");
break;
case 3:
alert("time out");
break;
default:
alert("unknown error");
break;
}
}
function initLocalStorage(){
if (window.localStorage) {
textarea.addEventListener("keyup", function() {
window.localStorage["value"] = this.value;
window.localStorage["time"] = new Date().getTime();
}, false);
} else {
alert("LocalStorage are not supported in this browser.");
}
}
window.onload = function() {
initDatabase();
initLocalStorage();
get_location();
}
</script>
<script language="javascript" type="text/javascript">
function getFromAndroid(str){ //接收来自android的数据
document.getElementById("android").innerHTML=str;
}
function sendToAndroid(){
console.log("!!!!!!!!!I'm sending to android!!!!!!!!!");
var str = "the data is from JavaScript!";
window.injs.runOnAndroidJavaScript(str);//通过injs接口调用android的函数
}
function ale()
{
alert("This is an alert!");
}
</script>
</head>
<body>
<div><input type="submit" name="Submit" value="alert" οnclick="ale()" /></div>
<input type="button" value="Send To Android" οnclick="sendToAndroid()"/>
<div id="android">JavaScript itme</div>
<textarea id="textarea"></textarea>
<input type='button' value='get' onClick="alert(window.localStorage['value']+':'+window.localStorage['time'])"/>
<div id="name"></div>
<div id="desc"></div>
<input type="button" value="updateData" οnclick="updateData()"/>
<div id="Latitude"></div>
<div id="Longitude"></div>
<div id="City"></div>
</body>
</html>
package com.yarin.android.html5;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.webkit.GeolocationPermissions;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.TextView;
//关于android2.3中javascript交互的问题
//http://code.google.com/p/android/issues/detail?id=12987
public class MainActivity extends Activity {
private WebView webView = null;
private Handler handler = new Handler();
private Button button = null;
final class InJavaScript {
public void runOnAndroidJavaScript(final String str) {
handler.post(new Runnable() {
public void run() {
TextView show = (TextView) findViewById(R.id.textview);
show.setText(str);
}
});
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
//调用javascript中的方法,传入string数据
webView.loadUrl("javascript:getFromAndroid('the data is from android!')");
}
});
webView = (WebView) findViewById(R.id.webview);
//把本类的一个实例添加到js的全局对象window中,
//这样就可以使用window.injs来调用它的方法
webView.addJavascriptInterface(new InJavaScript(), "injs");
//设置支持JavaScript脚本
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
//设置可以访问文件
webSettings.setAllowFileAccess(true);
//设置支持缩放
webSettings.setBuiltInZoomControls(true);
webSettings.setDatabaseEnabled(true);
String dir = this.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
webSettings.setDatabasePath(dir);
//使用localStorage则必须打开
webSettings.setDomStorageEnabled(true);
webSettings.setGeolocationEnabled(true);
//webSettings.setGeolocationDatabasePath(dir);
//设置WebViewClient
webView.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
});
//设置WebChromeClient
webView.setWebChromeClient(new WebChromeClient(){
//处理javascript中的alert
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
//构建一个Builder来显示网页中的对话框
Builder builder = new Builder(MainActivity.this);
builder.setTitle("Alert");
builder.setMessage(message);
builder.setPositiveButton(android.R.string.ok,
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
});
builder.setCancelable(false);
builder.create();
builder.show();
return true;
};
//处理javascript中的confirm
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
Builder builder = new Builder(MainActivity.this);
builder.setTitle("confirm");
builder.setMessage(message);
builder.setPositiveButton(android.R.string.ok,
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
});
builder.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.cancel();
}
});
builder.setCancelable(false);
builder.create();
builder.show();
return true;
};
@Override
//设置网页加载的进度条
public void onProgressChanged(WebView view, int newProgress) {
MainActivity.this.getWindow().setFeatureInt(Window.FEATURE_PROGRESS, newProgress * 100);
super.onProgressChanged(view, newProgress);
}
//设置应用程序的标题title
public void onReceivedTitle(WebView view, String title) {
MainActivity.this.setTitle(title);
super.onReceivedTitle(view, title);
}
public void onExceededDatabaseQuota(String url,
String databaseIdentifier, long currentQuota,
long estimatedSize, long totalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater) {
quotaUpdater.updateQuota(estimatedSize * 2);
}
public void onGeolocationPermissionsShowPrompt(String origin,
GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
super.onGeolocationPermissionsShowPrompt(origin, callback);
}
public void onReachedMaxAppCacheSize(long spaceNeeded,
long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
quotaUpdater.updateQuota(spaceNeeded * 2);
}
});
// 覆盖默认后退按钮的作用,替换成WebView里的查看历史页面
webView.setOnKeyListener(new View.OnKeyListener() {
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.loadUrl("file:///android_asset/index.html");
}
}