|
|
|
| 您的位置:首页>>J2ME开发>>利用MIDP API建立跨多种无线平台的应用 |
|
|
利用MIDP API建立跨多种无线平台的应用
|
| 2005-06-09 来源:yesky 作者:QQ新人类 |
J2ME简介
J2ME是Sun Microsystems为在资源有限的设备上使用Java编程语言而设的。例如一部移动电话缺少计算能力、内存和工作站能力,它不能执行诸如高端服务器或者客户端工作站上的同样功能。
J2ME平台是建立在Java编程语言上的,可为资源有限的设备提供最大的功能。基本功能的一个子集是由一些特别的类提供的。
在这篇文章中,我将集中介绍CLDC(Connected Limited Device Configuration,连接有限设备配置)和MIDP类。这些类的集合构成了J2ME中的一个简档。这个简档是基于设备内存、处理速度、电池和网络连接带宽非常有限的基础之上的。
CLDC API简介
CLDC是一个基本的平台,MIDP API构建在上面。CLDC类包含了一套标准的函数集合,所有J2ME认证的电话将会支持这个集合。通常,你无需直接和这些类进行交互,不过某些设备要求你访问这些低级别的类来执行一些功能。这些低级别的访问在设备和平台开发时是不提倡的。
MIDP简要表
MIDP简要表是为了支持移动电话或者类似受屏幕或者键盘限制的设备而发布的,当然这些限制还包括有电池、处理器和带宽。
这个简要表包含了一系列的API,可让你创建各种的应用,例如使用自定制图形的视频游戏,或者是使用外部和内部数据源的全面的商业应用。
现在已经有设备生产商已经宣布他们将会在其设备上支持MIDP平台。 一个简单的例子
以下是一个HellwoWorld类型的简单例子,它可让你看看一个midlet的生命周期,midlet是在你的移动设备上执行的代码名字。它与一个applet类似,它包含有用户界面、数据和控制能力。
import javax.microedition.midlet.*; import javax.microedition.lcdui.*;
public class HelloMidlet extends MIDlet implements CommandListener { // Initialize the Midlet Display variable private Display midletDisplay;
// Initialize a variable for the doneCommand private Command doneCommand;
public HelloMidlet() { // Retrieve the display from the static display object midletDisplay = Display.getDisplay(this);
// Initialize the doneCommand doneCommand = new Command("DONE", Command.SCREEN, 1); }
/** * Create the Hello Midlet World TextBox and associate * the exit command and listener. */ public void startApp() { // Create the TextBox containing the "Hello Midlet World!!" message TextBox textBox = new TextBox("Hello Midlet", "Hello Midlet World!!", 256, 0);
// Add the done Command to the TextBox textBox.addCommand(doneCommand);
// Set the command listener for the textbox to the current midlet textBox.setCommandListener( (CommandListener) this);
// Set the current display of the midlet to the textBox screen midletDisplay.setCurrent(textBox); }
/** * PauseApp is used to suspend background activities and release * resources on the device when the midlet is not active. */ public void pauseApp() { }
/** * DestroyApp is used to stop background activities and release * resources on the device when the midlet is at the end of its * life cycle. */ public void destroyApp(boolean unconditional) { }
/* * The commandAction method is implemented by this midlet to * satisfy the CommandListener interface and handle the done action. */ public void commandAction(Command command, Displayable screen) { // If the command is the doneCommand if (command == doneCommand) { // Call the destroyApp method destroyApp(false);
// Notify the midlet platform that the midlet has completed notifyDestroyed(); } } }
| midlet的输出如图一所示,它其实是J2ME Windows Toolkit DefaultGrayPhone模拟器的一张抓图。
 **************************图一************************ | 头两行导入指定的midlet类来支持MIDlet类, CommandAction接口和用户接口(UI)类。这些类放在MIDP API中,其中带有一个经过修改的Java编程语言子集。MIDP API中包含的类将会在本文后面详细讨论。
public class HelloMidlet extends MIDlet implements CommandListener
该行声明HelloMidlet类是扩展MIDlet类,并且实现了CommandListener接口。每个midlet都必须扩展抽象的MIDlet类,该类包含了以下表示的三个方法,而每一个midlet都必须覆盖它们以完成自己的生命周期。
| 方法名 |
方法的目的 |
| startApp |
分配渴望的系统资源和初始化应用 |
| pauseApp |
暂时挂起耗资源的处理 |
| destroyApp |
释放被midlet使用的资源并且处理掉midlet | 在上面的例子中,startApp包含了大部分的功能,这是由于HelloMidlet并没有使用其它的系统资源,例如网络连接或者数据存储。在HelloMidlet被执行的时候,将会调用startApp。
如你所料,构造器将在startApp方法前被执行。在这个例子中,构造器由全局的Display对象接收显示。此外,构造器初始化doneCommand。
上面的startApp方法将用来创建在midlet上显示的屏幕。以下的行是用来初始化TextBox屏幕的。
TextBox textBox = new TextBox("Hello Midlet", "Hello Midlet World!!", 256, 0);
一个midlet的屏幕还包括有Commands。一个command就是midlet用来创建菜单的技术,就象上图中的“Done”按钮。以下代码就是用来为TextBox屏幕加入“Done”按钮的代码:
// Add the done Command to the TextBox textBox.addCommand(doneCommand);
| Command源还会在被点击时产生CommandActions。在上面的简单例子中,HelloMidlet将会实现CommandListener的接口,因此还会处理所有自己的事件。在开发系统变得更复杂时,使用一个扩展的方式来处理事件将会更为有利。
// Set the command listener for the textbox to the current midlet textBox.setCommandListener( (CommandListener) this);
| 既然TextBox已经被创建,它就准备好被显示在设备的屏幕上。在以下的代码中。我将当前的显示设置为新创建的TextBbox;
// Set the current display of the midlet to the textBox screen midletDisplay.setCurrent(textBox);
| HelloWorld midlet是一个很简单的例子,它只使用了MIDP平台上的一些类。在以下的部分,我将会介绍MIDP API的一个子集。 MIDP/CLDC API概述
由于MIDP/CLDC API将在一个性能有限的设备上运行,因此Java的一些功能被移除或者修改。MIDP/CLDC API包含有以下的类库:
java.lang.*
java.io.*
java.util.*
javax.microedition.io.*
javax.microedition.ui.*
javax.microedition.rms.*
javax.microedition.midlet.*
java.lang包
这个库只是J2SE java.lang包中标准类的一个子集。一个值得注意的地方是Float类,MIDP并不支持浮点的计算。以下是其中包含的类:
| Object |
Class |
Runtime |
System |
| Thread |
Runnable |
Throwable |
Math |
| String |
Boolean |
Short |
Long |
| Byte |
Character |
Integer |
StringBuffer | java.io包
-java.io包中包含了用来从远程系统中接收信息的方法。在CLDC API中,包含有以下的类:
| InputStream |
OutputStream |
Reader |
Writer |
| DataInput |
DataOutput |
DataInputStream |
DataOutputStream |
| ByteArrayInputStream |
ByteArrayOutputStream |
InputStreamReader |
OutputStreamReader |
| PrintStream |
|
|
| java.util包
java.util包只是原有包中一个很小的子集。它仅包含有以下的类:
| Calendar |
Date |
TimeZone |
Enumeration |
| Vector |
Stack |
Hashtable |
Random | javax.microedition.io包
javax.microedition.io包中的主要对象是Connector类。你可将该类强制转换为不同的连接类型,如下所示,使用的是连接接口。
| 连接接口 |
连接的目的 |
| StreamConnection |
打开一个基本的连接来读/写简单的数据 |
| ContentConnection |
打开一个可提供内容长度、类型和加密信息的连接。该接口由StreamConnection接口扩展而来 |
| HttpConnection |
打开一个可提供通过HTTP接口的连接,包含有得到/设置头部和HTTP的特殊处理。该接口由ContentConnectioninterface扩展而来。 | Connector open()方法有以下普通的形式:
Connector.open(":;");
javax.microedition.ui包
javax.microedition.ui包中的类可让你定义你的midlet用户接口。在UI设计方面,API提供了两个主要的选择。
在以下的例子中,我们将使用Canvas,它通过Graphics对象来构造一个自定义的UI。使用Canvas,你可以设计多线程的视频游戏或者非传统的用户界面。
在前面的HelloMidlet例子中,使用的是Screen对象和子类,它是用来构造表格形式的用户界面的。我将会在第2部分中讨论这些UI类的能力,你也可以从Javadoc中了解它们。
javax.microedition.rms包
javax.microedition.rms包中的类是用来在设备上实现一个临时存储数据库的。该数据库的存储和获取信息的性能受到设备的限制。
我将在后面讨论这些数据库API。
javax.microedition.midlet包
javax.microedition.midlet中包含有MIDlet的类。MIDlet类执行midlet的生命周期,并且提供getAppProperty(key) 方法来由应用属性中获取信息,应用属性设置在jad文件中。
开始设计前的准备
看过上面的例子,并且对MIDP平台的性能有所了解后。我将会介绍安装MIDP环境的过程。此外,我还会介绍建立和配置midlet类的过程。 安装
Sun最近推出的一个工具包简化了midlet的开发。Java 2 Micro Edition Wireless Toolkit ( J2MEWTK)为midlet开发提供了一个全面的工具包。
当前的工具包安装有两个限制。首先,它只能在Windows的环境中运行。Sun将会在不久的将来推出Solaris和Linux版本的工具包。第二,安装的目录名不能包含有任何的空格,这是由于该工具的内部建立过程决定的。
在下载该工具包后,你只需要双击该应用来执行它。接着有一些提示来让你指定安装的位置。J2MEWTK允许和Forte开发环境进行集成,它也可以从Sun得到。要为工具包装上Forte扩展,你需要选择自定义安装。
以下的目录结构将被创建到你的安装目录中。要注意的是,目录名不能包含有空格,否则运行会不正确。
| 目录 |
目的 |
| {Install}/apps |
包含的文件与你的个人项目有关。所有的原代码、资源和配置文件将包含在这里。此外,这些目录包含有编译过程的产品,该过程由该工具运行。 |
| {Install}/bin |
存放着midlet环境的bin文件,这些bin文件用来预证实和建立应用代码 |
| {Install}/lib/midpapi.zip |
包含有为CLDC和MIDP API而设的类 |
| {Install}/docs |
包含有API Javadoc文件和MIDP用户指南(PDF格式) | 启动KToolbar
你可以由命令行或者安装时生成的菜单来启动KToolbar。执行文件是Ktoolbar.bat。
KToolbar启动后的界面如图二所示。
 ************************图二************************** | 创建一个项目
在启动该工具后,你就可以创建一个项目,例如是我前面提到过的HelloMidlet。你只需要点击图二中的"New Project..." 按钮,这时将会弹出一个对话框,见图3。
 *********************图三********************* | 对话框要求输入该项目的名字和一个midlet的类名。一个项目中可包含有多个midlet,你可以在这里修改midlet的名字。
在这个例子中,你可在项目名和midlet类名中输入HelloMidlet。在输入完后点击创建项目的按钮,这时将会出现图4的界面,它是用来收集HelloMidlet项目的设置的。
 *********************图四****************** | 图4中的默认设置是基于项目名和midlet名的。MIDlet-Jar-URL的默认值是项目的名字。你不必修改上面展示的任何设置。
 **********************图五***************** | 图5中的界面是让你指定一个项目的某些属性的。midlet可以接收这些属性,并且将它们作为应用的一部分。因此,我建议你在这里填写它们的值,而不是在个别的应用中设置它们。
 ********************图六*************** | 图六中展示的是包含在HelloMidlet项目中的全部midlet列表。J2ME Windows Toolkit还可让你修改这些midlet的显示顺序(在jar文件运行在模拟器时)。在这个例子中,仅有一个midlet,因此它的显示为MIDlet-1。 编译midlet
J2MEWTK包含有一个内置的编译工具,可为你的项目执行编译的过程。要编译你的项目,只需点击图2中的编译按钮就可以了。这个工具集包含有一个自动化的编译过程,不过有些工具是没有的,因此,这里介绍一下编译的步骤:
1。创建用作编译处理的类和临时类目录;
2。编译Java源文件到临时类目录中;
3。预验证包含在临时类中的类文件,并且输出到类中;
4。Jar已经验证的类文件;
5。Jar资源文件;
6。创建一个备忘来更新jad文件的jar文件大小;
编译的结果是,产生的jar文件将包含有全部的预验证类,这些类是给设备配置应用和项目的jad文件时需要的。
jad文件
jad文件包含有全部关于midlet的信息,包括它的属性名和它的相关属性值。在例子中的HelloMidlet类中,jad文件是:
MIDlet-1: HelloMidlet, HelloMidlet.png, HelloMidlet
MIDlet-Jar-Size: 1387
MIDlet-Jar-URL: HelloMidlet.jar
MIDlet-Name: HelloMidlet
MIDlet-Vendor: Sun Microsystems
MIDlet-Version: 1.0
项目列表中包含有midlet的名字、URL、大小和版本。最令人感兴趣的是顶部的MIDlet-1那行。由于在这个jad文件中只有一个midlet,因此,仅有一行。如果有n个midlet,就会有n行,如下所示:
MIDlet-1: ...
MIDlet-2: ...
...
MIDlet-n: ...
上面的每一行将会提供midlet的名字、midlet的图象文件和包含该midlet的类文件名。
为什么要预验证?
上面提到,类文件需要运行预验证的过程。这个过程可确保类文件不包含有任何的无效操作。此外,在一个更强大的计算机上执行一些标准的虚拟机要比全部交给设备的KVM好。
KVM被设计为可放入到1K内,而且已经被优化为在设备上处理,它不包含有预验证中进行的基本处理。
运行midlet
你也可以在J2MEWTK中运行midlet。图2中KToolbar的运行按钮是灰色的。一旦项目被装载,这个按钮将会被激活。要运行midlet,可在以下的列表中选择你要进行测试的设备:
DefaultColorPhone: 默认电话(彩色版本)
DefaultGrayPhone: 默认的电话
MinimumPhone: 一个很基本的模拟器
Pager: 一个双向的传呼机
在选择好设备后,你只需按下运行的按钮就可以启动模拟器。如果你要从命令行中运行midlet,可执行以下的命令:
java -cp \lib\kvem.jar;\lib\kenv.zip; \lib\lime.jar -Dkvem.home= [-D<:property>=] com.sun.kvem.midp.Main -descriptor | 要了解命令行的全部语法,可参考Sun提供的用户指南(5.5.2.1部分)。 图形框架例子
以下的例子构造了一个简单的图形框架,可让你在MIDP环境中有效地开发图形代码。
这个简单的图形例子包含有以下的类:
GraphicalMidlet: 用来处理和设备交互的midlet类
GraphicalCanvas: 包含有graphical对象的canvas
GraphicalObject:一个实现Runnable的默认graphical对象
MovingTextObject: 默认的用来移动文本的对象
VerticalScrollingTextObject:默认文本对象的一个扩展
在该例子中,GraphicalMidlet类负责扩展MIDlet类,因此执行midlet的生命周期。此外,该类还负责在用户准备退出应用时,实现CommandAction接口来处理单一的Exit命令。
GraphicalMidlet类的构造器从静态访问的Display对象中接收display对象。构造器然后初始化一个GraphicalCanvas类,它的作用是作为CommandListener。
public GraphicalMidlet() { display = Display.getDisplay(this);
canvas = new GraphicalCanvas(display); canvas.addCommand(exitCommand); canvas.setCommandListener(this); }
| 在GraphicalCanvas的构造器中,一个新的VerticalScrollingTextObject对象被创建,用来传送canvas和信息。在这个简单的框架中,并没有关于速度、定位或者文本信息颜色的额外信息。这些扩展就留给读者作一个练习吧。
public GraphicalCanvas(Display d) { display = d; // save the display
graphicalObject = new VerticalScrollingTextObject (this, "Hello Midlet World!!"); height = this.getHeight(); width = this.getWidth(); }
| GraphicalCanvas的paint方法是用来重画屏幕的。在这个例子中,canvas清除以前的项目,然后请求GraphicalObject画自己。
protected void paint(Graphics g) { g.setColor(255,255,255); g.fillRect(0,0,width,height); graphicalObject.paint(g); }
| GraphicalMidlet调用的start()方法是用来提醒GraphicalCanvas开始它的处理。在这个例子中,canvas类初始化一个新的包含有Runnable GraphicalObject类的新线程。canvas类接着启动一个新的线程,这样它就可以在调用repaint方法来画canvas前,开始它的处理。
你也可以扩展这个例子,通过加入超过一个GraphicalObject到canvas中,然后同时执行他们。这个留给你作为一个简单的练习。
void start() { display.setCurrent(this); Thread t = new Thread(graphicalObject); t.start(); repaint(); }
| GraphicalObject类实现了Runnable的接口,因此可以由GraphicalCanvas类中start()方法中的线程启动。这个线程将会一直执行直到stopThread被调用来跳出该循环。
public void run() { stopThread = false;
while (!stopThread) { move(); canvas.repaint();
try{ Thread.sleep(100); }catch(InterruptedException ie){ stopThread = true;} } }
| GraphicalObject并不知道它的子类对象如何进行移动和描绘,不过它指定了两个方法必须被覆盖,它们是:
public abstract void move(); public abstract void paint(Graphics g); | 通过覆盖以上的方法,MovingTextObject可以实现它希望的移动和描绘计划。因此,要产生一个不同的对象,例如一个滚动的齿轮,你只需要修改paint和move方法。
public void paint(Graphics graphics) { graphics.setColor(0,0,0); graphics.drawString(stringValue, posX, posY, Graphics.TOP| Graphics.LEFT); }
public void move() { posX = getX(); posY = getY(); }
| 在上面的move()方法中,getX()和getY() 方法的调用是用来返回移动文本对象的X和Y位置的。我这样做是为了解释该框架的一个扩展。在这个例子中,该扩展是相当简单的,getX()返回一个常数值,而getY()方法增加Y的值,直到到达底部的显示。
通过扩展MovingTextObject,你可以加入其它的移动计划。例如,一个RandomMovingTextObject类可以实现随机的X和Y值,并且在getX和getY的方法中返回这些值。进一步的扩展留给读者完成。
本文的要点
在这部分的文章中,我的目的是介绍MIDP的概念,通过一个简单的代码讲解它的生命周期,还介绍了一个简单的类似基本applet的图形例子。
在后面的文章中,我将讨论MIDP为无线设备提供的存储系统。使用基于表格的例子,我还会分析可以用来提供一个无线数据库的API。
然后我将详细讲述用来连接无线设备和外部数据源(例如URL)的API。此外,我还为通过一个更为详细的应用来讲解一些概念,以便你更为有效地进行MIDP开发。
结论
在无线设备上引入Java代码,可改进该平台的功能性。midlet拥有革新无线平台的潜力,这是由于它可让开发者集中精力于为移动用户开发功能更强、更容易使用的应用。当与该行业的一些其它的技术结合的时候,例如位置感应,该平台将会很快被人们接受。
这是一个令人激动的领域,它可让开发者进入无线领域而不要学习太多新的Java API。该平台令Java的“write once ,run everywhere”的概念有了一个全新的含义。
|
|
|
|