欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android WebView加载html5介绍

程序员文章站 2023-11-29 08:28:16
android设备多分辨率的问题 android浏览器默认预览模式浏览 会缩小页面 webview中则会以原始大小显示 android浏览器和webview默认为mdpi。...
android设备多分辨率的问题
android浏览器默认预览模式浏览 会缩小页面 webview中则会以原始大小显示
android浏览器和webview默认为mdpi。hdpi相当于mdpi的1.5倍 ldpi相当于0.75倍
三种解决方式:1 viewport属性 2 css控制 3 js控制
1 viewport属性放在html的<meta>中
html代码
复制代码 代码如下:

<spanstyle="font-size: x-small"> <head>
<title>exmaple</title>
<metaname=”viewport” content=”width=device-width,user-scalable=no”/>
</head></span>

meta中viewport的属性如下
html代码
复制代码 代码如下:

<spanstyle="font-size: x-small"> <metaname="viewport"
content="
height = [pixel_value | device-height] ,
width = [pixel_value | device-width ] ,
initial-scale = float_value ,
minimum-scale = float_value ,
maximum-scale = float_value ,
user-scalable = [yes | no] ,
target-densitydpi = [dpi_value | device-dpi |
high-dpi | medium-dpi | low-dpi]
"
/></span>


2 css控制设备密度
为每种密度创建独立的样式表(注意其中的webkit-device-pixel-ratio 3个数值对应3种分辨率)

html代码
复制代码 代码如下:

<linkrel="stylesheet"media="screen and (-webkit-device-pixel-ratio: 1.5)"href="hdpi.css"/>
<linkrel="stylesheet"media="screen and (-webkit-device-pixel-ratio: 1.0)"href="mdpi.css"/>
<linkrel="stylesheet"media="screen and (-webkit-device-pixel-ratio: 0.75)"href="ldpi.css"/>

在一个样式表中,指定不同的样式

html代码
复制代码 代码如下:

#header {
<spanstyle="white-space: pre"> </span> background:url(medium-density-image.png);
}
@media screen and (-webkit-device-pixel-ratio: 1.5) {
// css for high-density screens
#header {
background:url(high-density-image.png);
}
}
@media screen and (-webkit-device-pixel-ratio: 0.75) {
// css for low-density screens
#header {
background:url(low-density-image.png);
}
}


html代码
复制代码 代码如下:

<metaname="viewport"content="target-densitydpi=device-dpi, width=device-width"/>
[code]
3 js控制
android浏览器和webview支持查询当前设别密度的dom特性
window.devicepixelratio 同样值有3个(0.75,1,1.5对应3种分辨率)
js中查询设备密度的方法
js代码
[code]
if (window.devicepixelratio == 1.5) {
alert("this is a high-density screen");
} elseif (window.devicepixelration == 0.75) {
alert("this is a low-density screen");
}

android中构建html5应用
使用webview控件 与其他控件的使用方法相同 在layout中使用一个<webview>标签
webview不包括导航栏,地址栏等完整浏览器功能,只用于显示一个网页
在webview中加载web页面,使用loadurl()
java代码
复制代码 代码如下:

webview mywebview = (webview) findviewbyid(r.id.webview);
mywebview.loadurl("http://www.example.com");

注意在manifest文件中加入访问互联网的权限:
xml代码
复制代码 代码如下:

<uses-permissionandroid:name="android.permission.internet"/>

在android中点击一个链接,默认是调用应用程序来启动,因此webview需要代为处理这个动作 通过webviewclient
java代码
复制代码 代码如下:

//设置webviewclient
webview.setwebviewclient(new webviewclient(){
publicboolean shouldoverrideurlloading(webview view, string url) {
view.loadurl(url);
returntrue;
}
publicvoid onpagefinished(webview view, string url) {
super.onpagefinished(view, url);
}
publicvoid onpagestarted(webview view, string url, bitmap favicon) {
super.onpagestarted(view, url, favicon);
}
});

这个webviewclient对象是可以自己扩展的,例如
java代码
复制代码 代码如下:

privateclass mywebviewclient extends webviewclient {
publicboolean shouldoverrideurlloading(webview view, string url) {
if (uri.parse(url).gethost().equals("www.example.com")) {
returnfalse;
}
intent intent = new intent(intent.action_view, uri.parse(url));
startactivity(intent);
returntrue;
}
}

之后:
java代码
复制代码 代码如下:

webview mywebview = (webview) findviewbyid(r.id.webview);
mywebview.setwebviewclient(new mywebviewclient());

另外出于用户习惯上的考虑 需要将webview表现得更像一个浏览器,也就是需要可以回退历史记录
因此需要覆盖系统的回退键 goback,goforward可向前向后浏览历史页面
java代码
复制代码 代码如下:

publicboolean onkeydown(int keycode, keyevent event) {
if ((keycode == keyevent.keycode_back) && mywebview.cangoback() {
mywebview.goback();
returntrue;
}
returnsuper.onkeydown(keycode, event);
}

java代码
复制代码 代码如下:

webview mywebview = (webview) findviewbyid(r.id.webview);
websettings websettings = mywebview.getsettings();
websettings.setjavascriptenabled(true);

(这里的websetting用处非常大 可以开启很多设置 在之后的本地存储,地理位置等之中都会使用到)
1 在js中调用android的函数方法
首先 需要在android程序中建立接口
java代码
复制代码 代码如下:

finalclass injavascript {
publicvoid runonandroidjavascript(final string str) {
handler.post(new runnable() {
publicvoid run() {
textview show = (textview) findviewbyid(r.id.textview);
show.settext(str);
}
});
}
}

java代码
复制代码 代码如下:

//把本类的一个实例添加到js的全局对象window中,
//这样就可以使用windows.injs来调用它的方法
webview.addjavascriptinterface(new injavascript(), "injs");
在javascript中调用js代码
function sendtoandroid(){
var str = "cookie call the android method from js";
windows.injs.runonandroidjavascript(str);//调用android的函数
}

2 在android中调用js的方法
在js中的方法:
js代码
复制代码 代码如下:

function getfromandroid(str){
document.getelementbyidx_x_x_x("android").innerhtml=str;
}

在android调用该方法java代码
复制代码 代码如下:

button button = (button) findviewbyid(r.id.button);
button.setonclicklistener(new onclicklistener() {
publicvoid onclick(view arg0) {
//调用javascript中的方法
webview.loadurl("javascript:getfromandroid('cookie call the js function from android')");
}
});

3 android中处理js的警告,对话框等 在android中处理js的警告,对话框等需要对webview设置webchromeclient对象
java代码
复制代码 代码如下:

//设置webchromeclient
webview.setwebchromeclient(new webchromeclient(){
//处理javascript中的alert
publicboolean 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() {
publicvoid onclick(dialoginterface dialog, int which) {
result.confirm();
}
});
builder.setcancelable(false);
builder.create();
builder.show();
returntrue;
};
//处理javascript中的confirm
publicboolean 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() {
publicvoid onclick(dialoginterface dialog, int which) {
result.confirm();
}
});
builder.setnegativebutton(android.r.string.cancel,
new dialoginterface.onclicklistener() {
publicvoid onclick(dialoginterface dialog, int which) {
result.cancel();
}
});
builder.setcancelable(false);
builder.create();
builder.show();
returntrue;
};
@override
//设置网页加载的进度条
publicvoid onprogresschanged(webview view, int newprogress) {
mainactivity.this.getwindow().setfeatureint(window.feature_progress, newprogress * 100);
super.onprogresschanged(view, newprogress);
}
//设置应用程序的标题title
publicvoid onreceivedtitle(webview view, string title) {
mainactivity.this.settitle(title);
super.onreceivedtitle(view, title);
}
});

android中的调试
通过js代码输出log信息
js代码
js代码: console.log("hello world");
log信息: console: hello world http://www.example.com/hello.html :82
在webchromeclient中实现onconsolemesaage()回调方法,让其在logcat中打印信息
java代码
复制代码 代码如下:

webview mywebview = (webview) findviewbyid(r.id.webview);
mywebview.setwebchromeclient(new webchromeclient() {
publicvoid onconsolemessage(string message, int linenumber, string sourceid) {
log.d("myapplication", message + " -- from line "
+ linenumber + " of "
+ sourceid);
}
});

以及java代码
复制代码 代码如下:

webview mywebview = (webview) findviewbyid(r.id.webview);
mywebview.setwebchromeclient(new webchromeclient() {
publicboolean onconsolemessage(consolemessage cm) {
log.d("myapplication", cm.message() + " -- from line "
+ cm.linenumber() + " of "
+ cm.sourceid() );
returntrue;
}
});

*consolemessage 还包括一个 messagelevel 表示控制台传递信息类型。 您可以用messagelevel()查询信息级别,以确定信息的严重程度,然后使用适当的log方法或采取其他适当的措施。
html5本地存储在android中的应用
html5提供了2种客户端存储数据新方法: localstorage 没有时间限制 sessionstorage 针对一个session的数据存储
js代码
复制代码 代码如下:

<script type="text/javascript">
localstorage.lastname="smith";
document.write(localstorage.lastname);
</script>
<script type="text/javascript">
sessionstorage.lastname="smith";
document.write(sessionstorage.lastname);
</script>

webstorage的api:
js代码
复制代码 代码如下:

//清空storage
localstorage.clear();
//设置一个键值
localstorage.setitem(“yarin”,“yangfegnsheng”);
//获取一个键值
localstorage.getitem(“yarin”);
//获取指定下标的键的名称(如同array)
localstorage.key(0);
//return “fresh” //删除一个键值
localstorage.removeitem(“yarin”);
注意一定要在设置中开启哦
setdomstorageenabled(true)
在android中进行操作 java代码
//启用数据库
websettings.setdatabaseenabled(true);
string dir = this.getapplicationcontext().getdir("database", context.mode_private).getpath();
//设置数据库路径
websettings.setdatabasepath(dir);
//使用localstorage则必须打开
websettings.setdomstorageenabled(true);
//扩充数据库的容量(在webchromeclinet中实现)
publicvoid onexceededdatabasequota(string url, string databaseidentifier, long currentquota,
long estimatedsize, long totalusedquota, webstorage.quotaupdater quotaupdater) {
quotaupdater.updatequota(estimatedsize * 2);
}
在js中按常规进行数据库操作 js代码
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'];
transaction.executesql("insert into yarin(id, name, desc) values (?, ?, ?)", [data[0], data[1], data[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+')');
}
returnfalse;
}

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.getelementbyidx_x_x_x("name").innerhtml="name:"+newfeature.name;
document.getelementbyidx_x_x_x("desc").innerhtml="desc:"+newfeature.decs;
}
}
function updatedata(){
yarindb.transaction(
function (transaction) {
var data = ['fengsheng yang','i am fengsheng'];
transaction.executesql("update yarin set name=?, desc=? where id = 1", [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.");
}

注意onload中的初始化工作
复制代码 代码如下:

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();
}

html5地理位置服务在android中的应用
android中java代码
复制代码 代码如下:

//启用地理定位
websettings.setgeolocationenabled(true);
//设置定位的数据库路径
websettings.setgeolocationdatabasepath(dir);
//配置权限(同样在webchromeclient中实现)
publicvoid ongeolocationpermissionsshowprompt(string origin,
geolocationpermissions.callback callback) {
callback.invoke(origin, true, false);
super.ongeolocationpermissionsshowprompt(origin, callback);
}
在manifest中添加权限 xml代码
<uses-permissionandroid:name="android.permission.access_fine_location"/>
<uses-permissionandroid:name="android.permission.access_coarse_location"/>
html5中 通过navigator.geolocation对象获取地理位置信息 常用的navigator.geolocation对象有以下三种方法: js代码
//获取当前地理位置
navigator.geolocation.getcurrentposition(success_callback_function, error_callback_function, position_options)
//持续获取地理位置
navigator.geolocation.watchposition(success_callback_function, error_callback_function, position_options)
//清除持续获取地理位置事件
navigator.geolocation.clearwatch(watch_position_id)
其中success_callback_function为成功之后处理的函数,error_callback_function为失败之后返回的处理函数,参数position_options是配置项 在js中的代码js代码
//定位
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.getelementbyidx_x_x_x("latitude").innerhtml="latitude:"+latitude;
document.getelementbyidx_x_x_x("longitude").innerhtml="longitude:"+longitude;
document.getelementbyidx_x_x_x("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;
}
}

其中position对象包含很多数据 error代码及选项 可以查看文档
构建html5离线应用
需要提供一个cache manifest文件,理出所有需要在离线状态下使用的资源
例如manifest代码
cache manifest
#这是注释
images/sound-icon.png
images/background.png
clock.html
clock.css
clock.js
network:
test.cgi
cache:
style/default.css
fallback:
/files/projects /projects
在html标签中声明 <html manifest="clock.manifest"> html5离线应用更新缓存机制 分为手动更新和自动更新2种 自动更新: 在cache manifest文件本身发生变化时更新缓存 资源文件发生变化不会触发更新 手动更新: 使用window.applicationcache
js代码
复制代码 代码如下:

if (window.applicationcache.status == window.applicationcache.updateready) {
window.applicationcache.update(); 
}
在线状态检测 html5 提供了两种检测是否在线的方式:navigator.online(true/false) 和 online/offline事件。在android中构建离线应用java代码
//开启应用程序缓存
websettingssetappcacheenabled(true);
string dir = this.getapplicationcontext().getdir("cache", context.mode_private).getpath();
//设置应用缓存的路径
websettings.setappcachepath(dir);
//设置缓存的模式
websettings.setcachemode(websettings.load_default);
//设置应用缓存的最大尺寸
websettings.setappcachemaxsize(1024*1024*8);
//扩充缓存的容量
publicvoid onreachedmaxappcachesize(long spaceneeded,
long totalusedquota, webstorage.quotaupdater quotaupdater) {
quotaupdater.updatequota(spaceneeded * 2);
}