HTML5桌面应用开发手册

概述

HTML5桌面应用是指程序多数逻辑都交由页面处理,并大量运用HTML5技术,将页面跑在CEF容器里的一类产品。程序分为两部分,一部分是页面程序,一部分是封装CEF的定制化的浏览器,由于定制的浏览器高度桌面化,用户不会觉得使用的是一个浏览器。本手册将阐述如何快速新建一个产品,如何调试产品,如何发布产品,如何更新产品等及以目前native所提供的API,在页面开发中常用的机制解释。

此框架主要适用于web页面桌面化,通过调用web服务器上的接口,把程序的数据加载到程序上,并呈现给用户的这类产品,一般展示类的产品都可以适用这套框架开发,如果是图形化要求,客户端游戏类的产品不适合应用此框架。

使用此框架开发的产品,在发布后,页面文件均打包在本地的pacakge目录内的两个ntpk文件,分别为orca.ntpk与xxx.ntpk(xxx.ntpk名称由可执行文件定义,稍后详述),我们的主要开发内容即为构建这两个ntpk。

页面端程序

引导产品

native第一个加载的文件是app_init.html,这个页面里有app_init.js的引入,此文件是程序的入口,在脚本里做一些如程序托盘图标,右键菜单等逻辑处理,如果是开机启动会把参数传到这个页面的url里方便做相关开机启动的逻辑,最后通过location.href=’xxx’,引入到产品的页面中。程序第一个进入的是这个页面是为了做一些程序初使化的工作,和前端的页面逻辑没有多大关系,如果不需要有这一个初使化的页面,可以直接加载进入程序的初使页,在初使页里做些app_init.js做的一些相关工作。 在由引导页进入程序的主要界面后,就正式进入页面定制出来的界面,开发人员可以按需求,以页面形式展示窗体,用以脚本编写各种逻辑功能,在这里和一般的网页开发是类似。 需要注意的是,在页面脚本的第一部分逻辑是用来调整窗体的大小,位置,添加最大化,最小化,关闭等桌面应用的通用特性,如果窗体可以缩放,要按native提供的接口改变窗体的大小,和窗体的移动也是如此,在鼠标mousedown时触发native提供的窗体移动接口。

img

前端文件

项目的前端文件可以放置在任何的文件夹里,只要在app_init.js引导进入项目时能正确找到就可以,如我们是如些放置前端文件:

url = 'orca://mailease/html/win7/login.html'

Native可以用orca://这么一个协议指定到程序的文件夹,再去该文件夹里找前端的页面文件。为了开发便利,再加上前端开发和native程序是分开放置,所以在开发环境下,需要指定ntpk包的path(通过xxx-package-dir参数,下详),传给native端, native便可以通过上面的地址找到相对应的页面。ntpk包可以由工具生成,文件夹先打成zip文件,再能工具生成ntpk包。 在发布情况下由于页面都打包成了ntpk文件,因此就不需要指定path。

页面窗体

用此种方式开发出来的产品,每一个窗体都是一张页面,如果是同一窗体里要改成另外一个窗体,用js修改location.href,就可以跳转到那个需要的页面上,这样以实现窗体UI变换。 窗体的通用功能: 窗体最小化, 窗体最大化, 窗体restore, 窗体关闭, 窗体移动, 窗体拖动边缘缩放窗体, 窗体是否需要隐藏, 窗体是否需要在任务栏显示, 窗体的最小尺寸 以上是一个窗体在桌面应用中所具有的基本属性,这些接口都是由native提供接口支持。在页面打开时,都需要对上面的基本动作属性进行处理。在做完窗体的基本属性设置完后,开始对页面上具体功能进行逻辑处理,这里的处理和我们一般的前端开发类似,如果需要native提供接口来处理一些js无法完成的工作时,就由native开出新的接口供js调用。

Native端exe程序

由于各个项目的需求并不相同,因此exe程序需要定制(比如exe图标会不同),以新版邮箱助手为例,说明其定制过程。 framework.dll开放了几个接口(均为C接口),用来实现这样的定制: OrcaInitialize() –> 初始化。 其接受一个参数,类型为 OrcaSetting* , OrcaSetting的定义如下(详情可查看external.h):

typedef struct _OrcaSetting
{
    /*OrcaSetting大小*/     size_t size;
    /*UserAgent字符串*/     char* user_agent;
    /*页面cache的路径*/     wchar_t* cache_path;
    /*LocalStorage路径*/    wchar_t* local_storage_path;
    /*存放log文件的目录名*/ wchar_t* log_file_dir; /*log名称为“exe名称.exe”*/
    /*首先加载的页面url*/   char* init_page_url;
    /*自定义的域名数组*/    char** custom_domain;
    /*自定义的域名元素个数*/unsigned int custom_domain_count;
}OrcaSetting;

OrcaRun() --> 开始运行

下面是个简单的例子。

img

页面调试产品

调试工具是chrome developer tools,这个调试工具和chrome浏览器里的developer tools是一样的,只要我们在开发的时候调用出来就可以了,邮箱助手在开发环境下是用一个脚本来启动程序,在启动的时候把参数传进去,就可以在启动程序后用f12调出 developer tools

set objShell=wscript.createObject("WScript.Shell")
path=left(Wscript.ScriptFullName,len(Wscript.ScriptFullName)-len(Wscript.ScriptName))
orcaPath = path & "orca"
maileasePath = path & "..\..\webapp"
param = "--orca-startup=auto --enable-memory-trace --memory-trace-elapse --force-show-window --enable-dev-tools --enable-invoke-trace --orca-package-dir=" & orcaPath & " --mailease-package-dir=" & maileasePath
iR = objShell.Run(Path & "mailease.exe " & param,0,TRUE)

以上是在开发环境下启动程序的脚本,param传入的参数是 --enable-dev-tools --enable-invoke-trace --orca-package-dir --mailease-package-dir 可以具体看一下native当前所支持的参数启动

enable-dev-tools可以通过F12开关开发者工具
enable-invoke-trace将js调用native接口的信息打印到mailease.log中
enable-memory-trace将内存的使用情况输出到memory.log中
force-show-window在创建窗口时强制显示其窗口,便于调试那些起始时即隐藏的页面
memory-trace-elapseenable-memory-trace开启时才有效,决定内存跟踪log的刷新时间,单位毫秒,默认为1000
force-aero-style--force-aero-style=on表示强制使用aero风格的ui,--force-aero-style=off表示强制不使用aero风格的ui,为其他值或者此值不指定表示根据系统情况探测
XXX-package-dir指定加载未打包的页面文件(XXX为package的名称),如指定 --maileas-package-dir=c:\to\svn\path\webapp,则所有的mailease包内的文件均从c:\to\svn\path\webapp文件夹内加载
orca-debug-on-startup程序启动时即请求调试器调试之,与orca-wait-for-debugger-time配对使用
orca-wait-for-debugger-timeorca-debug-on-startup开启时有效,指定程序等待调试器的时间,单位为秒,如果不指此项,默认为60秒,与orca-debug-on-startup配对使用
enable-dev-tools可以通过F12开关开发者工具
enable-invoke-trace将js调用native接口的信息打印到debug.log中
erase-shadow-frame去掉阴影边框,以防止阴影效果对某些显示起到干扰效果

这些参数都有合理的应用场景,比如当不确定是页面问题还是native程序有bug时,便可以打开enbale-invoke-trace来将js调用native接口的详细log打印出来,之后查看log便可以方便的确定问题的范围。 在开发环境下用脚本启动时传入上面的这些参数,都会对native响应某个特性,如果用不脚本启动,在开发环境下要启动时带上这些参数也是会响应这些功能。 在developer tools里支持f5刷新页面,在开发时,发现bug,修复完bug,验证bug是否修复完整,可以在开启developer tools的情况下,用f5刷新页面,以避免重新启动程序验证bug是否修复完整。

产品发布

前端部分的发布

  • 前端采用的是NEJ框架,只需简单配置,就可以生成压缩,混淆后的代码,并导出到指定的发布文件夹。
  • 修改页面版本号,并将其打包成ntpk文件

Native部分的发布

将可执行文件、framework.dll、locales、chrome.pak、ntpk文件打包成安装包,便可以发布了。

更新策略

这套框架所支持的更新分为两部分(前端页面包更新与native程序更新),每部分的更新都是由页面触发完成的,以新版邮箱助手的Native更新为例,简要说明其更新过程: img

如图所示,整个更新流程为页面驱动,框架为更新提供支持。这些支持包括以下几个接口。

  • app.newUpdatePackage(name),生成此次更新所需的升级文件,其会位于安装目录下的update文件夹内
  • package.append(content),向升级文件中添加内容,这些内容多半是由页面端从服务器端获得
  • app.updateWhenRestart(name),告知框架在下次启动的时候将native更新
  • app.updateNtpksWhenRestart(ntpksname),告知框架在下次启动的时候将ntpk包(也就是页面包)更新。

注意,最后两个接口是根据实际需求选择一个进行更新的。

前端更新

当页面通知native下次启动时更新ntpk包时,native会将这些信息记录在update/orca_update_ntpk_flag文件内,于是在下次启动的时候native便会将这些页面包替换掉。

前端更新策略是产品启动时,通过native当前产品的版本号取出,通过ajax询问服务器上有没有更新包产生,如果有把服务器的包下载过来,下载成功后通知native下次启动时用更新后的包。前端部分成两个部分,一个是app_init.html引导程序进入的部分和项目主体部分。因此分为两个包更新前端的程序,一个是xxx1.ntpk主包,一个是xxx2.ntpk副包。xxx1.ntpk包是页面程序包,xxx2.ntpk包是引导入进程序的那部分页面包。

Native更新

当页面通知native下次启动更新整个程序时,native会将此信息记录在update/orca_update_flag文件内,于是在下次启动的时候native会启动native更新程序,完成更新。

升级策略

由于每个产品的需求不一样,因此升级策略需要自己定制,不过版本号的获取倒是可以借助于另外两个接口来完成,分别为

  • app.version, 获取native版本号
  • app.getNtpkVersion(ntpkname),获取ntpk版本号

app.version获取到的版本号是一个标准的四元版本号,即major.minor.build.revision,其中build.revision是编译时即确定的,而major.minor 是从安装目录下的version.dat文件获取。

Native端API

现有API调用

在API文档里有详细的对现有的API的阐述,在native提供的壳上运行脚本都能顺利调到。

### API扩展 由于每个产品都会有各自特殊的需求,要对现在的API上进行扩展,此处的扩展实际上是编写标准的npapi插件,做好后放到安装目录的plugins文件夹内即可。 编写npapi插件的请参看 https://developer.mozilla.org/en/Gecko_Plugin_API_Reference

常用页面机制

窗体的信息同步

窗体间的信息同步,主要是由localStorage的storage方法完成同步的事件触发。如果页面A上的消息需要传递给页面B上,在A的localStorage里设置一个键值对,B页面上的storage事件,可以监听到localStorage的值的改变,如果监听到的key需要处理的,就可以在B页面上做下应的处理。需要注意的是,在同一个页面上storage事件并不会触发,只会对不同url地址的页面才能触发storage事件。

页面布局

桌面产品的UI上一般都可以拖动周边,使窗口进行缩放,窗体上的某几个条是不会改变位置,如底部的按钮,顶部的工具条等,在这种情况下,我们可以对中间的那一快用绝对定位的方式进行定位,其他的几块都用绝对定位,这样放窗体缩放时,这几块的结构都会在窗体之内,不会有滚动条等,在桌面窗体一般缩放窗体不希望有滚动条出现。

img

localStorage

将用户的数据保存在localStorage,在删除用户时,需要将相应用户的数据删除,使localStorage尽量保存有用数据。由于窗体的很多用户数据是会有共享的,所以放在localStorage避免了有额外的数据请求,新开的窗体直接从localStorage里取就可以。

缩放窗体

绝对定位8个div元素,div的高度为3像素,并按z-index把他们的层级提高,他们的cursor做成相应的表现,在这些元素上mousedown时做对应元素的行为,调用native提供的接口,以做到窗提能随鼠标拖动。

img

多个用户的情况下,需要切换在发送请求前切换cookie,使请求能通过服务器验证,获取请求数据。Cookie的切换是通过native提供的接口,删除(browser.removeCookie())和设置(browser.setCookie())接口,在删除前要把cookie保存起来,下次还会用到这个数据,跨域设置cookie也是需要由native提供的接口完成这个操作。

窗体透明

Win7下桌面应用有一个aero的模式,为了桌面应用有这样的一种效果,可以把页面的body的背景色去掉,在body上的需要透明的节点设一个opacity,就可以透过应用看到应用后面的效果。

img

Tutorial

基本的要点均已提及,示例代码可以参照 orca_sample.7z,在调试时需要添加参数,指定到初使化的html页面

img

© 1997-2013 Netease. All Rights Reserved.
comments powered by Disqus