明辉站/网站教程/内容

使用Java 编写手机应用程序(续)

网站教程2024-06-08 阅读
[摘要]█对MIDlet进行调试 编写PalmOS上的Spotlet时,我们可以利用System.out.println()函式帮我们印出一些讯息以帮助调试,那幺在手机上的MIDlet呢? 原则上,我们还是可以利用System.out.println()函式做一些输出。当模拟器执行时,就会在命令列上输出一...
█对MIDlet进行调试

编写PalmOS上的Spotlet时,我们可以利用System.out.println()函式帮我们印出一些讯息以帮助调试,那幺在手机上的MIDlet呢? 原则上,我们还是可以利用System.out.println()函式做一些输出。当模拟器执行时,就会在命令列上输出一些讯息。
另外,在PalmOS上,有KVMutil.prc可以帮助我们纪录程序所输出的讯息。那手机上呢? 因为没有实际的机器可以测试,因此这个问题到现在还不得而知,相信Motorola到时候会有完善的解决方案吧!
在Motorola J2ME SDK内附的说明文件之中,概略地提到了调试的问题,里头提到,往后如果我们要进行机上调试(on-device debugging)的话,必须要满足几个条件:

机器本身要具备调试相关功能,并与KDWP(Kvm Debug Wire Protocol)兼容。因为调试时,调试工具需要利用KDWP和机器上交谈以取得调试信息。
制造厂商本身要提供下载MIDlet到手机上以进行调试的方法。
提供对MIDlet调试的工具,必须支持手机在利用KDWP调试时所使用的传输接口(例如串行口或UDP)。
嗯,看起来能够进行调试,MIDlet程序的编写应该是很方便的事情了。

█Motorola J2ME SDK对中文的支持

相信看过RUN!PC 11月号的文章「利用Java 编写PalmOS应用程序基础篇」的读者,在编写PalmOS上的Spotlet时一定会遇到中文无法正常显示的问题。中文的问题分成两个部分,一个是在用户接口上的中文问题,一个是在命令列输出(利用System.out.println()函式所做的输出)上的中文问题,请大家做个小实验,将前面我们所编写的程序改如下:
HelloMIDlet.java
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class HelloMIDlet extends MIDlet
{
private Display firstDisplay ;
private Form firstForm ;
HelloMIDlet()
{
firstDisplay = Display.getDisplay(this) ;
firstForm = new Form("哈罗!MIDlet") ;
StringItem firstStrItem = new StringItem("哈罗","米德列特") ;
firstForm.append(firstStrItem) ;
System.out.println("MIDlet启动") ;
}

protected void startApp() throws MIDletStateChangeException
{
firstDisplay.setCurrent(firstForm) ;
}

protected void pauseApp()
{
}

protected void destroyApp(boolean unconditional)
throws MIDletStateChangeException
{
}
}
将本MIDlet编译并经过预身审核之后,我们开启模拟器来执行此MIDlet,底下为执行结果:


用户接口输出:命令列输出
 
我们从结果发现,预设的编译指令会让用户接口正常输出中文,而命令列无法输出正确的中文。

我们从结果发现,预设的编译指令会让用户接口正常输出中文,而命令列无法输出正确的中文。

接着请将compileAll.bat之中原本的指令
javac -O -bootclasspath ..\..\lib %COMPILECLASS%
修改为
javac –encoding ISO8859_1 -O -bootclasspath ..\..\lib %COMPILECLASS%
之后,重新编译此MIDlet执行结果:

用户接口输出: 命令列输出
 
我们从结果发现,预设的编译指令会让用户接口无法正常输出中文,而命令列却可以输出正确的中文。

这个结果与PalmOS上所做的中文测试结果有所不同。
当您编写Spotlet时,如果您使用javac 。。。指令时,您会发现模拟器上的用户接口输出是乱码,可是命令列上的输出却可以正常输出中文。但是如果您使用的是javac -encoding ISO8859_1 。。。指令,则CLDC内附模拟器上的用户接口输出或是命令列上的输出全部都变成乱码,无法正常输出中文(这个部分是因为CLDC内附模拟器实做的问题,造成与实际机器的结果有差异)。
总之,如果之前您所编写的Spotlet无法在装有中文系统的实际机器或POSE上正常输出中文,请您也如法炮制,在编译指令中加入-encoding ISO8859_1,就可以在实际机器或POSE上看到正常的中文字了。

会产生此问题的主因,主要是因为编译好的Java类文件(byte code)之中,所有的文字编码都采用UTF8。举例来说,当您在程序码里用到"启动"这两个中文字时,
"起"这个字的Big5编码为B1D2。
"动"这个字的Big5编码为B0CA。
我们会使用javac xxxx.java来编译原始码以产生类文件。其实这行指令,在繁体中文的Windows环境底下,相当于javac -encoding "Big5" xxxx.java。也就是说,当编译器读取到Big5编码范围的中文字时,会自动将此Big5码经过「Big5è Unicode 对照表」将Big5转为Unicode,也就是说,经过查表之后,
“起”这个字的Unicode编码为555F。
“动”这个字的Unicode编码为5272。
然后再利用UTF8编码将此Unicode转为UTF8,储存在类文件之中,因此,如果您用UltraEdit之类的文字编辑器查看类文件时,您会看到,
"起"这个字的UTF8编码为E5959F。
"动"这个字的UTF8编码为E58B95。

接着,当我们在程序执行时如果要将中文输出,则JVM会负责读进UTF8码,然后将其转回Unicode,最后依据您所使用的系统环境预设的编码转回Big5,再输出至屏幕上。
可是经过测试结果,KVM似乎只有做到把UTF8读进来,转换回Unicode之后就直接输出了。少了转回Big5的步骤,因此,操作系统把Unicode当作Big5来处理,自然就找不到该码所对应的中文字了,也因此输出的是一堆 ????? 的符号。这也是我们在PalmOS上即使装了中文系统,也无法正常显示中文的缘故。
OK,既然知道KVM只帮我们做了一半的工作,那事情就好办了,我们只要让UTF8转回之后,仍然保有Big5的编码方式即可,于是我们使用指令javac -encoding ISO8859_1 xxxx.java,请编译器不要将程序码中中文Big5编码的两个byte视为一体(因为视为一体就会引发查询Big5 è Unicode对照表的工作),只要将中文当作是普通的西欧字母字集即可,因此,当我们使用了上述指令,您会发现类文件之中的中文变成,
"起"这个字的UTF8编码为C2B1 C392。
"动"这个字的UTF8编码为C2B0 C38A。
大家可以发现编译器把B1、D2、B0、CA个别当作一个码来处理。于是,当KVM读到此编码时,就会将他们转回B1D2以及B0CA,然后KVM直接输出,就可以正常地使用中文了。

最后总结整个问题,就笔者的推断,CLDC内附的模拟器再没有使用javac –encoding ISO8859_1 xxxx.java指令之前,会在用户接口使命令列输出乱码,这才是正常的结果, 而Motorola J2ME SDK内附模拟器的用户接口中文之所以没问题,很可能只是因为模拟器操作的差异。因此根据KVM的输出结果来看,很可能在实际的手机上,我们都必须加上-encoding ISO8859_1选项才能正确输出中文吧!

在此特别感谢静宜大学资管系的唐恺隆(kailung.tang@msa.hinet.net)同学。因为笔者于他经过热烈的讨论之后,我们才能对J2ME的中文问题有更深入的认识

█支持Motorola J2ME SDK的开发工具

在编写本文的时候,支持MIDlet开发的集成开发环境(IDE)只有Motorola J2ME SDK附带文件之中所提到的CodeWarrior而已。相信其它厂商,如Borland,应该也会很快地利用其产品JBuilder的OpenTools API来支持MIDlet的开发才对,更何况Borland JBuilder目前已经有Spotlet的解决方案了。
因为笔者无法拿到CodeWarrior作测试,所以无法在此提供大家相关信息,相信如果有机会的话,会另外以专文向大家介绍如何利用CodeWarrior编写MIDlet。
Motorola J2ME SDK附带文件在附录的部分有对利用CodeWarrior开发MIDlet做简单的介绍,相信对初学者来说,已经相当足够了。

█Motorola J2ME SDK内含的辅助开发工具

在Motorola J2ME SDK之中内含三项辅助开发工具,可以便利我们的程序开发工作,它们分别是:

J2ME模拟器(J2ME Emulator)
让您可以在您的PC上模拟Motorola将来会支持J2ME的手机装置。如此一来就可以在PC上直接测试写好的程序。
Bytecode验证器(Bytecode Verifier)
此验证器用来验证类文件(classfile)之中的bytecode不会对存储器做非法的存取。并确认载入虚拟机器的类文件所做的所有动作皆符合Java虚拟机器规格(Java Virtual Machine Specification)。
配置编辑器(Configuration Editor)
让您能够建立或修改device profile。
在Motorola J2ME SDK内附的文件之中对这三个工具有详细的说明,笔者在此就不再赘述了。

█总结

呼!好累人,终于到了该做总结的时候了! 大家以为MIDlet就这样结束了吗?不! MIDlet还有许多好玩的玩意儿呢! 我们将在本系列之后的文章中为大家更深入探讨MIDlet。咱们下次见。

█附录:范例程序

Motorola J2ME SDK之中内附许多有趣的范例,它们位于demo/midlets/目录底下。有兴趣继续精进的读者可以由这些范例学到更多有关MIDlet的深入技巧,由于这些范例的执行画面过大,所以在本文之中就将他们省略,请读者们自行参考说明文件。
这些范例程序有:
Bounce
com.mot.j2me.midlets.bounce.Bounce
PaddleBall
com.mot.j2me.midlets.paddleball.PaddleBall
Scribble
com.mot.j2me.midlets.scribble.Scribble
FontDemo
com.mot.j2me.midlets.tutorials.FontDemo
GraphicsDemo
com.mot.j2me.midlets.tutorials.GraphicsDemo
RecordStoreDemo
com.mot.j2me.midlets.tutorials.RecordStoreDemo
UDP Tutorial Application
com.mot.j2me.midlets.tutorials.UDPReceive
AlertTest
com.mot.j2me.midlets.tests.AlertTest
ChoiceGroupTest
com.mot.j2me.midlets.tests.ChoiceGroupTest
DateFieldTest
com.mot.j2me.midlets.tests.DateFieldTest
FormTest
com.mot.j2me.midlets.tests.FormTest
GaugeTest
com.mot.j2me.midlets.tests.GaugeTest
KeyEventsTest
com.mot.j2me.midlets.tests.KeyEventsTest
TextBoxTest
com.mot.j2me.midlets.tests.TextBoxTest
TextFieldTest
com.mot.j2me.midlets.tests.TextFieldTest
TickerTest
com.mot.j2me.midlets.tests.TickerTest

█网络资源
◎网站
名称 URL
Motorola官方网站 http://www.motorola.com/java/
Metrowerks(CodeWarrior) http://www.Metrowerks.com

……

相关阅读