转贴(电脑报):J2ME无线通信编程入门

J2ME无线通信编程入门  
  尹华成 附录文章

  随着支持Java软件的手机问世,开发应用于手机上的程序已经不再是梦想。本文将向读者介绍如何利用J2ME开发手机及移动设备的应用程序。

  一、基础篇:J2ME体系结构详解
  1.什么是J2ME
  J2ME即JAVA 2 Micro Edition,它是Java 2的组成部分,与J2SE、J2EE并称。J2ME是一种高度优化的Java运行环境,应用于大量的消费类电子设备,如Cellular Phones(蜂窝电话)、Screen Phones(可视电话)、Digital Set-top Boxes(数字机顶盒)、Car Navigation Systems(汽车导向系统)等,同时也广泛被移动通信设备所采用,如移动电话、双向寻呼机、智能卡、个人电脑记事本(Personal Organizer)和掌上电脑(Palmtop)等。J2ME技术将Java语言的与平台无关的特性移植到小型电子设备上,允许移动无线设备之间共享应用程序。

  2.J2ME体系结构和配置
  (1)J2ME体系结构

  J2ME体系结构基于设备的系列和类别,一个类别定义了一个特定种类的设备。移动电话、寻呼机和个人电脑记事本都是单独的类别。对存储器和处理能力有相近需求的若干类别的设备构成设备的一个系列。移动电话、寻呼机和个人电脑记事本一起就是占用资源很小的设备的一个系列。图1定义了在J2ME环境中设备的系列和类别之间的关系。

 

  另外,为了支持资源受限设备所要求的那种灵活性和可定制部署,人们将J2ME体系结构设计成模块化和可伸缩。J2ME技术在一个完整的应用程序运行模型中定义了这种模块性和可伸缩性,在该模型中的4个软件层都构建在设备的主机操作系统上。J2ME的体系结构如图2所示。

 

  Java 虚拟机层(Java Virtual Machine Layer):是Java虚拟机的一个实现,它是为特定设备的主机操作系统定制的,而且支持特定的J2ME配置(Configuration)。

  配置层(Configuration Layer):配置层定义了Java虚拟机功能上和特定类别设备上可用的Java类库的最小集。从某种程度上说,一个配置定义了Java平台功能部分和库的共同性,开发者可以假设这些功能部件和库在属于某一特定类别的所有设备上都是可用的。

  框架层(Profile Layer):框架层定义了特定系列设备上可用的应用程序编程接口(API)的最小集。框架在一个特定的配置上实现。应用程序是针对特定框架编写的,因此可以移植到支持该框架的任何设备上。一个设备可以支持多个框架。用户和应用程序供应商看到最多的就是这一层。

  MIDP(Mobile Information Device Profile)层:移动信息设备框架。是Java API集合,它处理诸如用户界面、持久存储和联网等问题。

  (2)J2ME配置

  由上可知,J2ME组件都围绕一个中心,这些中心被称为“配置”(Configuration)。它们用于消费电子和嵌入设备的特别的类。目前J2ME定义2个“配置”,这2种“配置”由于其处理运算的能力不同而支持不同的设备对象。

  Connected Limited Device Configuration(CLDC,有限连接设备配置):该“配置”定义Java应用程序接口以及支持手持设备的技术。如手机、掌上电脑等。

  Connected Device Configuration(CDC,连接设备配置):该“配置”支持“插入墙”式设备的应用程序接口,如机顶盒等。

  上述两种“配置”,其区别在于它们应用于的设备的能力:

  CLDC设备的处理器能力有限(与台式机比较),且存储器大小一般只在128KB到512KB之间,而CDC系统则不同,它可能有32位或64位处理器,以及有限的存储容量,不过它的下限也超过512KB。它们共同所遵循的原则是,每个不同功能的硬件设备都将被不同的虚拟机支持。

  3.J2ME的简表
  虽然,“配置”为一组通用设备提供了最小的Java平台,但是开发者感兴趣的是为个别设备设计应用程序,当他们只使用“配置”进行开发,那么所编写的应用程序肯定会有所欠缺。“配置”必须满足所有设备的最小要求,而用户界面、输入机制和数据持久性都具有高度的设备具体性,每一种设备都有自己的方法,这些往往不在“配置”所能满足的最小要求范围之内。

  现在,5个已知简表已经有了规范。而每个简表的责任都是为了完善配置的不足。

  (1)MIDP简表

  MIDP(Mobile Information Device Profile,移动信息设备简表)是第一个实现的简表,它补充了CLDC配置,并且提供应用程序语义和控件、用户界面、持久存储器、网络和用于移动电话的计时器、双通道呼叫器和其他无线电设备。

  (2)PDA简表

  Palm公司是开发PDA简表规范的领头人,该简表完善了CLDC配置,在相当长的时间内,它都将是KJava类程序包的替代品。Java规范建议该简表至少应当提供2个核心功能片段,即用户界面显示工具包,适合于“有限的尺寸和深度显示”,另一个则是持久数据存储器机制。显示工具包应该是抽象窗口工具包的一个子集,而持久机制将为应用程序、数据、配置/环境信息提供简单的数据存储。

  (3)Foundation简表

  Foundation简表的任务是担任一个基础简表,便于以后开发出来的提供图形用户接口、 网络等功能的简表附着在它之上。除了用于基础简表,Foundation简表还提供完整网络的支持,不管有没有使用图形用户接口。

  (4)Personal简表

  在当前规范的需求下, Personal简表提供下一代Personal Java环境。该简表允诺,提供互联网连接性和Web保真度以及一个能够运行Java Applets的GUI。

  (5)RMI简表

  我们知道CDC配置为共享的、固定网络连接信息设备提供最小的Java环境。该简表将通过提供Java到Java的RMI来协助提供更好的网络连接性。

  二、入门篇:MIDP简表应用实例
  前面我们介绍了J2ME的基础知识,同时也提到了MIDP简表的作用。现在我们来看看如何利用J2ME与MIDP开发应用程序。

  注意:遵照MIDP简表和CLDC配置规范编写的Java应用程序,我们称其为MIDlet。

  1.MIDP/CLDC API概述
  由于MIDP/CLDC API将在一个性能有限的设备上运行,因此Java的一些功能被移除或者修改。

  (1)MIDP的类库

  如上所述,SUN在CLDC配置之上定义了MIDP层,用以提供对用户界面(User Interface,UI)、永久存储介质(Persistinace Storage)和网络等支持。下面,我们来看看MIDP的类库。

  MIDP由四个javax.microedition包组成,包括:

  javax.microedition.rms:关于永久存储介质(rms即Record Management System)。

  javax.microedition.midle:定义了MIDlet的框架,以及MIDlet与环境的交互。

  javax.microedition.io:提供网络支持。

  javax.microedition.lcdui:关于用户界面(UI分为High Level和Low Level两种API)。

  (2)构件

  MIDP简表和CLDC配置组合起来,为创建移动电话和简单双向寻呼机上的应用程序提供了完整的开发环境。

  MIDP框架的核心是一个MIDlet应用程序。这个应用程序继承了MIDlet类,以允许应用程序管理软件对MIDlet进行控制、从应用程序描述检索属性以及对状态变化进行通知和请求。所有MIDlet都继承MIDlet类──运行时环境(应用程序管理器)和MIDlet应用程序代码之间的接口。MIDlet类提供了用于调用、暂停、重新启动和终止MIDlet应用程序的API。应用程序管理软件可以在运行时环境内管理多个MIDlet的活动。此外,MIDlet可以自己发出一些状态变化,并把这些变化通知给应用程序管理软件。

  MIDP API类的完整集合可以分为两个类别:

  用于用户界面的MIDP API:设计这些API是为了能以一系列屏幕显示为基础,与用户进行交互操作,每一屏幕显示适量的数据给用户。这些API允许应用程序决定下一屏显示什么、执行什么、计算和使用网络服务的何种请求。

  用于处理数据库的MIDP API:这些API负责组织和操作设备数据库,这个数据库由在MIDlet的多个调用之间跨越时保持持久的信息组成。底层的CLDC API用于处理字符串、对象和整数。还提供了Java 2 API的一个子集,用于处理I/O和网络通信。

  (3)用户界面设计(UI)

  MIDP API尽管维护的是一个受限的框架,但它还是提供了用户界面元素的完整集合。以下是最重要的UI元素:

  Alert:用于在屏幕上显示异常情况或错误的信息。

  Choice:用于实现从既定数量的选项中进行选择。

  ChoiceGroup:提供一组相关选项。

  Form:作为其用户界面元素的容器。

  List:提供一个选项列表。

  StringItem:只显示字符串。

  TextBox:允许用户输入和编辑文本的屏幕显示。

  TextField:允许用户输入和编辑文本。多个TextField可放到一个Form中。

  DateField:是一个可编辑的组件,用于表示日期和时间信息。DateField可以放到Form中。

  Ticker:用于文本的可滚动显示。

  (4)设备数据库管理

  MIDP简表提供了一组用于组织和操作设备数据库的类和接口:RecordStore、RecordComparator和RecordFilter。RecordStore由大量的记录组成,这些记录在MIDlet的多个调用之间跨越时保持持久。对RecordStore中的记录进行比较,或者从RecordStore中抽取若干组记录,都是RecordComparator和RecordFilter接口提供的功能。

  2.配置编程环境
  与其他编程语言不同,在开发一个J2ME程序之前首先要配置好J2ME编程环境。

  (1)软件准备

  在开发一个MIDlet之前,需要下载:

  Java Development Kit(JDK),1.2版本以上。

  Connected, Limited Device Configuration(CLDC)。

  Mobile Information Device Profile(MIDP)。

  (2)软件安装

  JDK安装:JDK已经默认了用于安装文件的目录,当然你也可以选择安装在一个你自己选定的路径。如E:/jdk1.3。

  安装CLDC配置:将下载到CLDC软件解压到硬盘,笔者推荐路径为E:/j2me。解压以后,E:/j2me路径的结构如下所示:

  E:/j2me

   |

  j2me_cldc

  安装MIDP简表:同上,解压MIDP软件到硬盘目录E:/j2me,现在该目录结构如下所示:

  E:/j2me

  |

  j2me_cldc

  midp-fcs

  (3)配置软件

  PATH环境变量是Windows操作系统用来定位可执行程序的,我们需要更新PATH来指向Java编译程序和CLDC、MIDP程序的路径。

  更新JDK的PATH:如果是在Windows NT/2000环境中,请在控制面板中双击“系统”图标,在出现的对话框中单击“高级”选项卡,单击“环境变量”按钮,在出现的对话框中“系统变量”列表中找到并双击PATH,在出现的对话框中的“变量值”的末尾添加JDK安装路径的/bin目录。假设你安装JDK是1.3版本并选择默认安装路径,本例为E:/jdk1.3。如果是在Windows 98环境中,请在C:/Autoexec.bat文件的最后加上以下两行即可。

  set path= E:/jdk1.3/bin;%path%

  set classpath=.;

  更新CLDC路径:你还需要更新你的PATH环境变量来指向存放CLDC可执行文件的目录。按照上面讲述的相同步骤添加到PATH中:

  E:/j2me/j2me_cldc/bin

  更新MIDP路径:更新PATH环境来指出存放MIDP可执行文件的目录,该文件是用于测试MIDlet的移动电话模拟器。

  按照上面讲述的步骤添加到PATH中,这里是E:/j2me/midp-fcs/bin。

  下面让我们来更新CLASSPATH环境变量。CLASSPATH告诉Java编译程序到什么地方搜索那些不是JDK平台本身附带的类库,在本例中,我们需要更新CLASSPATH来指向MIDP类。你还需要有当前目录的引用("."),作为CLASSPATH的一部分,按照上面概述的相同的步骤,更新CLASSPATH: CLASSPATH=e:/j2me/midp-fcs/classes;。

  注意:最后的点“.”表示当前的工作目录。

  最后,让我们来添加SCREEN_DEPTH环境变量。MIDP含有一个测试MIDlet用的移动设备模拟器,这个模拟器可以以有色模式运行,也可以运行于黑白两色构成的灰度梯度模式。为了指定颜色数,你可以添加环境变量 SCREEN_DEPTH。如CREEN_DEPTH=8。添加该环境变量与处理PATH和CLASSPATH变量的方法类似。

  下表中给出了SCREEN_DEPTH值和颜色的对应关系。

  


颜色数

颜色数

 

1
2
2
4

 

4
16
8
256

 

 

  3.编写代码
  现在我们编写“Hello World!”应用程序来了解J2ME程序的结构及编写方法,在这里,程序名是HelloJ2ME,程序代码如下:

  import javax.microedition.midlet.*;

  import javax.microedition.lcdui.*;

  public class HelloJ2ME extends MIDlet implements CommandListener

  {

    private Display display;

  private TextField tfHello;

  private Command cmExit;

  private Form fmMain;

   public HelloJ2ME()

   {

  display = Display.getDisplay(this);

     //创建主窗体

   fmMain = new Form("HelloJ2ME");

     //创建“Exit”按钮

   cmExit = new Command("Exit", Command.SCREEN,1);

     //创建一个可以容纳15个字符的文本单行

   tfHello = new TextField("Text","Hello World!",15,TextField.ANY);

     //把控件增加到主窗体

     fmMain.addCommand(cmExit);

   fmMain.append(tfHello);

   fmMain.setCommandListener(this); 

   }

  正如我们所看到的那样,HelloJ2ME程序扩展了MIDP基本应用程序MIDlet类,并导入了两个包名称空间:javax.microedition.midlet和javax.microedition.lcdui。前者包括该应用程序的MIDlet基类,而后者则提供了一组类似Swing的GUI元素供应用程序使用。

  MIDlet类提供了3种抽象方法供设备应用程序管理器与其运行的应用程序通讯。只要应用程序被激活、构造器执行完毕之后就会立即调用startApp方法,而不是在应用程序最初启动时就这样做。应用程序在一次运行过程中会在活动和不活动状态之间多次转变,这样你就不必编写单独运行的初始化代码了,因为这类代码很可能会执行好多次。为此应该采用构造器来完成同一功能。

  管理器指示应用程序关闭之后就会调用destroyApp方法。和startApp方法不一样的是该方法只在应用程序生存期内调用一次,所以在这个方法内编写清除代码是很安全的。实际上,由于MIDP并没有为对象包括finalize函数,所以你不得不在以上方法处执行清除功能。同时,由于典型的移动设备比通常情况下的标准平台欠缺稳定,经常被用户进行开关机或者复位操作。所以你也不能真正指望destroyApp派上大用场。

  最后的抽象方法就是pauseApp了。该方法主要作用是发出这样的通知。因为用户转换到其他应用或者采用了设备的某项功能促使应用程序不能继续运行而暂时停止应用程序的运行。由于大多数移动设备都缺乏执行多任务的处理能力,以上的这类情况是完全可能发生的。所以在这个方法中应该编码释放所有资源。一旦应用程序重新开发运行则应用程序管理器会再度调用startApp方法。

  三、进阶篇:无线消息传送系统分析
  针对手机软件的特殊性,我们有必要了解“无线消息传送”的基本原理。下面我们将重点为大家介绍几种常用的无线消息服务方式。

  1.GSM短信服务与小区广播服务
  无线消息传递的思想为J2ME开拓了全新的前景。由无线消息传递支持的J2ME应用程序能独立于平台来访问无线通信资源,如全球移动通信系统(Global System for Mobile Communication,GSM)网络(一种允许跨国通信的移动电话系统)的短信服务(SMS)和小区广播服务(CBS)。

  (1)GSM 短信服务(SMS)

  SMS是GSM网络中移动电话、传真机与IP地址之间简短文本消息的传递。所传递的消息不得超过160个字母、数字字符,且不包含图像或图形。这一服务的主要特性是迅速、价廉并能保证消息会到达目标用户。

  消息一经发送,就会由短信服务中心(SMSC)接收,该中心必须随即将消息发送到适当的移动设备。为了做到这一点,SMSC会向归属位置寄存器(Home Location Register,HLR)发送SMS请求以找到漫游用户。一旦HLR接收到该请求,就会以用户的状态(如1.不活动或活动,2.漫游位置)来响应SMSC。如果响应为不活动,则SMSC将保留消息一段时间。当用户使用其设备时,HLR会向SMSC发送一个SMS通知,而SMSC则尝试进行发送。

  SMSC以短信发送点对点(Short Message Delivery Point-to-Point)格式将消息发送到GSM消息发送系统。该系统会寻呼设备,若设备做出响应,则发送消息。同时,SMSC会收到验证,即消息已经由最终用户接收,然后将该消息归类为已发送,并且将不再尝试发送它。

  (2)GSM小区广播服务

  GSM小区广播服务允许将消息发送到当前位于某个特定小区的每个移动台(Mobile Station,MS),如移动电话、传真机和IP地址。在一段时间内重复小区广播消息,从而使在第一次发送之后才进入小区的MS也能接收到消息。可以用二进制数据或ASCⅡ文本的形式最多发送15页的数据,每页最多有93个字符,测试装置仅提供对ASCⅡ消息的支持。小区广播消息按主题分类,给每条消息都分配了通道号、消息代码、更新号和语言。

  通道号:标识消息主题的头部号(如'气象报告'或'交通信息')。

  消息代码:标识特定的消息,这样当MS收到的消息代码与以前收到的相同时,会意识到这是一条重复消息,就会不显示给用户。

  更新号:用来标识消息的特定版本。

  语言:指明消息所用的语言。更改此参数不会使消息的原文得到翻译。

  2.无线消息传送系统解析
  简单地讲,我们可以把一个无线消息传送系统看作一个三层体系结构,由接口层(Interface Layer)、实现层(Implementation Layer)和传输层(Transport Layer)组成。

  接口层构成了一组通用的消息传递接口,它们独立于所有消息传递协议。这些接口提供消息的基本定义,定义发送和接收消息的基本功能,以及提供向MIDlet应用程序通知进入消息的机制。

  实现层包含这样的类,它们实现每个接口层以访问无线消息传递,如GSM移动设备上的SMS或CBS功能。例如,就SMS而言,这一层提供了用于SMS消息的消息连接实现,以及具有文本或二进制属性的SMS消息的实现。实现层还执行用于底层协议的消息分段和并置。然后,MIDlet可以在MessageConnection中指定应该将某条消息拆分成几段。

  传输层包含这样的类,它们实际实现了将消息传送到移动设备的协议。

  3.通用消息传递API──javax.wireless.messaging

  此API由javax.wireless.messaging包定义,该包定义了所有用于发送和接收无线消息的接口。

  Message:提供消息的基本定义,充当一个容器来容纳消息的地址、有效负载及关于发送和阻塞的标志。它是TextMessage和BinaryMessage的超接口(Super Interface),后两个分别是带文本有效负载属性和带二进制有效负载属性的消息对象。Message的结构如图3所示。

 

  MessageConnection:提供接收和发送消息的基本功能。它包含一个发送和接收消息的方法、一个创建新Message对象的工厂(Factory)方法和一个计算发送某指定Message对象所需底层协议段数量的方法。

  通过调用 Connector.open()可将这个类实例化。

  在客户机方式连接中,只能发送消息。通过将标识目的地址的字符串传递到 Connector.open()方法来创建客户机方式连接。该方法返回MessageConnection对象。

  clientConn=(MessageConnection)Connector.open("sms://+18643630999:5000");

  在服务器方式连接中,可以发送或接收消息。通过将标识本地主机上端点(取决于协议的标识符,例如,端口号)的字符串传递给Connector.open()方法来创建服务器方式连接。

  serverConn =(MessageConnection)Connector.open("sms://:5000");

  MessageListener:它提供了向MIDlet应用程序通知有进入消息的基本机制。当可以读取新到消息时,它允许MIDlet接收一个回调。

  (1)短信服务API

  J2ME的com.sun.midp.io.j2me.sms包提供了用于短信服务消息传递系统的API,并允许MIDlet访问GSM移动设备上的SMS功能。

  该包主要包括MessageObject和Protocol两个主要组件,用于支持SMS消息的发送和接收。

  MessageObject:用于SMS消息实现。

  在实现层,javax.wireless.messaging.Message接口是作为缓冲区实现的。MessageObject处理消息缓冲区的创建和缓冲区之外的输入/输出操作。此外,它有两个子类,即TextObject和BinaryObject。这些类实现具有文本或二进制有效负载的SMS消息。

  Protocol:它实现发送SMS消息所需的与低层传输(Transport)机制的消息连接。在这一过程中,它检查所有的运行配置参数,并处理与无效URL语法、安全性违规、I/O违规和无效参数有关的异常。Protocol还处理使用数据包或串行端口连接的消息发送与接收。

  (2)小区广播消息传递API

  J2ME的com.sun.midp.io.j2me.cbs包提供用于小区广播消息传递系统的API,并允许MIDLlet访问GSM移动设备上的CBS功能。

  该包的主要组件com.sun.midp.io.j2me.cbs.Protocol支持CBS消息的接收。CBS与SMS的不同之处在于,URL连接字符串不支持指定的主机,而且它仅用于入站协议。有CBS能力的MIDlet可接收消息,但不能发送它们。

  四、实例分析篇:一个J2ME消息传递应用程序
  下面我们通过分析一个示例程序WMAServer来介绍J2ME是如何实现消息传送的?示例程序的主要功能是:等候进入的SMS消息,然后将它们显示在电话屏幕上。javax.microedition.lcdui包提供了一组功能,用于实现应用程序的用户界面。

  WMAServer MIDlet通过将标识本地主机上端点(取决于协议的标识符,例如端口号)的字符串传递给Connector.open()方法来创建服务器方式连接。为了能收到进入消息的通知,MIDlet在MessageConnection实例serverConn处注册一个MessageListener对象。

  serverConn.setMessageListener(MessageListener ml);

  它还在MessageListener接口中实现notifyIncomingMessage()。当进入消息到达 MessageConnection时,就调用notifyIncomingMessage()方法。应用程序必须使用 MessageConnection的receive()方法来检索该消息。

  WMAServer应用程序从进入消息读取文本或二进制的有效负载数据,然后将其存储在字符串对象中供以后显示。

  public void notifyIncomingMessage(MessageConnection conn) {

  Message msg = null;

  // Try reading (maybe block for) a message

  try {

    msg = conn.receive();

  }

  catch (Exception e) {

    // Handle reading errors

    System.out.println("processMessage.receive " + e);

  }

  // Process the received message

  if (msg instanceof TextMessage) {

    TextMessage tmsg = (TextMessage)msg;

    msgReceived = tmsg.getPayloadText();

  }

  else

  {

    // process received message

    if (msg instanceof BinaryMessage) {

     BinaryMessage bmsg = (BinaryMessage)msg;

     byte[] data = bmsg.getPayloadData();

     // Handle the binary message...

    msgReceived = data.toString();

   }

  }

  当必须释放连接资源和相关联的侦听器对象时,应用程序提供destroyApp()方法。

  public void destroyApp(boolean unconditional){

   try {

    if(serverConn != null){

    serverConn.setMessageListener(null);

    serverConn.close();

    }

  }

  Catch(IOException e){

    //Handle the exception...

    e.printStacktrace();

  }

  五、实践篇:编写“捕捉键盘输入的ASCⅡ码”程序
  通过前面的介绍,我们对J2ME已经有了一个直观的认识。下面我们将通过编写一个具体的实例程序,来进一步说明J2ME编写手机应用程序的方法。本例程序应用于摩托罗拉388手机,例程完成后,将捕捉键盘输入的ASCⅡ码。

  1.关于开发工具
  MotoJ2SDK是摩托罗拉388手机定制的命令行开发工具包,其中集成的开发环境包括有CodeWarrior、JCreator等。

  无线手持设备(MDIP)简易开发工具包(MDIP的安装方法前文中已有介绍)。

  Java 2 SDK 1.3是必备的,它提供开发、测试和运行Java程序的平台(安装方法见前文)。

  开发环境笔者推荐使用JCreator。

  2.JCreater+MotoJ2SDK的配置与使用
  这是必须而且是极其重要一步,如果配置不正确,你的程序将无法运行。我们假设所有开发工具的安装路径如下:

  JCreator:D:/Program Files/Xinox Software/JCreator LE

  MotoJ2SDK:D:/Motoj2sdk

  JDK:D:/jdk1.3.1

  开始配置之前,我们首先要激活模拟环境。运行D:/MotoJ2SDK/generic/scripts/runConstructor.bat,并正确选择手机型号、选择语言、选择Normal,最后点击“创建”即可。完成以上工作后,我们就可以进行配置了。

  第一步,选择Configure→Options→JDK Profiles。

  注意:一定新建profile and select“D:/jdk1.3.1”。

  将该名字更改为“J2ME 388”;Add classes path更改为“D:/Motoj2sdk/lib”;Add documentation path更改为“D:/Motoj2sdk/docs”。

  第二步,选择 Configure→Options→JDK Tools。

  选择Complier,选中And Edit It项,将parameters更改为“-O -bootclasspath D:/motoj2sdk/lib $[JavaFiles]”。

  第三步,选择Configure→Options→Tools。

  单击“New”按钮,选择DOS command新建一个名字为“Preverifier”的DOS command,并将arguments更改为“d:/Motoj2sdk/bin/preverifier.exe -classpath "d:/Motoj2sdk/lib" -d . .”;将initial directory更改为“$[PrjDir]”。

  第四步,按上面的方法在新建一个名字为“Run Emulator”的DOS command。

  将arguments更改为“java–D java.library.path=d:/MotoJ2SDK/lib -classpath "d:/MotoJ2SDK/bin/Emulator.jar";"d:/MotoJ2SDK/ConfigTool.jar" com.mot.tools.j2me.emulator.Emulator -classpath$[PrjDir];"d:/MotoJ2SDK/lib" –deviceFiled:/MotoJ2SDK/bin/resources/device.props javax.microedition.midlet.AppManager $[CurClass] -JSA 1 1"

  将initial directory 更改为 “d:/Motoj2sdk/bin”。

  第五步,同样按照上面的方法新建一个名字为“Create Jar”的DOS command。 

  将arguments更改为“"$[JavaHome]/bin/jar.exe" cvfM $[PrjName].jar

   META-INF/MANIFEST.MF *.CLASS *.png”。

  将 initial directory 更改为“$[PrjDir]。”

  3.编写实例代码
  选择“Empty Project”新建一个工程,并取名为myJ2 。JCreater会自动在你的工作目录中生成子目录“myJ2”。选择“java File”新建一个java文件。编写以下代码:

  import javax.microedition.lcdui.*;

  import javax.microedition.midlet.*;

  public class test extends MIDlet implements CommandListener {

  private KeyEventsDemoCanvas myCanvas;

  private Display myDisplay;

  private Command okCommand = new Command("OK", Command.OK, 1);

  myJ2() {

  myDisplay = Display.getDisplay(this);

  myCanvas = new KeyEventsDemoCanvas();

  myCanvas.addCommand(okCommand);

  myCanvas.setCommandListener(this);

  }

  public void commandAction(Command c, Displayable s) { }

  protected void startApp() throws MIDletStateChangeException {

  myDisplay.setCurrent(myCanvas);

  }

  protected void pauseApp() { }

  protected void destroyApp(boolean unconditional) { }

  class KeyEventsDemoCanvas extends Canvas {

  public final int BACKGROUND_COLOR = 0xFFFFFF;

  public final int FOREGROUND_COLOR = 0x000000;

  private int lastKey;

  public void paint(Graphics g) {

  g.setColor(BACKGROUND_COLOR);

  g.fillRect(0, 0, getWidth(), getHeight());

  g.setColor(FOREGROUND_COLOR);

  g.drawString("Press a key!", 0, 0, Graphics.TOP | Graphics.LEFT);

  if (lastKey != 0) {

  g.drawString("Key Code: " + lastKey, 0, g.getFont().getHeight(),

  Graphics.TOP | Graphics.LEFT);

  try {

  g.drawString("Action: " + getGameAction(lastKey), 0,

  2 * g.getFont().getHeight(),

  Graphics.TOP | Graphics.LEFT);

  g.drawString("Key Name: " + getKeyName(lastKey), 0,

  3 * g.getFont().getHeight(),

  Graphics.TOP | Graphics.LEFT);

  } catch (Exception e) {

  }

  }

  }

  public void keyPressed(int keyCode) {

  lastKey = keyCode;

  repaint(); 

  }

  public void keyRepeated(int keyCode) {

  System.out.println("Key repeated" + keyCode);

  }

  }

  保存文件,并命名为myJ2.java。在Project中单击“Add file”按钮,在出现的对话框中选中你刚才的myJ2.java文件,编译程序,运行即可。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值