本章学习创建一个不通过应用商店发布的离线Web应用。使用这种方案,用户可以通过手机浏览器访问Web应用然后将它安装到手机上,下一次可以通过同样的URL或者应用图标来访问这个应用时,应用将不再从服务器端加载,而是直接从本地启动。
1.定义软件包
需要使用HTML5的一个API,叫做Application Cache,应用程序缓存,也成为离线API。
软件包其实是一组文件,是用户访问应用站点时必须由浏览器下载到本地的文件。
2.HTML清单
软件包内的文件是根据一个被称为缓存清单(cache manifest)的文本文件来发布的。清单文件的第一行必须是CACHE MANIFEST,随后是所有需要被下载到设备上的资源的URL列表,URL可以是相对路径或者绝对路径。
样例:
CACHE MANIFEST:
# jQuery core
http://code.jquery.com/jquery-1.6.1.min.js
# jQuery Mobile files without custom theme
http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css
http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js
http://code.jquery.com/mobile/1.0/images/ajax-loader.png
http://code.jquery.com/mobile/1.0/images/icons-18-black.png
http://code.jquery.com/mobile/1.0/images/icons-18-white.png
http://code.jquery.com/mobile/1.0/images/icons-36-black.png
http://code.jquery.com/mobile/1.0/images/icons-36-white.png
# My app files, relative to the HTML document
images/logo.png
data/countries.json
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
清单文件的名称通常叫offline.appcache,并且只有以text/cache-manifest的MIME类型提供给客户端才有效。
如果支持PHP,那么只需要把文件的扩展名改为.php,然后使用下面这个模板,不需要其他特殊配置就可以生效了:
<?php header('Content-Type: text/cache-manifest');
?>CACHE MANIFEST:
- 1
- 2
下一步需要在HTML文件中定义清单文件的URL,通过设置HTML元素的manifest属性来完成的:
<html manifest="offline.appcache">
<-- 应用正文 -->
</html>
- 1
- 2
- 3
3.下载应用
支持应用缓存的浏览器找到清单说明后,就会在后台下载清单文件。后台的下载进程和正常的页面加载是完全分开的。下载进程会把清单里面的每一个文件都下载下来,保存在设备上一个只有它能访问的地方。
只要有一个资源没有下载成功,那么整个软件包都将无效,所有的资源都不会被保存在本地。
4.访问在线资源
CACHE MANIFEST:
# jQuery core
http://code.jquery.com/jquery-1.6.1.min.js
# jQuery Mobile files without custom theme
http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css
http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js
http://code.jquery.com/mobile/1.0/images/ajax-loader.png
http://code.jquery.com/mobile/1.0/images/icons-18-black.png
http://code.jquery.com/mobile/1.0/images/icons-18-white.png
http://code.jquery.com/mobile/1.0/images/icons-36-black.png
http://code.jquery.com/mobile/1.0/images/icons-36-white.png
# My app files, relative to the HTML document
images/logo.png
# Resources that should be downloaded from the web
NETWORK:
data/countries.json
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
countries.json每次都不会下载到本地,而是每次都从服务器端获取。如果没有联网,这个文件就访问不到了。
NETWORK段落支持通配符*或者文件夹的资源描述文件。
如果所有资源都在网络上获取,可以使用以下方式:
NETWORK:
*
- 1
- 2
5.更新资源
因文件需要更新而修改清单的方式包括增加空格、修改资源的名字(加上版本信息),甚至是增加一些注释,包含一个随机数或者最后修改时间。
比如:
CACHE MANIFEST
# webapp updated 2012-01-01
- 1
- 2
只要有一个字节改变,旧的清单就会失效,浏览器就会重新下载所有的文件(不支持单个文件下载),然后刷新2次后生效。
6.JavaScript对象
有一个全局变量applicationCache可以帮助我们了解应用缓存的状态。
先检查applicationCache对象是否可用:
if (window.applicationCache!=undefined) {
// The API is available
}
- 1
- 2
- 3
查询当前状态:
if (window.applicationCache!=undefined) {
// The API is available
if (applicationCache.status==applicationCache.UPDATEREADY) {
// There is an update waiting for reload
}
}
- 1
- 2
- 3
- 4
- 5
- 6
0:UNCACHED:页面第一次加载,或者没有可用的清单文件
1:IDLE:缓存闲置1
2:CHECKING:本地清单文件正在比对服务器端的清单文件进行检查
3:DOWNLOADING:资源下载中或者升级
4:UPDATEREADY:有更新已经被下载,但要到下一次加载时才生效
applicationCache事件:
checking:浏览器正在检查清单文件
downloading:浏览器开始下载清单文件上的资源
progress:其中一个资源下载完毕(可以根据这个下载进度条)
cached:第一次下载已经顺利完成
noupdate:和服务器端清单文件比较后发现没有可用的更新
updateready:存在可用的更新,并且新的资源文件已经下载完毕,重新加载后生效
error:下载资源过程中出现错误
obsolete:检查更新后,本地清单文件失效,web应用从本次存储中删除,下一次不再进行离线访问
可以使用addEventListener方法来进行事件绑定:
if (window.applicationCache!=undefined) {
// The API is available
applicationCache.addEventListener('updateready', function() {
// There is an update waiting for reload
if (confirm("There is an update ready. Do you want to load it now?")) {
history.reload();
}
});
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
安装应用图标:
应用下载完毕后,可以引导用户将应用图标添加到主屏幕或者应用菜单上。
图标快捷方式名一般是HTML页面的title元素的值,所以有必要保持title的简洁(1、2个词)来适应屏幕的大小。
图标的大小问题见下面的实例
全屏
只在IOS平台上有效,且用户必须从主屏幕上启动应用程序。HTML页面上定义以下meta标签:
<meta name="apple-mobile-web-app-capable"
content="yes">
- 1
- 2
全屏检测
ios平台,通过navigator.standalone属性强制应用在全屏下进行安装和使用。以下代码放到mobileinit中即可。
if (navigator.standalone!=undefined) {
// It's iOS
if (!navigator.standalone) {
// It's in Safari
$.mobile.changePage($("#install"), {transition: "none"});
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
修饰Web应用
更改(屏幕顶部)手机的状态栏的颜色:
<meta name="apple-mobile-web-app-status-bar-style" content="black">
- 1
content:default(灰色)、black、black-translucent(透明的黑色区域,一般不用)
启动图片:
<link rel="apple-touch-startup-image" href="images/launch.png">
- 1
更合适的用法是自适应:
<link rel="apple-touch-startup-image" href="images/launch-iphone.png"
media="(max-device-width: 480px)">
<link rel="apple-touch-startup-image" href="images/launch-iPad-p.png"
media="screen and (min-device-width: 481px) and (max-device-width: 1024px)
and (orientation:portrait)">
<link rel="apple-touch-startup-image" href="images/launch-iPad-l.png"
media="screen and (min-device-width: 481px) and (max-device-width: 1024px)
and (orientation:landscape)">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
一个完整的例子:
一个提供离线访问,并且定义了快捷方式图标和全屏配置的JQM Web应用的模板如下:
<!DOCTYPE HTML>
<-- 包括应用程序离线缓存定义的HTML -->
<html manifest="offline.appcache">
<head>
<meta charset="UTF-8">
<title>short title</title>
<meta name="viewport" content="width=device-width,user-scalable=no">
<-- 使用自定义主题的JQM文件 -->
<link rel="stylesheet"
href="http://code.jquery.com/mobile/1.0/jquery.mobile.structure-1.0.min.css" />
<link rel="stylesheet" href="custom_theme.css">
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js">
</script>
<-- 应用图标Icons -->
<link rel="icon" href="icons/icon32.png">
<link rel="shortcut icon" href="icons/icon32.png">
<link rel="apple-touch-icon" href="icons/icon57.png" sizes="57x57">
<link rel="apple-touch-icon" href="icons/icon114.png" sizes="114x114">
<link rel="apple-touch-icon" href="icons/icon72.png" sizes="72x72">
<link rel="apple-touch-icon" sizes="80x80" href="icons/icon80.png">
<link rel="apple-touch-icon-precomposed" sizes="android-only" href="icons/icon57.png">
<-- 如果需要全屏显示 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-startup-image" href="images/launch-iphone.png"
media="(max-device-width: 480px)">
<link rel="apple-touch-startup-image" href="images/launch-iPad-p.png"
media="screen and (min-device-width: 481px) and (max-device-width: 1024px)
and (orientation:portrait)">
<link rel="apple-touch-startup-image" href="images/launch-iPad-l.png"
media="screen and (min-device-width: 481px) and (max-device-width: 1024px)
and (orientation:landscape)">
</head>
<body>
<!-- jQuery Mobile's pages -->
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
存储离线数据
使用Web Storage API。它兼容性好,支持localStorage和sessionStorage这两个基于键值对进行存储的集合。
localStorage是一个在设备上持久存储的字符串集合,sessionStorage也差不多,只是每次浏览器关闭后它会被清空。
localStorage可以存储:JSON、JS、CSS、HTML、转化为base64字符串的图片。
操作localStorage的方法是:getItem和setItem。
//保存数据
localStorage.setItem("name", "value");
//获取数据
var value = localStorage.getItem("name");
- 1
- 2
- 3
- 4
- ').addClass('pre-numbering').hide(); (this).addClass(′has−numbering′).parent().append( numbering); for (i = 1; i