Java 2 Micro Edition[J2ME]

8 篇文章 0 订阅
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

 Java 2 Micro Edition 概念
  J2ME 在设计其规格的时候,遵循着「对于各种不同的装置而造出一个单一的开发系统是没有意义的事」这个基本原则。于是 J2ME 先将所有的嵌入式装置大体上区分为两种 :一种是运算功能有限、电力供应也有限的嵌入式装置(比方说PDA 、手机);另外一种则是运算能力相对较佳、并请在电力供应上相对比较充足的嵌入式装置 (比方说冷气机、电冰箱、电视机上盒 (set-top box))。因为这两种型态的嵌入式装置,所以Java 引入了一个叫做Configuration 的概念,然后把上述运算功能有限、电力有限的嵌入式装置定义在Connected Limited Device Configuration(CLDC)规格之中;而另外一种装置则规范为 Connected Device Configuration(CDC)规格。也就是说, J2ME 先把所有的嵌入式装置利用Configuration 的概念区隔成两种抽象的型态。
  其实在这里大家可以把Configuration 当作是J2ME 对於两种类型嵌入式装置的规格,而这些规格之中定义了这些装置至少要符合的运算能力、供电能力、记忆体大小等规范,同时也定了一组在这些装置上执行的 Java 程序所能使用的类别函式库、这些规范之中所定义的类别函式库为 Java 标准核心类别函式库的子集合以及与该型态装置特性相符的扩充类别函式库。比方就CLDC 的规范来说,可以支援的核心类别函式库为java.lang.* 、java.io.*、java.util.*,而支援的扩充类别函式库为java.microedition.io.*。区分出两种主要的Configuration 之後,J2ME 接著在定义出Profile的概念。Profile 是架构在Configuration 之上的规格。之所以有Profile的概念,是为了要更明确地区分出各种嵌入式装置上Java 程序该如何开发以及它们应该具有哪些功能。因此Profile 之中定义了与特定嵌入式装置非常相关的扩充类别函式库,而 Java 程序在各种嵌入式装置上的使用者介面该如何呈现就是定义在Profile 里头。Profile 之中所定义的扩充类别函式库是根据底层Configuration 内所定义的核心类别函式库所建立。
  Java 在嵌入式系统上的应用
  由于Java 本身最初的设计理念即是针对嵌入式系统,因此将他用在嵌入式系统上真可谓如鱼得水。在这个Linux 开始兴起的时空交会点,网路上出现了一篇关于嵌入式 Linux 与Java 互相配合以造就双赢局面的相关报导,这是由 LinuxDevices.com 的专栏作家 Randy Rorden 所发表的一篇白皮书,名为「 Java 与嵌入式 Linux 合作」。 在这篇文章里头,作者对嵌入式Linux与Java 个别的优点提出他的看法,同时也提出了Java-Linux 平台的构想。有兴趣的读者可以到到下列几个网站参考相关新闻与资料。
  1. Java 与嵌入式 Linux 合作白皮书
  http://www.ctech.com.tw/d-news/news/linux/89090208.asp
  2. Java 及嵌入式Linux 合作
  http://www.linuxdevices.com/news/NS5973673868.html
  3. 即将来临的Java-Linux 结合
  http://www.linuxdevices.com/articles/AT7102892618.html
  -------------------------------------------------------------------------------------------------------
  J2ME (Java 2 Micro Edition) 简介
  ■前言
  如果您曾经到http://www.javasoft.com网站上查询有关Java 2 Micro Edition 的资料,十之八九会被一大堆的技术名词搞的一头雾水。什么 KVM ,什么CLDC 、CDC 、MIDP ,後面还冒出了Personal Java 、Embedded Java以及JES 等名词。虽然名为Java 的微小版本,可是它的世界可真是不小,让我们满肚子「见山不是山,见水不是水」的疑惑。的确,在我刚开始接触 Java 2 Micro Edition 的时候,就感觉到这个玩意儿实在越看越让人摸不著头绪。因此在本章中,我舍弃了技术上的细节,希望带大家从巨观的角度来看待 Java 2 Micro Edition 的世界。希望读过本章之後,可以使大家体验「见山是山,见水是水」,一切豁然开朗的感觉。首先,我们必须先对Java 2 Micro Edition 在整个Java 技术之中的定位做个了解。
  ■各种不同版本之Java 程序的开发
  如前面所说,各种不同的Java 版本,在其支援的核心类别函式库之完整性以及所支援的 Java 基本型别这两件事情上都有所差异,也就是说,不管您开发的是企业所使用的Java 程序、嵌入式装置上执行的Java 程序、浏览器上执行的Applet ,或是在PC 上执行的应用程序。您都必须在您的电脑上先安装 J2SE ,然後再安装各种版本的核心类别函式库以及额外的扩充类别函式库,如此才能成功地开发各种不同目的的Java 程序。J2SE所提供的Java 编译器(javac.exe)可以帮助我们编译各种不同平台上的Java 程序,而J2SE 所提供的Java 虚拟机器(java.exe)则可以帮助我们在PC 上先行测试这些程序执行结果的正确与否。另外,Java 编译器并不会帮您检查您的程序是否符合各种平台上所支援的核心类别函式库与 Java基本型别。举例来说,虽然我们在前面说过,Smart Card 版本并不支援boolean 、byte 以外的Java 基本型别,而且该平台也只支援java.lang.*核心类别,可是当我们在撰写 Smart Card 平台上的程序时,就算在程序码里头用了boolean 或byte 以外的Java 基本型别,或者使用了java.lang.*之外的其他核心类别,编译器仍然可以照常帮您编译出类别档。这个时候大家一定开始产生疑惑 --那么这些程序如果放到Smart Card 上头执行的时候,出了问题怎么办 ? 难道不会造成Smart Card 上的虚拟机器执行时发生错误吗 ? 针对这个可能发生的潜在问题,Sun Microsystems 在各种不同版本的开发套件中,有些会内附检查器 (checker)或者预先审核器 (preverifier),这两个工具可以帮助您在将程序放到目标平台之前先做好检查和预先审核的工作。检查器会帮您找出类别档之中不合目标平台规格的部分,并提醒你这些地方可能无法在目标平台上执行。因此只要有检查器的协助,您大致上可以确定您的程序可以符合目标平台的规定并顺利执行。 Java Card 的开发套件中就附有检查器。
  而某些平台的开发套件则附有预先审核器,预先审核器除了做检查器做的工作之外,还有一项额外的工作,就是减轻目标平台上虚拟机器的负担,要解释预先审核器这个额外的工作,在传统的 Java 程序之中,为了安全上的考量,任何进入执行环境的类别档 (不管该类别档是来自本机或是远端机器 ),都必须先经过Byte Code 审核器(Byte code verifier)的验证,以防止程序在传送途中遭到恶意的修改,而使得 Java 程序在执行时对系统有不良影响。经过审核之後,该类别档才能开始被J 虚拟机器所执行。如果这个审核的动作在一般的 PC 上执行,速度倒是还能够接受,可是一旦放到如 Palm 或是手机这些CPU 较慢、记忆体也比较少的机器上面就显得十分吃力了。为了节省宝贵的 CPU 运算时间(既能省电又能够加速程序执行 ),因此,在程序设计师产生能够让某些特定平台执行的类别档之前,程序设计师必须先在 PC 上使用预先审核器做一些前置的审核工作,预先审核器会在类别档之中加入一些特殊标记或符号。如此一来,当这些程序放到目标平台上执行时,就可以大幅减少在目标平台上做审核时的时间,藉而加速程序的的启动及执行速度。因此在J2ME 之下的程序(Spotlet 、MIDlet),其执行步骤变成因为预先审核的关系,执行时Byte Code 审核器的工作就变少了,也因此从程序载入到开始执行之间的时间因而缩短。 CLDC标准实作和MIDP 参考实作之中就附有预先审核器。
  ■Java 版本的演进
  相信熟悉Java 演进历史的人或多或少都听说过,Java 技术一开始并非就叫做 Java ,而是叫做OAK ,而且最早的时候就是为了嵌入式系统而设计的一项产品。後来因为网际网路的发达,而OAK 的诸多特性刚好又适合用在网路上(例如可移植性、编译後程序码很小),因为商标已被注册的关系,因此 OAK 被改名成Java ,从此因缘际会地成了网路上的闪亮巨星,并随著时间越来越成熟,也慢慢地产生了许多非原本预期中的相关运用。虽然 Java 已经被用到许多企业级软体上,可是其实骨子里面还是非常适合用在嵌入式系统之中。
  虽然从Java 1.0 发表之後,Java 就被广泛地使用在桌上型应用程序以及Applet 的开发上,但是,从Java 1.1 开始,Java又回到了它一开始的老路--也就是嵌入式系统方面的应用,在当时Sun Microsystems 发表了Embedded Java 与Personal Java(也有人简称为PJava)这两项规格。其中Embedded Java 是为了资源十分有限,而且没有显示设备的嵌入式装置而设计; Personal Java 则是为了在能够与网际网路连线、并拥有显示系统(例如彩色LCD)的消费性电子装置而设计。接著Java 的版本演进到Java 2 ,这时为了再明显区分各种Java 的应用,所以分割出了J2EE 、J2SE、以及 J2ME 三种版本。这三种版本的各种特性我们已经在前面已经详细地描述,在此不再赘述。不过请大家记住,由於 Java 2将Java 的应用区分成三大块,使得 Java 程序语言的发展不会再像Java 1.1时如树枝状般扩散出去,这么一来有助於大家对 Java 各种应用的??清,而不会造成今後越发展下去越不可收拾的混乱局面。额外向大家一提的是,後来Personal Java 发展到1.2 版的时候,也采用了一些Java 2 平台上与安全性有关的设计。
  ■Java 2 Micro Edition 概观
  J2ME 在设计其规格的时候,遵循著「对於各种不同的装置而造出一个单一的开发系统是没有意义的事」这个基本原则。於是 J2ME 先将所有的嵌入式装置大体上区分为两种 :一种是运算功能有限、电力供应也有限的嵌入式装置(比方说PDA 、手机);另外一种则是运算能力相对较佳、并请在电力供应上相对比较充足的嵌入式装置 (比方说冷气机、电冰箱、电视机上盒 (set-top box))。因为这两种型态的嵌入式装置,所以Java 引入了一个叫做Configuration 的概念,然後把上述运算功能有限、电力有限的嵌入式装置定义在Connected Limited Device Configuration(CLDC)规格之中;而另外一种装置则规范为 Connected Device Configuration(CDC)规格。也就是说, J2ME 先把所有的嵌入式装置利用Configuration 的概念区隔成两种抽象的型态。
  其实在这里大家可以把Configuration 当作是J2ME 对於两种类型嵌入式装置的规格,而这些规格之中定义了这些装置至少要符合的运算能力、供电能力、记忆体大小等规范,同时也定了一组在这些装置上执行的 Java程序所能使用的类别函式库、这些规范之中所定义的类别函式库为 Java标准核心类别函式库的子集合以及与该型态装置特性相符的扩充类别函式库。比方就CLDC 的规范来说,可以支援的核心类别函式库为java.lang.*、java.io.*、java.util.*,而支援的扩充类别函式库为java.microedition.io.*。区分出两种主要的Configuration 之後,J2ME 接著在定义出Profile的概念。Profile 是架构在Configuration 之上的规格。之所以有Profile的概念,是为了要更明确地区分出各种嵌入式装置上Java 程序该如何开发以及它们应该具有哪些功能。因此Profile 之中定义了与特定嵌入式装置非常相关的扩充类别函式库,而 Java 程序在各种嵌入式装置上的使用者介面该如何呈现就是定义在Profile 里头。Profile 之中所定义的扩充类别函式库是根据底层Configuration 内所定义的核心类别函式库所建立。
  ■Java 在嵌入式系统上的应用
  由於Java 本身最初的设计理念即是针对嵌入式系统,因此将他用在嵌入式系统上真可谓如鱼得水。在这个Linux 开始兴起的时空交会点,网路上出现了一篇关於嵌入式 Linux 与Java 互相配合以造就双赢局面的相关报导,这是由 LinuxDevices.com 的专栏作家 Randy Rorden 所发表的一篇白皮书,名为「 Java 与嵌入式 Linux 合作」。在这篇文章里头,作者对嵌入式Linux与Java 个别的优点提出他的看法,同时也提出了Java-Linux 平台的构想。有兴趣的读者可以到到下列几个网站参考相关新闻与资料。
  1. Java 与嵌入式 Linux 合作白皮书
  http://www.ctech.com.tw/d-news/news/linux/89090208.asp
  2. Java 及嵌入式Linux 合作
  http://www.linuxdevices.com/news/NS5973673868.html
  3. 即将来临的Java-Linux 结合
  http://www.linuxdevices.com/articles/AT7102892618.html
  ■为何要用Java 撰写PDA 上的应用程序?
  由於预期到今後行动通讯时代的来临,所以通讯相关行业变的前景可期,而除了达成行动通讯的主要工具 -- 手机月来越精巧之外,有更多的厂商相继投入PDA 的生产与开发。本来PDA 主要的平台有PalmOS 、Windows CE 以及EPOC ,也不知道曾几何时,开始一大堆公司投入embedded linux 的研发,其中包括国内资策会自己开发的 @ViS 作业系统,互慧科技也有自己的嵌入式作业系统,当然更不用说大陆厂商与韩国厂商了。 喔喔!这些作业平台的数量比起 PC 来说真不知道要复杂上几倍。对一般使用者来说当然影响比较小,可是对於程序开发者来说,看到这么多不同的程序发展平台,真是让人望之却步。如果每个平台都有自己的程序写法以及函式库,那么光是看上面这些平台至少就要学习五种以上程序的写法。当然,只专精一种平台当然是很好的事情。可是程序设计师不禁要说 :”如果我们写出来的软体可以在不经过修改原始码的情况下就能够在这些平台上执行,那不是更完美吗?” 对程序开发者来说,这样的投资报酬率当然是最大的。
  要在那么多平台上开发程序,对程序设计师来说的确是一个很大的挑战,如果要把所有的时间和精力放在软体的可用性上,那么相对地很多时候我们根本没有那么多时间撰写各种平台的程序。要解决这个问题,一般来说程序设计师会选用一个可以跨平台的Framework 来达成至少source code level 的跨平台(例入Qt 就能做到)。不过在本篇文章中我们要介绍的则是更终极的解决方案 ?Java ,利用Java 的”write once, run anywhere”特性,我们可以真正达到程序只要写一次,拿到任何平台上都可以执行(当然前提是必须要PDA 的厂商也要实作出该平台的Java Virtual Machine 才行)。利用Java 来做PDA 上的程序当然有其缺点,最广为人知的可能就是执行效率的问题, Java 在执行速度这个议题上一直让人诟病。不过笔者认为,随著技术的发达,将会有更快更省电的PDA 专用CPU 出现,因此效率上的问题其实是可以忽略的。更何况,当 Sun 在设计J2ME 的时候,也用了很多方式企图加快Java 在PDA 上的执行速度(例如预先审核 )。
  ■总结
  看完了本章之後,您对整个Java 2 Micro Edition 有个大致上的了解了吗? 再进入下一章之前,请务必弄清楚本章所提到的专有名词。如果各位想对各种技术规格做更详细的了解,请自行参考下表所列出的网页。
  Consumer &Embedded Technologies
  http://java.sun.com/products/consumer-embedded/
  Consumer &Embedded Technology Center
  http://developer.java.sun.com/developer/products/j2me/
  Java 2 Micro Edition
  http://www.javasoft.com/j2me/
  JDC J2ME Tech Tips
  http://developer.java.sun.com/developer/J2METechTips/
  CLDC &KVM
  http://www.javasoft.com/products/cldc/
  C &E Center Wireless Technologies
  http://developer.java.sun.com/developer/products/j2me/wireless.
  html
  MIDP
  http://www.javasoft.com/products/midp/
  Embedded Java
  http://www.javasoft.com/products/embeddedjava/
  Personal Java
  http://java.sun.com/products/personaljava/
  JavaPhone
  http://java.sun.com/products/javaphone/
  Java Embedded Server
  http://www.sun.com/software/embeddedserver/index.html
  C &E Center Java Embedded ServerTechnology
  http://developer.java.sun.com/developer/products/j2me/embedserv
  .html
  JavaTV
  http://www.javasoft.com/products/javatv/
  C &E Center Digital Interactive Television
  http://developer.java.sun.com/developer/products/j2me/tv.html
  Java Card
  http://java.sun.com/products/javacard/
  C &E Center JavaCardTechnology
  http://developer.java.sun.com/developer/products/j2me/smartcard
  .html
  Motorola 官方Java 网站
  http://www.motorola.com/java/
  JINI
  http://www.sun.com/jini/
  C &E Center Downloads &Specifications
  http://developer.java.sun.com/developer/products/j2me/downloads
  .html
  Spotless System Page
  http://www.sun.com/research/spotless/
  随着支持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文件,编译程序,运行即可。

本文转自
http://baike.baidu.com/view/7125.htm

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值