浏览 3996 次
锁定老帖子 主题:MIDlet生命周期
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-12-23
最后修改:2010-01-26
AMS使用如下生命周期方法来控制MIDlet的状态: Ø 默认构造器。AMS调用默认构造来执行基本的初始化工作,如设置实例变量。此时MIDlet还处在暂停(Paused)的状态,它并没有获得任何所需的资源。 Ø startApp()方法。AMS调用startApp()方法来获取MIDlet所需的资源,然后MIDlet将会处于活动(Active)状态。 Ø pauseApp()方法。AMS调用pauseApp()方法来释放MIDlet持有的任何资源。如果MIDlet创建了对象,则将对象状态存储到持久性存储器中并把对象设置为Null。如果MIDlet启动了任何线程,则停止或者暂停这些线程。 Ø destroyApp()方法。AMS调用destroyApp()方法来保存MIDlet的状态并释放MIDlet持有的任何资源。通常,一个设计良好的MIDlet应该在被关闭前进入此状态。 下面的代码框架包含了基本的生命周期方法,可以将其作为程序的模版。出色的开发工具在新建MIDlet的时候都会自动生成类似下面的框架,如Netbeans IDE。 import javax.microedition.midlet.*; public class MyMIDlet extends MIDlet{ public MyMIDlet(){ //默认构造器 } public void startApp(){ //进入活动状态 } public void pauseApp(){ //进入暂停状态 } public void destroyApp(Boolean unconditional){ //进入销毁状态 } } 2.MIDlet的状态 用户启动MIDlet之后,被启动的MIDlet将处于应用程序生命周期中的三个状态之一。可能的状态是暂停(Paused)、活动(Active)和销毁(Destroyed)。 Ø 活动状态。当一个MIDlet进入活动状态时,它将获得用于执行任务的所有资源。转移到活动状态之后,所需的线程应该被启动。 Ø 暂停状态。当一个MIDlet进入暂停状态时,它应该释放所有持有的资源并停止活动的线程。如果有需要,则应该把数据保存到持久性存储器中,这样在程序重新进入活动状态的时候可以重用。 Ø 销毁状态。当一个MIDlet进入销毁状态时,它应该释放所有资源、停止正在执行的线程并保存持久性的数据。 MIDlet的状态如图2-17所示。 AMS控制着MIDlet在上述三种状态中的迁移,通过调用MIDlet的生命周期方法来通知应用程序。读者需要仔细参考MIDP Java doc来熟悉MIDlet的状态迁移。这里总结如下: Ø 默认构造器。当用户启动一个MIDlet的时候,AMS创建一个新的MIDlet实例,通过调用默认构造器来执行初始化工作。当构造器返回后,MIDlet被置于暂停状态。如果在构造器执行期间抛出异常,那么MIDlet立即进入销毁状态。 Ø public void startApp()方法。在MIDlet处于暂停状态的时候,AMS调用startApp()方法指示MIDlet应该进入活动状态。startApp()方法可能会抛出MIDletState ChangeException,这个异常说明MIDlet现在不能启动,但是可能稍后会启动。如果阻止MIDlet启动的错误是短暂性的,那么你可以捕获这个异常并从错误中恢复。如果这个错误是非短暂性的,那么应该调用notifyDestroyed()方法,MIDlet进入销毁状态。 Ø public void pauseApp()方法。当MIDlet在活动状态的时候,AMS调用这个方法指示MIDlet将从活动状态进入暂停状态。 Ø public void destroyApp(boolean unconditional)方法。AMS可以在MIDlet处于活动或者暂停的时候调用这个方法,指示MIDlet将进入销毁状态。参数unconditional代表了终止请求的类型,如果unconditional为true,那么终止请求是强制执行的。如果unconditional为false,那么终止请求是可自由决定的,MIDlet可以抛出MIDletStateChangedException而持续运行。 3.控制MIDlet的状态改变 AMS控制MIDlet的状态改变,在代码执行到某一点你可能需要状态的改变。MIDlet类提供了如下三个方法来允许一个MIDlet来控制它自己的状态。 Ø resumeRequest()方法。MIDlet调用这个方法表明它本身已经准备好进入活动状态了。resumeRequest()方法调用的结果是,AMS会在何时调用MIDlet的startApp()方法。 Ø notifyPaused()方法。该方法允许MIDlet主动暂停自己。当MIDlet处于活动状态的时候,它可以调用notifyPause()方法通知AMS MIDlet已经主动进入暂停状态。在必要的时候,AMS可以调用startApp()方法重新启动MIDlet,也可以调用destroyApp()方法来终止MIDlet。 Ø notifyDestroyed()方法。该方法允许MIDlet主动销毁自己。当MIDlet处于活动状态的时候,它可以调用notifyDestroyed()方法通知AMS MIDlet已经主动进入了销毁状态。 必须注意的是,如果上述的三个通知方法被调用,那么AMS就不会再调用相应的生命周期方法。例如,如果已经调用了notifyPaused()方法,那么pauseApp()方法就不会主动被调用。也就是相关的生命周期方法应该先于通知方法之前调用。因此,我们经常在退出应用程序的代码中看到如下的方法: public void exitMIDlet(){ try{ destroyApp(false); notifyDestroyed(); }catch(MIDletStateChangeException ex){ ex.printStackTrace(); } } 如果exitMIDlet()方法中只是调用notifyDestroyed()方法,那么destroyApp()方法就不会被AMS方法自动调用,这样本来由destroyApp()方法完成的销毁和状态保存工作都没有被完成。图2-18说明了MIDlet的状态控制。 2.3.3 MIDlet套件 把一组MIDlet打包到一个jar文件然后发布,这个文件称做MIDlet套件。在MIDlet套件的内部有个Manifest.mf文件用于描述MIDlet套件的内容信息,其中就包含定义MIDlet套件中的MIDlet的属性。在同一个MIDlet套件中的MIDlet可以访问同样的资源,如类和数据,他们之间共享运行环境。 从物理组织上说,MIDlet套件包含如下的内容: Ø 一个或者多个MIDlet,它们必须是javax.microedition.MIDlet的子类; Ø MIDlet的支持类,这些类是在CLDC和MIDP中都没有定义的,需要开发者自己创建,比如功能类等; Ø 资源文件,如图片、文本和多媒体文件; Ø Manifest.mf文件用于描述MIDlet套件的信息。 MIDlet类是MIDlet套件中必须包含的,因为它定义了应用程序的生命周期。多个MIDlet可以打包在一个MIDlet套件中发布,这样开发者可以一次创建多个MIDlet。 MIDP规范中要求Manifest.mf文件,这是一个文本文件。它由名称和值组成,中间由“:”分隔。下面是一个典型的Manifest.mf文件的内容。 01Manifest-Version: 1.0 Ant-Version: Apache Ant 1.6.2 Created-By: 1.4.2_03-b02 (Sun Microsystems Inc.) MIDlet-1: Mboker,/icon.png,com.mboker.blog.midp.MBokerMIDlet MIDlet-Vendor: Vendor MIDlet-Version: 1.0 MIDlet-Name: mboker MicroEdition-Configuration: CLDC-1.0 MicroEdition-Profile: MIDP-2.0 每个MIDlet套件有个可选的JAD文件来描述MIDlet套件的信息,与Manifest.mf文件不同的是,JAD文件位于MIDlet套件的外部。虽然是可选的,但是JAD文件的作用非常重要。在MIDlet套件安装到移动设备之前,AMS首先会读取JAD文件的内容,分析MIDlet套件是否与设备实现兼容,比如配置和简表的版本是否匹配。如果不兼容,那么系统会拒绝安装这个套件。当用户从网络上下载MIDlet套件的时候,如果不进行这一步检查,就可能出现用户安装应用程序后不能够运行的问题,给用户造成不必要的浪费。JAD文件的格式与Manifest.mf的文件格式非常相似,都是以“:”来分隔名称和值的。 表2-2描述了在MIDlet套件中定义的属性。 表2-2 MIDlet套件中定义的属性 属 性 描 述 Manifest.mf JAD文件 MIDlet-Name 标记MIDlet套件的名称 必需 必需 MIDlet-Version 标记MIDlet套件的当前版本号 必需 必需 MIDlet-Vendor 创建此套件的组织 必需 必需 MIDlet-n 标记MIDlet类的文件名称、图标和包含包结构的类名 必需 必需 属 性 描 述 Manifest.mf JAD文件 MicroEdition-Profile 标记套件能够成功地运行所需的简表版本 必需 必需 MicroEdition-Configuration 标记套件能够成功地运行所需的配置版本 必需 必需 MIDlet-Jar-URL 指示AMS下载套件的地址 必需 MIDlet-Jar-Size 说明jar文件的大小,以字节为单位 必需 MIDlet-Description 描述套件 可选 可选 MIDlet-Icon 在设备上代表套件的图标 可选 可选 MIDlet-Info-URL 提供MIDlet套件的信息 可选 可选 MIDlet-Data-Size 指定套件用于持久性存储所需的最小字节数 可选 可选 MIDlet-Permission(MIDP2.0) 定义套件成功运行需要访问的受限API的许可 可选 可选 MIDlet-Permissions-Opt(MIDP2.0) 定义那些访问受限API非关键的许可 可选 可选 MIDlet-Push(MIDP2.0) Push注册 可选 可选 MIDlet-Install-Notify(MIDP2.0) 定义接收套件安装状态的URL 可选 可选 MIDlet-Delete-Notify(MIDP2.0) 定义接收套件删除报告的URL 可选 可选 MIDlet-Delete-Confirm(MIDP2.0) 提示用户确认删除了套件 可选 可选 注:MIDlet-n,MicroEdition-Profile和MicroEdition-Configuration不必同时出现在JAD文件和Manifest.mf文件中,可以只出现在其中之一。 Manifest.mf文件和JAD文件都必须包含的三个属性MIDlet-Name,MIDlet-Version和MIDlet-Vendor必须一致,否则AMS会拒绝安装MIDlet套件。当用户安装MIDlet套件的时候,AMS会鉴别正在安装的套件是信任的(Trusted)还是非信任的(Untrusted)。根据套件类型的不同,AMS处理在两个文件中重复定义的属性时采取了如下方法。 Ø 信任套件。如果定义的属性在Manifest.mf和JAD文件中都出现,那么它们必须要一致。 Ø 非信任套件。如果定义的属性在Manifest.mf和JAD文件中都出现,那么JAD文件中的定义的属性值占先。 MIDP 2.0规范中定义了几个新属性,如MIDlet-Permission和MIDlet-Push。在第7章介绍MIDP 2.0的安全模型和PUSH注册机制时将详细讲解上述新属性。 2.3.4 MIDP应用程序的属性 MIDlet可以访问两种运行时的属性值:系统属性和应用程序属性。 1.系统属性 系统属性是在CLDC(Connected Limited Device Configuration)中定义的,属性值被写入底层的系统,我们可以读取它们,但是不能修改这些属性值。如果想读取一个系统属性值,那么可以使用System类的静态方法System.getProperty()来读取。有时候我们可能想读取特定手机的系统信息,比如IMEI号。解决办法就是去参考这款手机的开发指南和规范,比如,从SonyEricsson系列手机读取IMEI号,调用方法:System.getProperty ("com. onyericsson.imei"),这时将返回手机的IMEI号码,如IMEI 123456-00-123456-1-00。需要说明的一点是,在SonyEricsson P910上查询IMEI号码时,传递的字符串参数应该是com.sonyericsson.IMEI(IMEI须大写)。如果在不支持此项功能的手机上查询IMEI号时,将什么都不返回,例如,在T610上调用。 表2-3列举了系统属性。 表2-3 MIDP应用程序系统属性 JSR 属性名称 默 认 值 30 microedition.platform null microedition.encoding ISO8859_1 microedition.configuration CLDC-1.0 microedition.profiles null 37 microedition.locale null microedition.profiles MIDP-1.0 75 microedition.io.file.FileConnection.version 1.0 file.separator 依赖于底层实现 microedition.pim.version 1.0 118 microedition.locale null microedition.profiles MIDP-2.0 microedition.commports 依赖于底层实现 microedition.hostname 依赖于底层实现 120 wireless.messaging.sms.smsc 依赖于底层实现 139 microedition.platform 依赖于底层实现 microedition.encoding ISO8859-1 microedition.configuration CLDC-1.1 microedition.profiles 依赖于底层实现 177 microedition.smartcardslots 依赖于底层实现 179 microedition.location.version 1.0 180 microedition.sip.version 1.0 184 microedition.m3g.version 1.0 185 microedition.jtwi.version 1.0 195 microedition.locale 依赖于底层实现 microedition.profiles IMP-1.0 205 wireless.messaging.sms.smsc 依赖于底层实现 205 wireless.messaging.mms.mmsc 依赖于底层实现 2.应用程序属性 应用程序属性值是在应用程序描述符文件或者MANIFEST文件中定义的,当我们部署应用程序的时候可以定义应用程序属性。比如下面是一个典型的JAD文件内容。 MIDlet-1: HttpWrapperMidlet,httpwrapper.HttpWrapperMIDlet MIDlet-Jar-Size: 16315 MIDlet-Jar-URL: HttpWrapper.jar MIDlet-Name: HttpWrapper MIDlet-Vendor: Vendor MIDlet-Version: 1.0 MicroEdition-Configuration: CLDC-1.0 MicroEdition-Profile: MIDP-1.0 Which-Locale: en 其中Which-Locale就是应用程序属性值,我们可以通过MIDlet的成员方法getAppProperty()来得到它,代码片断如下: import javax.microedition.midlet.*; public class MyMIDlet extends MIDlet { private String suiteName; private String which_locale; public MyMIDlet(){ suiteName = getAppProperty( "MIDlet-Name" ); which_locale = getAppProperty("Which-Locale"); } //这里省略了其他代码 } 属性值对大小写是敏感的,如果属性值在底层系统、JAD文件和Manifest文件中都没有定义的话,那么将返回Null。 熟悉MIDP应用程序的系统属性对我们开发灵活、强大的MIDlet至关重要。可以根据系统属性返回值来动态地生成应用程序的菜单。例如,通过判断底层系统是否支持MMAPI来决定应用程序中是否要添加摄像功能。下面的例子演示了如何在MIDlet中读取系统属性。 package com.j2medev.ch3.property; import javax.microedition.lcdui.*; import javax.microedition.midlet.*; public class DetectMIDlet extends MIDlet { private static DetectMIDlet instance = null; private Display display = null; private Displayable form = null; public DetectMIDlet() { instance = this; } protected void startApp() { if(display==null) { //首次启动应用程序 display = Display.getDisplay(this); form = new TestForm(); display.setCurrent(form); } else{ display.setCurrent(form); } } protected void pauseApp() {} protected void destroyApp(boolean unconditional) {} public static void quitApp() { instance.destroyApp(true); instance.notifyDestroyed(); instance = null; } } class TestForm extends Form implements CommandListener { private Command exit = new Command("退出", Command.EXIT, 0); public TestForm() { super("J2ME平台测试"); String s; //CLDC版本属性 s = System.getProperty("microedition.configuration"); append(getValue("CLDC版本", s)); //MIPD版本属性 s = System.getProperty("microedition.profiles"); append(getValue("MIDP版本",s)); s = System.getProperty("microedition.platform"); append(getValue("软件平台", s)); s = System.getProperty("microedition.encoding"); append(getValue("系统编码", s)); s = System.getProperty("microedition.locale"); append(getValue("区域设置", s)); s = System.getProperty("microedition.jtwi.version"); append(getValue("JTWI", s)); //判断是否支持MMAPI s = System.getProperty("microedition.media.version"); append(getValue("MMAPI", s)); //判断是否支持WMA s = System.getProperty("wireless.messaging.sms.smsc"); if(s!=null) { append(getValue("WMA", "支持")); append(getValue("SMS", s)); s = System.getProperty("wireless.messaging.mms.mmsc"); append(getValue("MMS", s)); } else append(getValue("WMA", null)); //判断是否支持蓝牙 s = System.getProperty("bluetooth.api.version"); append(getValue("蓝牙", s)); //判断是否支持个人信息管理 s = System.getProperty("microedition.pim.version"); append(getValue("PIM", s)); //判断是否支持文件系统 s=System.getProperty("microedition.io.file.FileConnection. version"); append(getValue("FileConnection", s)); //判断是否支持SIP s = System.getProperty("microedition.sip.version"); append(getValue("SIP", s)); //判断是否支持M3G JSR 184 s = System.getProperty("microedition.m3g.version"); append(getValue("M3G", s)); addCommand(exit); setCommandListener(this); } private String getValue(String prompt, String s) { return prompt + ":" + (s==null ? "不支持" : s) + "\n"; } public void commandAction(Command c, Displayable d) { if(c==exit){ DetectMIDlet.quitApp(); } } } DetectMIDlet的运行界面如图2-19所示。 图2-19 DetectMIDlet的运行界面 2.3.5 发布MIDP应用程序 MIDlet开发完成后,需要进行一系列的测试。测试通过后我们就可以发布MIDlet套件了。本节讲述如何搭建OTA(Over The Air)下载服务器来发布MIDP应用程序。 OTA是指通过无线网络下载和安装J2ME应用程序的方案。搭建OTA服务器是比较简单的,但是做一个完整的OTA解决方案却非常复杂,因为这要设计到软件的管理、下载计费和安全认证等多个问题。 当手机通过无线网络发出请求要求下载相关软件的时候,通常是访问特定的页面,页面可以使用WML语言编写。客户端(手机)首先发送获得JAD文件的请求,服务器接收到请求后把JAD文件发送给客户端,客户端根据MIDlet-Jar-URL的信息请求下载jar文件,服务器响应请求并把jar包传输给客户端,客户端接收数据并开始安装软件。原理如图2-20所示。 我们采用Tomcat 5.0作为OTA下载服务器,请参考附录B来正确安装并运行Tomcat 5.0。假设安装目录为C:\Tomcat 5.0,使用文本编辑器打开C:\Tomcat 5.0\conf\web.xml文件,查看服务器是否支持jad和jar两种MIME类型,内容如下: <mime-mapping> <extension>jad</extension> <mime-type>text/vnd.sun.j2me.app-descriptor</mime-type> </mime-mapping> <mime-mapping> <extension>jar</extension> <mime-type>application/java-archive</mime-type> </mime-mapping> 如果采用的Tomcat服务器版本比较早,可能不支持上述两种MIME类型,需要手动把上述XML格式的内容添加到web.xml文件中。接下来编写一个WML文件down.wml作为下载页面,内容如下: <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"> <wml> <card title="Welcome" id="main"> <p>Software center:</p> <p align="left"> <a href="UIDemo.jad"> UIDemo</a></p> </card> </wml> 将down.wml放置到C:\Tomcat 5.0\webapps\ROOT,这样我们可以使用手机语句http://yourserver:port/down.wml下载页面。我们使用WTK2.2自带的UIDemo作为下载文件,将UIDemo.jar和UIDemo.jad文件复制到C:\Tomcat 5.0\webapps\ROOT目录下。 WTK2.2提供了通过OTA的方式运行MIDP应用程序的功能。单击【开始】→【所有程序】→【J2ME Wireless Toolkit 2.2】→【OTA预配置】,启动AMS的安装管理器。单击【应用程序】按钮进入已安装软件列表中,选择“安装应用程序”进入URL输入界面。输入http://localhost:8080/down.wml(读者根据自己服务器的IP地址和端口号填写),然后单击【转到】命令,如图2-21所示。 图2-21 安装UIDemo套件 AMS安装器首先解析down.wml文件,把其中含有的UIDemo显示在列表中。单击【安装】按钮后AMS安装器就会读取UIDemo.jad文件并解析文件内容,然后显示在安装界面内,提示用户是否要安装UIDemo。这时,单击【安装】按钮即可开始安装MIDlet套件。安装完成后UIDemo会出现在已安装的应用程序列表中。安装过程如图2-22所示。 图2-22 安装UIDemo套件 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |