drawable—hdpi 高分辨率、
drawable—mdpi 中辨率、
drawable—ldpi 低分辨率、
drawable—xhdpi 超高分辨率
如果图片放置不对,那么可能导致图片过大、过小以及模糊问题
写开发文档时要用到数据库开发的表结构,在网上找到了一段sql语句,经测试完全符合我的需求,不敢独享,语句如下:
select * from (
SELECT t1.Table_Name AS "表名称",
t3.comments AS "表说明",
t1.Column_Name AS "字段名称",
t1.Data_Type AS "数据类型",
t1.Data_Length AS "长度",
t1.NullAble AS "是否为空",
t2.Comments AS "字段说明",
t1.Data_Default "默认值"
FROM cols t1 left join user_col_comments t2
on t1.Table_name=t2.Table_name and t1.Column_Name=t2.Column_Name
left join user_tab_comments t3
on t1.Table_name=t3.Table_name
WHERE NOT EXISTS ( SELECT t4.Object_Name FROM User_objects t4
WHERE t4.Object_Type='TABLE'
AND t4.Temporary='Y'
AND t4.Object_Name=t1.Table_Name )
ORDER BY t1.Table_Name, t1.Column_ID
)k where k."表名称" = 'LBSP_EC_REMAPP';
查询完成后,导出htm格式,在复制黏贴到word,搞定!
纯 web 模式的局限性
在 Worklight 架构下,纯 web 模式虽然可以像本地应用一样被安装在手机上,但是所提供的服务和传统的网页相比,几乎没有任何的区别,并且因为在分辨率和性能上与台式机相比有明显的差距,所以整体的体验相对于台式机会逊色不少。那么 web 模式应该如何扩展才能体现作为手机应用的优势呢?首先在完成基本的网页显示内容的情况下,需要能够扩展功能,使之可以调用手机本地的功能,诸如相机、定位系统、电话本等等;其次不但可以调用手机的本地功能,当手机和外接设备联系时,还能调用外接设备,比如条形码的检测;最后不同的手机操作系统在实现相同功能时因为策略的不同可能带来不同的效果,比如在打开网页的 PDF 文件上,iPhone 采用直接显示的策略,但是 Android 采取下载的策略,统一的解决这些问题,并且提供良好的提示机制也是手机客户端开发需要考虑的问题。以上这些方向都可以改善纯 web 模式的客户体验,提高手机应用的适用范围。
基于上面的描述,Worklight 中引入了一个定义,称之为混合同化模式(hybrid app mix)。在标准的网页程序中 JavaScript 语言只是负责对页面的元素进行操作,修改网页的树状结构。在 Worklight 混合模式的定义中,又可以按照使用技术的不同分为两类:web 模式下基于 Worklight 客户端 API 的 JavaScript 函数负责从远程的服务器中获得信息,以及同各种不同的后端数据库交互,进行诸如身份验证、数据读取等工作;在 mix 模式下,应用中的 JavaScript 不但可以从事前面的所有工作,还能通过它调用本地的 Java 或者 Object-C 代码,从而完成网页和本地功能的交互工作。在目前提供的技术中,开发者可以使用三种方式来完成这项工作:第一、通过 Worklight 中的 API,调用本地的页面,从而实现本地页面支持的 Java 或者 Object-C 方法,实现对本地功能的调用;第二、使用开源的 Cordova(也就是原有的 PhoneGap)框架,调用已经集成完毕的本地功能;第三、调用或者开发 Cordova 的插件,按照 Cordova 规定的模板,用户可以自行集成本地代码和 JavaScript 文件到 Cordova 框架中,用于调用本地功能。
本文将逐一介绍这三种方式,并且分析各自的利弊。但是需要指出的是,基于 Worklight 进行本地功能的开发,只能对客户端应用起到一定的辅助作用,如果大量的使用自行编辑的本地代码,不但丧失了原来的优势(利用 web 技术提高了开发的效率),反而会因为调用层次的增加带来运行效率低下的问题。所以在开发本地功能时,需要权衡利弊,作出适当的选择。
Worklight 提供的模式
在 Worklight 的客户端 API 中,有一个函数可以调用本地已经编写好的页面,通过它可以方便的在不同页面间(网页和本地页面)进行数据的交换。它的函数形式如清单 1 所示:
清单 1. WL.NativePage.show 函数
WL.NativePage.show(className, callback, data)
函数一共包括三个参数,其定义如下
- className:是一个字符串值,它代表本地类的名称;不过在不同系统中略有差别,在 iOS 系统中它是类的名称,在 Android 系统中它是类的完整名称(包括 package 的值)。从这个参数不难看出,函数会使用类似反射的机制来实现对象的调用。
- callback:是一个函数对象,当本地页面调用完成后,需要返回到网页中进行后续的处理,这个回调函数的作用就在于此。函数的参数是一个 JSON 对象,用于存放本地页面返回的数据。在不同的操作系统中返回数据的方法不同,可以查看表 1 获得信息。
- data:一个 JSON 对象,用于将网页上的参数传递给本地页面进行处理。但是在不同系统中参数的类型受到一定的限制,在 iOS 系统中数据必须是字符串类型,在 Android 系统中数据可以是各种基本类型或者它们的数组形式。在不同的系统中如何读取相应的数据,可以查看表 1 获得信息。
表 1. 不同客户端比较
Worklight 提供的方法虽然比较灵活,但是需要进行的编码工作比较多。比如需要定义相应的本地类,定义相互的数据接口,并且进行测试,这些工作会延长产品的开发周期,也容易引入错误,从而引起产品的不稳定。如果可以直接调用第三方的开源库,这样就可以减少本地功能的开发周期,并且获得稳定的代码表现和良好的代码维护。Cordova 作为 PhoneGap 的后续开源框架就提供了相应的功能。
Cordova 支持的功能
Worklight 本身集成了 Cordova 的相应功能,在使用时需要注意的问题是,系统本身集成了 Cordova 的 1.6.1 版本,所以参考相应的 API 文档说明时,需要确定具体的版本。
Cordova 支持的功能可以分为十三类,对于常用的手机功能均有涉及,
- Accelerometer:通过手机的加速度机,获取手机在三个轴上相应的加速度和速度,用于监听用户的一些手势操作。这个功能主要用于游戏功能的开发,在企业级的应用中使用较少。
- Camera:获取照相设备,并且在拍摄完成后取得拍摄的内容。这个功能在企业级应用上有很大作用,比如企业开发的人事和报销系统,可以让员工用来拍摄自己的照片和出差时候的发票,并且在手机上完成后续流程的操作。
- Capture:可以获取手机中的视频、音频等设备,进行录制拍摄等工作。这个功能在企业级应用中可以用来完成录制声音,递交口头报告等工作。
- Compass:指南针信息,在企业级应用中使用很少。
- Connection:通过判定用户手机和网络的连接情况,应用可以调用不同的方案代码来实现功能的优化。如果企业级应用对网络安全有要求的情况下,可以通过判定不同网络的连接情况,开启和关闭应用的一些功能。
- Contacts:本地通讯录是企业级应用中一个重要的内容。用户可以通过相关函数将网页上的内容备份到本地的联系人列表中,同时也可以将本地联系人内容上传到企业的网络上,这样可以方便企业内部管理员工的信息。
- Device:可以获取手机的基本信息,作为一种常规的功能,可以在应用中对不同环境进行代码优化。
- Events:用于监听用户的不同操作事件。这些函数主要作用是使用手机的一些本地按键,让程序更像是一个本地应用,比如 Android 中的回退按键可以让菜单返回上级,但是网页操作对这个按键的响应是退出应用,通过对用户的返回按键进行监听,在 web 模式下的网页程序也可以利用回退按键实现页面的返回,这样让 web 应用更符合用户的使用习惯。
- File:在企业级应用中,企业可能有些公开的规章制度供用户查看,或者规定的表格需要员工填写。通过相应的方法,可以下载和上传内容,便于在手机端完成企业定义的工作流程。
- Geolocation:GPS 信息对于企业级应用的重要作用在于确认重要资源的位置。比如运输公司可以通过 GPS 信息获取运输工具的具体位置和历史位置,从而判定运输工具的运行情况。对于公司的报销系统,GPS 信息也是很重要的,可以通过相应信息的比对,确认员工出差时的历史位置信息。
- Media:可以查看网上的视频信息,这只是一个支持类,用于编写代码时的方便和接口的统一。
- Notification:利用手机本身的功能,可以将应用中的提醒发到手机端。比如在企业应用中会提醒员工重要的会议即将开始,或者项目的截止日期等等,利用通知机制,可以帮助员工良好的完成企业布置的任务。
- Storage:将信息存在手机端的数据库中,可以用于存放用户的偏好设置,或者将一些只读内容放在客户端,便于用户在不连通网络的情况下,仍然可以访问相关的内容。比如在企业应用中,相应的条理,规章制度等就属于这种情况。
从 Cordova 提供的内容看,对于普通的需求(企业级和非企业级),此框架均有良好的支持,开发者可以通过这个框架,完成系统要求的各种内容而不开发本地代码。
但是,Cordova 框架的内容毕竟有限,对于各种不同的客户端,框架不可能满足全部的要求。所以按照 Cordova 创建通用功能的方法,开发者可以自己创建 Cordova 插件,也可以在开源库中寻找其他开发者开发的插件系统,完成各种跨平台的本地功能。
Cordova 的插件系统
Cordova 框架从本质上说就是利用网页上的 JavaScript 语言调用本地的代码,只要符合架构的模板,很多的本地功能都可以被网页调用,而不需要使用本地页面。Cordova 的插件系统由以下几部分组成:
- 本地代码:开发者需要最终实现的本地内容,在不同的操作系统上有不同的要求(比如继承固定的类或者接口,实现固定的方法)
- 配置文件:本地代码开发完毕后,还需要将相应的配置内容放到配置文件上,这样框架才可以发现新插件的加入
- 定义和注册代码:当新的插件添加到配置文件后,系统需要添加 JavaScript 代码来确定这个插件的调用形式,同时将这个插件添加到 Cordova 的插件列表中,这些内容都需要在 JavaScript 文件中完成
- 调用代码:开发者根据规定的格式调用插件,输入相应的调用参数,获得成功返回的数据或者相应的错误信息
从上面的描述可以看到,Cordova 插件机制增加了整个框架的灵活性。其实,Cordova 本身提供的十三项功能也是利用插件形式完成的。在这种架构下,框架的扩展性相当强,耦合度也很低,是一种良好的开发模式。
在日常的开发中,Cordova 提供的一些功能已经有官方网站的详细介绍,本文的余下内容将着重演示其余两种方式:通过 Worklight 提供的模式调用本地功能,以及通过 Cordova 插件的方式调用本地功能。
实例和分析
本文使用的实例测试环境如下:Windows XP 系统,Worklight 插件版本 5.0.3,IDE 版本为 Eclipse Indigo,Android 版本为 2.2 及以上。应用将首先利用 Worklight 提供的模式完成数据在网页和本地页面之间的交互。然后利用 Cordova 的插件直接获取本地代码的值显示在网页上。
第一个应用的流程如下:用户在网页中输入字符串信息,传递给本地页面;本地页面显示信息,并且让用户输入反馈信息,用户点击确认后,返回到网页,在网页中显示输入的反馈信息。本地代码的关键内容如清单 2 所示:
清单 2. 本地页面代码
public class ExampleNative extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // get content String value = getIntent().getStringExtra("keyName"); // return content String rvalue = "the content returned"; Intent rIntent = new Intent(); rIntent.putExtra("rvalue", rvalue); setResult(RESULT_OK, rIntent); finish(); } }
从源代码中可以看到,源文件需要继承 Activity 类(关于 Activity 类的说明,可以查看 链接),并且通过 get 方法获得由网页传输过来的内容。在 Android 系统中,Intent 类是一个容器,可以将需要传递的数据按照键值对的方式放入其中,然后在 setResult 时将 Intent 作为参数放入,再调用 finish 后就可以将数据传递给其他页面了。在实例中本地的数据就是通过这种方式返回到网页的。完成源代码后,需要在 AndroidManifest 文件中添加配置信息,只有这样系统才能访问到相应的类文件。内容如清单 3 所示:
清单 3. 配置文件内容
<application android:label="@string/app_name" android:icon="@drawable/icon" > <activity android:name="wang.test.ExampleNative" />
完成了本地代码之后,网页端的代码按照如下方式完成:页面的内容在 common 文件夹下完成,然后在 common 和 environment(例如 android,iPhone 等)的 js 文件夹下实现相同的 JavaScript 方法,不同的是 common 环境下将直接显示提示信息,environment 环境下将实现具体的功能。相应的代码如清单 4 所示:
清单 4. common 和 environment 代码内容
common 代码 function openNative () { alert('Don't support on web page'); } Environment 代码 function openNative () { var params = {keyName : $('#field').val()}; WL.NativePage.show('wang.test.ExampleNative', callback, params); }
从代码中可以看到,调用的方式十分直接,并且不管在什么环境下,用户总能得到一定的提示信息。在 environment 下,回调函数完成的功能也很简单,就是将从本地代码中获取的数据显示在 alert 框中。具体的代码如清单 5 所示:
清单 5. 回调函数
function callback(data) { alert("Received value is: " + data.rvalue); }
这样 Worklight 提供的对本地功能的访问模式就完成了,不过从实质上讲它的调用是基于本地页面的,如果应用只是希望获得本地的数据(比如联系人的电话),这种实现方式就显得拖沓。
Cordova 插件的方法与上面不同之处就在于,系统可以直接调用具体的本地方法,直接获取需要的数据,这样就不需要相应的本地页面了。在接下来的示例中应用将实现 Cordova 插件的开发,具体的流程是根据用户输入的名称信息,返回相应的欢迎信息。根据插件系统的介绍,首先要完成一个本地代码,代码的内容如清单 6 所示:
清单 6. 插件本地代码
public class ExamplePlugin extends Plugin { @Override public PluginResult execute(String action, JSONArray arguments, String callbackId) { PluginResult result = null; if (action.equals("test")){ String rText = "Input content is: "; try { rText+= ", " + arguments.getString(0); result = new PluginResult(PluginResult.Status.OK, rText); } catch (JSONException e) { // .... } } else { result = new PluginResult(PluginResult.Status.INVALID_ACTION); } return result; } }
从代码中可以看到,插件代码需要继承的是一个 Plugin 类,并且实现相应的 execute 方法。在方法中三个参数分别是:执行的动作名称(action)、动作的参数数组(arguments)和回调函数的 ID(在 JavaScript 中使用)。系统通过 action 的名称和传入参数完成一个 PluginResult 的构建,最后将该结果返回给调用网页。
配置文件的位置是 res 下的一个 plugins.xml 文件(相应的内容可以查看 Phonegap 的 开始文档),清单 7 就是 XML 文件修改后的内容:
清单 7. 插件配置信息
<plugin name="ExamplePlugin" value="wang.test.ExamplePlugin" /> </plugins>
在网页端调用插件时,需要完成三个函数:插件 JavaScript 类的创建,插件的注册以及插件的调用。具体的内容如清单 8 所示:
清单 8. 插件调用代码
function ExamplePlugin(){ } ExamplePlugin.prototype.test = function(onTestSuccess, onTestFailure, para){ cordova.exec(onTestSucc, onTestFail, "ExamplePlugin", "test", [para]); }; cordova.addConstructor(function() { cordova.addPlugin("examplePlugin", new ExamplePlugin()); }); function callPlugin(){ window.plugins.examplePlugin.test(testSuccess, testFailure, "parameter"); }
从代码中可以看到,JavaScript 先初始化了一个对象,然后实现了它的 test 函数。在 Cordova 支持的插件调用函数中定义了五个参数,分别是:成功回调函数,失败回调函数,调用的类和动作,以及传入的参数。通过 Cordova 提供的函数将插件放入 Cordova 中,被上层函数调用时只需要调用事先定义的原型(prototype)函数就可。
三种方式比较
在完成了页面集成和插件编写后,需要分析一下这三种模式,在企业级应用中的取舍。从使用的稳定度和难易度来看,使用 Cordova 是最好的,它不但有完整的说明文档和详细的例子,并且框架的版本不断更新,可以期望有更好的功能加入。相应的插件也是一个不错的选择,虽然自己编写插件需要一定的本地代码知识,但是开源网站上的公开插件使得开发者可以先寻找合适的插件,再考虑自己编写的问题,这样就可以获得和 Cordova 原始版本类似的体验。
Worklight 提供的方式虽然灵活,但是需要很多的本地代码知识,而且必须借助一个本地页面进行操作,这样就大大降低了模式的适用性,而且手机端操作,用户总是希望操作的步骤要尽量简单,强制加入的本地页面使得用户的操作步骤增加了,减少了应用的友好性。
在比较插件模式和 Worklight 模式时,两者的最大区别在于后者需要自行创建的一个本地页面。所以 Worklight 模式可能用到的地方就是必须需要本地页面的环境下:比如用 3D 函数来呈现绚丽的页面,编辑拍摄的照片和设置音频视频等等,这些功能在企业级应用中情况较少。所以,在企业级应用开发中参考的方案应该按照如下排列:首先考虑 Cordova 框架和一些开源的 Cordova 插件,然后再考虑自行编制 Cordova 插件,当上面的方式均不行时最后才考虑 Worklight 的模式。
结束语
提供良好的本地功能是开发专业的企业级手机应用的有效手段,好的应用不但应该可以查看企业的各种信息,还应该允许用户进行丰富的操作,完成企业规定的流程。对于适应各种可能存在的需求,本地功能开发提供了良好的帮助。但是需要注意的是,本地功能不能成为 web 模式手机应用开发的主要形式,如果应用中需要大量用到本地代码,应该重新考虑设计方案,直接使用本地代码来完成应用系统。
熟悉 Cordova 的架构,并且了解在开源框架中成熟的插件产品,这样才能在有需求时减少本地代码的开发量,保持利用 web 模式开发手机应用的较高效率。