利用Java编写手机应用程序PalmOS基础篇

作者:王森

相信大家一定會發現,最近到處都是嵌入式系統(embedded system)的新聞。而目前也已經有不少國內外廠商推出各式各樣的PDA(Personal Digital Assistant,中文叫做個人數位助理)產品。相信大家一走到電腦賣場,只要隨便一看都能發現櫥窗裡所展示的各式各樣造型PDA。而讀者們也會發現周圍越來越多的人隨時隨地使用觸控筆在PDA的螢幕上做他們想做的事情。  為何PDA會成為熱門的話題呢? 根據媒體的說法,由於行動通訊時代的來臨,PDA似乎是能夠造就繼PC之後下一代數位革命的新產品。既然是大家看好前景的產業,當然在一開始市場上就是百家爭銘。從佔有率最高的Palm系列,接著是後來加入的Windows CE,尤其嵌入式Linux(embedded linux)的快速發展更是目前當紅的新聞題材。看來,PDA的戰火將會不停地延長下去。  其實,除了嵌入式Linux之外,很多人可能不知道Java也是另一個嵌入式系統之中很有趣的議題。熟知Java發展歷史的人應該都知道,Java一開始本來就是針對嵌入式系統而設計的,只不過由於因緣機會,遇到了網路蓬勃發展的時代,剛好Java的某些特性又非常適合應用在全球資訊網(WWW)之上。我想很多人大概只聽過Java可以用來撰寫能在瀏覽器上執行的Java Applet、獨立執行的Java應用程式(Java Application)以及專門在伺服器端執行的Java Servlet。而本系列文章所要介紹的主角,則是一種能夠在個人數位助理上執行的Java程式,它的名字就叫做 -- Java Spotlet,是目前大家所能見到Java的第四種應用。

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在其SDK 1.2之後的版本都統稱叫Java 2,而Java 2的規格裡頭將Java分成三種不同範圍的版本,分別是:
  • Java 2 Enterprise Edition(J2EE,Java 2企業版)
  • Java 2 Standard Edition(J2SE,Java 2標準版)
  • Java 2 Micro Edition(J2ME,Java 2 微小版)
其中,我們一般人常說的Java 2 SDK(以前叫做JDK)就是屬於J2SE的範圍。而J2EE則為企業量身定做的一些額外的標準和服務。J2ME則是Java在嵌入式系統上執行Java程式的解決方案,大家所知道最普遍的應用大概就是在 PDA上了。
本篇文章就是在探討如何利用Java來撰寫可以在PalmOS上執行應用程式,因此本文主題完全鎖定在J2ME上。在底下內容之中,我們一律將Java 2 Micro Edition簡寫成J2ME。

為何要用Java開發PDA上的應用程式 ?

由於預期到今後行動通訊時代的來臨,所以通訊相關行業變的前景可期,而除了達成行動通訊的主要工具 -- 手機月來越精巧之外,有更多的廠商相繼投入PDA的生產與開發。本來PDA主要的平台只有PalmOS以及Windows CE,也不知道曾幾何時,開始一大堆公司投入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上的執行速度,這些在底下的文章之中我們都可以清楚地看到。

初見KVM

請各位讀者先到Java Download Center (http://www.sun.com/software/communitysource/j2me/download.html) 下載 CLDC(CONNECTED LIMITED DEVICE CONFIGURATION v1.0)這兩個檔案。
  • j2me_cldc-1_0-src-winsol.zip
  • j2me_cldc-1_0-src-palm_overlay.zip

在下載之前,如果你已經是會員,直接輸入ID與密碼即可下載,否則請先註冊為會員(完全免費)


抓到這兩個檔案之後,請先解開第一個zip檔於根目錄下,這裡我們假設你把檔案解開至C磁碟機中,於是你會發現C磁碟下多了一個目錄叫做j2me_cldc,接著請解開第二檔案至C磁碟機中的j2me_cldc目錄底下,使用覆蓋的方式即可,揭開後會在j2me_cldc底下新增即覆蓋一些檔案和目錄。


在j2me_cldc目錄下的bin子目錄可以發現兩個Palm的可執行檔(.prc檔)分別是KVM.prc與KVMutil.prc,請將這兩個檔案下載到Palm上,你可以在Palm面板上發現這兩個程式的蹤影。其中,KVM.prc就是Java Virtual Machine在Palm上的版本,而KVMutil.prc而是一個輔助工具,具有許多功能可以幫助程式設計師,這些我們都會在稍後的文章之中提及。

安裝這兩個檔案之後,您可以試著分別執行這兩個檔案,如下圖:
從這裡大家可以發現,這兩個程式的執行結果是相同的,因為KVM在沒有執行任何程式的時候,預設會叫出KVMutil。

值得額外跟大家一提的是,CLDC裡頭附上了許多demo用的應用程式,都已經被編譯成.prc檔,它們都被放置在j2me_cldc目錄下的bin目錄底下,請讀者們如果有興趣一試,可以將他們下載到您的Palm上執行。
底下是這些應用程式的執行畫面介紹:
 
到這裡,相信大家都覺得十分新鮮有趣。不過使用Palm IIIc的玩家可能就有點失望了,畢竟在能夠顯示彩色畫面的螢幕上竟然只能顯示單色的程式,的確是一件美中不足的事。為了彌補想要在Palm上撰寫彩色Java程式的程式設計師的缺憾,筆者特地為大家介紹彩色版的KVM - Color KVM,您可以到以下網址找到相關訊息:http://www.kawt.de/ColorKVM.html 找到相關資訊,存網站上可以下載Color KVM的可執行檔,解開後讀者同樣可以發現有兩個.prc檔,分別是KVM.prc與KVMutil.prc,請大家將這兩個檔案下載到您的Palm IIIc上。
以下是一些Color KVM在安裝在Palm IIIc上的畫面。
在Color KVM的網站上,您可以抓到測試彩色用的程式ColorTest_prc.zip,解開後請您下載到您的Palm IIIc上,並執行他,結果如下圖:

如果您把這個ColorTest.prc安裝到只支援單色的KVM上,則會看到下面結果:

聰明的讀者一定會發現,同樣的程式,在只能顯示單色的Palm上執行的時候,會用漸層色顯示出來。

最後附帶一提的是,Color KVM的網站上您會發現有兩種版本的Color KVM,分別是:
  • ColorKVM.zip: The ColorKVM (Build 6, multi PDB) without the ROMized kAWT classes.
  • ColorKVM_kAWT090ROMized.zip: The ColorKVM (Build 6, multi PDB) with a ROMized version of kAWT v0.90. It is not necessary to add the kawt.pdb file to run the KawtSample or any other kAWT application.
如果讀者們要減少麻煩,請下載 ColorKVM_kAWT090ROMized.zip,由上面的說明大家可以知道,這兩個檔案的差別在於一個有內附kAWT而另外一個沒有。那麼什麼事kAWT呢? 撰寫過Java程式的人應該都利用過AWT(Abstract Window Tookit)來設計Java程式的圖形使用者介面(GUI),而kAWT就是AWT在Palm上的版本,目的也是讓程式設計師更方便地在Palm上面產生如Button、Combo Box、Edit Box之類的元件。當然,內附kAWT的Color KVM所佔的記憶體容量會大些。
接下來,我們要開始撰寫撰寫程式囉!相信讀著們已經摩拳擦掌準備一試身手了, Are you ready? Let’s go!

解決方案

當筆者撰寫此篇文章的時候,利用J2ME在Palm之上撰寫Java程式的方法大致上有以下三種:
  1. 直接利用Java 2 SDK配上Sun的CLDC套件
    http://www.sun.com/software/communitysource/j2me/download.html
  2. 使用JBuilder配合Sun的CLDC套件
    http://www.inprise.com/jbuilder/
  3. Visual Age for Java 配上自己的J2ME套件
    http://www-4.ibm.com/software/ad/vajava/
不過在本文中,我們只針對Java 2 SDK配上Sun的CLDC套件之解決方案來做討論,這是幫各位讀者打好基礎的最佳方式,一旦基礎打好,使用工具來協助開發都是很容易的事情。至於其他的解決方案,我們將會在本系列今後的文章裡頭做詳盡的探討,請有興趣的讀者可以放心。

先期準備工作

工欲善其事,必先利其器。因此在我們開始寫Palm上的Java程式之前,我們必須先花點時間準備好我們程式的執行環境以及編譯環境。順便我們也討論一下Palm上Java程式的撰寫流程。
■ 準備程式執行環境
在前面已經跟大家介紹過如何安裝KVM,在這裡筆者再簡單地跟讀者簡短說明:
請各位讀者先到Java Download Center (http://www.sun.com/software/communitysource/j2me/download.html) 下載 CLDC(CONNECTED LIMITED DEVICE CONFIGURATION v1.0)這兩個檔案。
  • j2me_cldc-1_0-src-winsol.zip
  • j2me_cldc-1_0-src-palm_overlay.zip

在下載之前,如果你已經是會員,直接輸入ID與密碼即可下載,否則請先註冊為會員(完全免費)

抓到這兩個檔案之後,請先解開第一個zip檔於根目錄下,這裡我們假設你把檔案解開至C磁碟機中,於是你會發現C磁碟下多了一個目錄叫做j2me_cldc,接著請解開第二檔案至C磁碟機中的j2me_cldc目錄底下,使用覆蓋的方式即可,揭開後會在j2me_cldc底下新增即覆蓋一些檔案和目錄。
在j2me_cldc目錄下的bin子目錄可以發現兩個Palm的可執行檔(.prc檔)分別是KVM.prc與KVMutil.prc,請將這兩個檔案下載到Palm上,你可以在Palm面板上發現這兩個程式的蹤影。
■ Palm上Java程式的撰寫步驟

撰寫Palm上的Java程式和一般的步驟相同,如圖:
  1. 撰寫程式原始碼
  2. 編譯
  3. 預先審核(Preverify)
  4. 測試與除錯
  5. 散佈
各位讀者比較會感到奇怪的地方在第三個步驟 - 預先審核,這個步驟可能會讓大家覺得有些疑惑。因為在各位撰寫Java Applet或是Java Application的時候從未做過這個步驟。其實,這個步驟很容易就可以完成,不像它的名稱看起來那麼地複雜。
為了讓讀者們更清楚這個動作的用意,請大家看看下面這張圖,這是一張傳統Java Applet或是Java Application由撰寫到執行的細部動作示意圖:


在傳統的Java程式之中,為了安全上的理由,任何載入JVM 的class檔在進入執行環境執行之前,都必須經過Byte code verifier的驗證,以防止有人在程式散佈途中遭到惡意的修改,而使得程式執行後對系統有不良影響。

這個審核的動作在一般的PC上執行,在速度倒是還能夠接受,可是一旦放到Palm這種使用較慢CPU的機器上面就顯得有點吃力了。為了節省寶貴的CPU運算時間(既能省電又能夠讓使用者早點看到程式畫面),因此,在程式設計師產生能夠讓KVM執行的class檔之前,先在PC上做一些前置的驗證工作(比方說加入一些特殊標記或符號),如此一來就可以大幅減少將來在Palm上做驗證時CPU的負擔,如此一來也可以加速程式的的啟動時間。

請大家回顧一下,在我們執行每一個CLDC所附的demo程式之前,我們都會看到KVM的啟動畫面如下:

從畫面中大家可以清楚的發現,當KVM做好初始化動作之後,接著會讀進我們用Java寫成的.prc檔,再來從.prc檔之中讀進byte code檔,最後就是再做一次審核(verify)的動作,只不過這個審核的動作因為有預先審核的關係,速度變的比傳統的Java程式要來的快。希望到這個地方,讀者們可以對整個程式開發步驟有個概觀的認識。
■ 準備程式編譯環境
首先,請先安裝Java 2 SDK(請用1.2.2以上的版本。目前最新版本為1.3,請至www.javasoft.com下載)。
最後,要開始撰寫程式之前,我們必須還要建立自己的工具和類別,這個地方讓人覺得很奇怪,為什麼Sun不直接提供可用的工具和類別呢? 總之每個人都有自己的答案,在這裡我們就不討論了,但是我們還是要自己動手輸入指令,否則接下來的工作都不能做了。
底下我們接假設您的CLDC裝在c:/j2me_cldc這個目錄之下
請在命令模式底輸入指令:
 cd c:/j2me_cldc/tools/palm/src/palm/database
我們要把這個目錄下的所有java全部編譯成class檔,接著要放到CLDC類別目錄底下。所以請鍵入:
 javac -d c:/j2me_cldc/bin/api/classes/ *.java
如果您使用的是Java SDK 1.3,則螢幕上會出現一些錯誤,意思大致上是說程式裡頭用了一些不再建議使用的API(deprecation)為了避免這個錯誤,請改用以下指令
 javac -deprecation -d c:/j2me_cldc/bin/api/classes/ *.java
額外跟各位一提的是,如果您在Windows 98底下進行CLDC的準備工作,您很可能遇到底下一大串錯誤訊息:
C:/j2me_cldc/tools/palm/src/palm/database>javac -d c:/j2me_cldc/bin/api/classes *.java java.lang.StringIndexOutOfBoundsException: String index out of range: -32
 at java.lang.String.charAt(String.java, Compiled Code)
at sun.io.ByteToCharMS950.getUnicode(ByteToCharMS950.java:39)
at sun.io.ByteToCharDoubleByte.convert(ByteToCharDoubleByte.java:115)
at java.io.InputStreamReader.convertInto(InputStreamReader.java:127)
at java.io.InputStreamReader.fill(InputStreamReader.java:176)
at java.io.InputStreamReader.read(InputStreamReader.java:239)
at java.io.Reader.read(Reader.java:104)
at sun.tools.java.ScannerInputReader.read(ScannerInputReader.java:127)
at sun.tools.java.Scanner.useInputStream(Scanner.java:166)
at sun.tools.java.Scanner.(Scanner.java:151)
at sun.tools.java.Parser.(Parser.java:59)
at sun.tools.javac.BatchParser.(BatchParser.java:61)
at sun.tools.javac.BatchEnvironment.parseFile(BatchEnvironment.java:465)

at sun.tools.javac.Main.compile(Main.java:489)
at sun.tools.javac.Main.main(Main.java:733)
error: An exception has occurred in the compiler; please file a bug report (http ://java.sun.com/cgi-bin/bugreport.cgi).
1 error



這是因為編碼的問題而導致的錯誤,請大家嘗試改用底下指令即可解決上述問題:
 javac -deprecation -encoding "ASCII"-d c:/j2me_cldc/bin/api/classes/ *.java
在此特別感謝 HUB同學(海大資科無敵男子漢,hublin@kimo.com.tw )的熱情協助,上述的解法由他所提供。
最後,請將c:/j2me_cldc/tools/palm/src/palm/database底下的兩個檔案: Wrapper.prc 和 DefaultTiny.bmp拷貝到c:/j2me_cldc/bin/api/classes/palm/database之下。注意,如果您在拷貝這兩個檔案時發現並沒有c:/j2me_cldc/bin/api/classes/palm/database這個目錄,那一定是您在上個指定輸入錯誤,否則這個目錄會自己建立。
完成了以上的準備工作之後,我們就要開始撰寫我們的第一個Palm上的Java程式了。

第一個Palm上的Java程式

 
■ 程式外觀
請大家先預覽一個能在Palm上執行的簡單Java程式,程式如下:
 

import com.sun.kjava.*;


public class HelloWorld extends Spotlet
{
//用來關閉程式的按鈕 Button exitButton;
// 取得Grpahic物件,以便繪圖之用
static Graphics g = Graphics.getGraphics();

//動態產生一個Spotlet, 並註冊事件處理函式.
public static void main(String[] args)
{

HelloWorld hw = new HelloWorld() ;
hw.register(NO_EVENT_OPTIONS);
}

public HelloWorld()
{
exitButton = new Button("Goodbye World",70,120);
paint();
}

private void paint()
{
g.clearScreen();
g.drawString("Hello World",60, 80);
exitButton.paint();
}

/*
當觸控筆觸碰液晶螢幕,就會引發pen down事件,
接著叫用以下事件處理函式
*/

public void penDown(int x, int y)
{
// 確認筆按下的位置在按鈕的邊界之內
if (exitButton.pressed(x,y))
{
System.exit(0);
}
}
}


■ 編 譯
為了編譯方便,請讀者先行新增一個批次檔,名為palmjavac.bat,其內容如下:
 javac -g:none -classpath c:/j2me_cldc/bin/api/classes;. -bootclasspath c:/j2me_cldc/bin/api/classes %1
請注意,實際上在批次檔中這兩行要連在一起,所以會發生javac.exe無法編譯的情形。
當palmjavac.bat完成之後,我們只要在命令列下打入:
 palmjavac HelloWorld.java
之後您就會在目錄底下看到編譯過後的HelloWorld.class。
■ 預先審核
為了預先審核方便,請讀者再先行新增一個批次檔,名為palmver.bat,其內容如下:
 c:/j2me_cldc/bin/preverify -classpath c:/j2me_cldc/bin/api/classes;. %1
請注意,因為排版的關係,所以把指令分成兩行,實際上在批次檔中這兩行要連在一起,所以會發生preverify.exe無法正確執行的情形。
當palmver.bat完成之後,我們只要在命令列下打入:
 palmver HelloWorld
之後您就會在目錄底下發現新產生了一個名為output的目錄,裡頭存放的正是經過預先審核的HelloWorld.class。
■ 測試
為了測試方便,請讀者再新增一個批次檔,名為palmtest.bat,其內容如下:
 c:/j2me_cldc/bin/kvm -classpath c:/j2me_cldc/bin/api/classes;./output %1
請注意,因為排版的關係,所以把指令分成兩行,實際上在批次檔中這兩行要連在一起,否則會發生kvm.exe無法正確執行的情形。
當palmtest.bat完成之後,我們只要在命令列下打入:
 palmtest HelloWorld
就會叫出CLDC內附的Palm模擬器(比起正式的模擬器來說,這個內附的模擬器比較陽春)接著您會在螢幕上看到如下畫面:

使用滑鼠在 Goodbye World 這個按鈕上按下滑鼠左鍵,此程式就會關閉。

其實這個CLDC內附的模擬器可以幫我們輸出一些程式執行時期的相關資料。如果您想要觀看,請將palmtest.bat的內容修改如下:

 c:/j2me_cldc/bin/kvm -verbose -classpath c:/j2me_cldc/bin/api/classes;./output %1 >> result.txt
請注意,因為排版的關係,所以把指令分成兩行,實際上在批次檔中這兩行要連在一起,否則會發生kvm.exe無法正確執行的情形。

這樣您就能夠在程式執行之後,打開result.txt觀看KVM所輸出的一些訊息,如果您要直接讓這些訊息輸出到螢幕上,請將palmtest.bat裡頭的">>result.txt"拿掉即可。下面是HelloWorld執行時螢幕上所輸出的資訊:
 GC heap size: 150000 bytes
Loading version information
Loading constant pool
Loading class info
Class info ok
Loading interfaces
Loading fields
Loading extra attributes
Extra attributes loaded
Fields loaded ok
Loading methods
Method ’main’
Method ’< init >’
Method ’paint’
Method ’penDown’
Method ’< clinit >’
Methods loaded ok
Loading extra attributes
Extra attributes loaded
Closing classfile
Class loaded ok
Invoking static initializer
Invoking static initializer
Invoking static initializer
Invoking static initializer
Invoking static initializer
Invoking static initializer
Invoking static initializer
這些訊息對於程式設計師在對程式除錯的時候會發揮相當的作用。
■ 程式散佈
在測試階段,kvm.exe所使用的是經過預先審核的class檔。但是實際上Palm上所執行的程式都是.prc檔,為了要讓我們的程式可以在別人的Palm上執行,所以最後一個步驟就是要把我們的class檔轉換成prc檔。
要執行最後這個步驟,我們必須借助在之前我們所編譯出來的相關工具,這個工具名為 MakePalmApp.class。
為了轉換方便,請讀者新增一個批次檔,名為palmapp.bat,其內容如下:
 java -cp c:/j2me_cldc/bin/api/classes palm.database.MakePalmApp -v -bootclasspath c:/j2me_cldc/bin/api/classes %1
請注意,因為排版的關係,所以把指令分成三行,實際上在批次檔中這三行要連在一起,否則會發生palm.database.MakePalmApp無法正確執行的情形。
當palmapp.bat完成之後,我們只要在命令列下打入:
 palmapp HelloWorld
螢幕上會出現下列訊息:
 HelloWorld
HelloWorld"
Small icon
Generating output file "HelloWorld.prc".
表示轉換過程成功
(請注意,預先審核過的HelloWorld.class要和palmapp.bat放在相同目錄下,否則螢幕上會出現ERROR: java.io.IOException: Cannot find file HelloWorld.class的錯誤訊息。)


這個時候您就會看到output目錄下產生了一個名為HelloWorld.prc的檔案,這就是我們所需要能在Palm上執行的程式了。請將這個檔案下載到您的Palm上,您會在Palm的螢幕上看到如下:
用觸控筆在上面輕點一下,就會看到下面畫面:
今後如果讀者們要將您使用CLDC所撰寫的Java程式分享給大家時,只要提醒使用者在他們的Palm上裝上KVM.prc,至於KVMutil.prc因為是用來協助程式設計師除錯用的工具,所以使用者可裝可不裝。之後程式設計師只要將您自己做好的的.prc檔給使用者即可。如果使用者的電腦上沒有裝上KVM.prc,則會出現下面畫面:

請諸位讀者在散佈您的程式時務必注意。
■ 除錯
寫程式的人都知道,程式很容易寫,但是bug卻很難除,在我們開發PC用的應用程式時,已經有非常優秀的除錯工具可以幫助我們除錯,但是在Palm上,以目前來說似乎沒有什麼比較有效的除錯工具。於是想起過去在螢幕上列印出一些訊息以協助除錯的日子。當我們在PC上Java Application的時候,我們可以利用System.out.println()這個函式幫我們在螢幕上輸出資料。
那麼在Palm上也可以這樣做嗎? 答案是肯定的。 如果可以,那資料都輸出到哪裡了呢? 嘿嘿!! KVMutil派上用場的時機到了。 請在您的Palm執行KVMutil這隻程式,並設定Screen Output的值,也就是說最多可以輸出13行
一旦這樣設定之後,您就可以在程式裡頭使用System.out.println()函式來輸出資料。
我們把之前的HelloWorld.java改寫成下面的樣子:
 import com.sun.kjava.*; public

class HelloWorld extends Spotlet
{
//用來關閉程式的按鈕
Button exitButton;
// 取得Grpahic物件,以便繪圖之用
static Graphics g = Graphics.getGraphics();

//動態產生一個Spotlet, 並註冊事件處理函式.
public static void main(String[] args)
{

System.out.println("HelloWorld Start") ;
HelloWorld hw = new HelloWorld() ;
hw.register(NO_EVENT_OPTIONS);
}

public HelloWorld()
{
exitButton = new Button("Goodbye World",70,120);
paint();
}

private void paint()
{
g.clearScreen();
g.drawString("Hello World",60, 80);
exitButton.paint();
}

/*
當觸控筆觸碰液晶螢幕,就會引發pen down事件,
接著叫用以下事件處理函式
*/

public void penDown(int x, int y)
{
System.out.println("Pen Down") ;
// 確認筆按下的位置在按鈕的邊界之內
if (exitButton.pressed(x,y))
{
System.exit(0);
}
}
}
程式執行之後,重新執行KVMutil,並按下 < View output >,就可以看到 HelloWorld所輸出的訊息,如下圖:

如果您是使用POSE(請參考附錄,對POSE會有詳盡的說明)執行KVM的話,您會在POSE所在的路徑之下發現兩個檔案,分別是STDOUT.txt與STDERR.txt,裡頭存放的內容正是前面這兩張圖裡頭所看到的文字內容。



眼尖的讀者會發現,KVMutil裡有個選項叫做Show heap stats,如下圖:



當您點選了這個選項之後,每當您的程式執行之前,KVM都會對Heap的情形做出回報,底下是HelloWorld執行前KVM出現的訊息視窗:



如果一開始設定了Save Output,而後來卻砍掉KVMutil.prc,那您的KVM.prc在執行時結果將會如下圖:


相信有了KVMutil的協助,一定可以幫助大家在程式寫作的路上更順手。

程式解說

相信有撰寫過Java Applet或是Java Servlet的讀者們都有知道,要製作Java Applet,就必須繼承自java.applet這個類別,要製作Java Servlet,則程式必須繼承自javax.servlet.http.HttpServlet這個類別。同理,要能夠在KVM上頭執行的Java Spotlet也必須要繼承自com.sun.kjava.Spotlet 。 因此一個Java Spotlet的程式外觀如下:
 import com.sun.kjava.*;
public class HelloWorld extends Spotlet
{
public static void main(String[] args)
{
}
}
Spotlet被KVM載入之後,就會開始接收一些基本的事件(event)並做出回應,Spotlet對待事件的方式與一般的GUI程式是有所區別的。寫過Applet的人都知道,畫面上的所有元件之間訊息傳遞都遵循著Java事件模型的機制在運作,但是在Spotlet上對於事件的處理有了本質上的改變。在Spotlet上,整個畫面被當作是一塊很大的是視窗,而不像PC上的視窗系統一個主視窗是由好幾個小視窗所構成。舉個例子來說,當Spotlet接收到觸控筆按下的時候,Spotlet就會呼叫相對應的事件處理函式(event handler),如下:
 public void penDown(int x, int y)
{

}
如果是在Applet之中,我們就必須在事件處理函式先判定事件的來源為何,是Button?還是其他GUI元件,可是在Spotlet裡並非如此,我們必須自己手動判動觸控筆所按下的位置是否在元件之中,所以程式如下:
 public void penDown(int x, int y)
{
if (testButton.pressed(x,y))
{
/*對應的程式碼*/
}
}
這是Spotlet與Applet在事件處理上很大的一個不同。
另外,在Applet裡頭,要讓GUI元件與事件處理函式產生關聯,就必須要利用addXXXXListener函式來註冊,而這個函式的參數必須要是一個實做了XXXXListener介面的物件才行,這是整個Java事件模型裡頭委派機制的最重要部分。然而在Spotlet裡頭就簡單很多,只要呼叫Spotlet類別的register函式,並傳給適當的參數即可。在我們之前的範例裡頭,用了以下的程式碼做註冊:
 HelloWorld hw = new HelloWorld() ;
hw.register(NO_EVENT_OPTIONS);
比起Applet,Spotlet的寫法簡單許多。之所以要儘量簡化Spotlet的程式結構,是因為過多的函式呼叫和複雜的訊息傳遞機制,會造成程式過大,執行起來速度也會太慢,有相當多方面的考量。
當然,由於Palm本身的硬體限制,Spotlet所能展現的GUI無法如同在PC上使用AWT來撰寫GUI程式那樣的漂亮,GUI元件自然也無法像PC上提供的那麼多采多姿。但是com.sun.kjava.* 這個package裡頭還是提供了不少非常基本而有用的元件(widgets)比方說Dialog、 Button 、Bitmap等等。
接下來講到paint這個函式,熟悉Applet的朋友都知道,AWT裡頭的元件都會有個叫做paint的函式,函式原型如下:
 private void paint(Graphics g)
每次畫面要重畫的時候,Container會自動呼叫自己內部的所有元件,並呼叫他們的paint函式,並傳給這個函式一個可以用來繪圖的畫布,所以每個元件只要取得這個畫布,就可以利用它做一些基本的繪圖。不過,在Spotlet裡頭並沒有這樣的機制,螢幕上的所有繪圖都要由我們一手包辦,在此,我們將繪圖函式的原型做點修改如下:
 private void paint()
也就是說,Spotlet的paint函式並不會得到一個Graphics物件以供繪圖使用,因為系統並不會呼叫paint函式,這個部分我們將在往後的文章中再和大家說明。我們必須改用Graphics物件的getGraphics函式來取得繪圖用的畫布,之前我們的範例程式如下:
 static Graphics g = Graphics.getGraphics();
任何時候我們需要在畫面上繪圖時,只要直接使用利用Graphics.getGraphics()所取得的Graphics物件來作畫即可。
在Applet之中,我們會呼叫Container的add函式,並傳入一個GUI物件當作參數,藉此連繫GUI物件與其Container的關係。可是由於在Spotlet並沒有這種Container與其內部元件的從屬關係,因此每次畫面重畫,呼叫Spotlet的paint函式之時,我們必須自己手動叫元件自己把自己畫在螢幕上,在我們的範例程式裡頭如下:
 private void paint()
{
g.clearScreen();
g.drawString("Hello World",60, 80);
exitButton.paint();
}



手動呼叫 Button的 paint函式
最後要跟讀者們提醒的是:雖然Java Applet以及Java Spotlet都屬於Java程式,但是充其量也只是代表他們是以"Java"來撰寫程式罷了,實際上的程式架構還是會依照他們的特殊定位而有所不同。所以同樣是撰寫GUI程式,但是程式流動的方向和概念有時候是相差慎選的。Palm上的應用程式有其獨特的風格,程式設計師在撰寫Palm應用程式時,也不能拿撰寫PC上應用程式的思考模式來撰寫,畢竟,Palm只是一台功能有限的機器,在Palm的世界裡,一點一滴的記憶體都是十分寶貴的,太花俏的GUI只會佔據太多的記憶體,佔據CPU大量的運算週期,也讓小小的螢幕看起來更加複雜,在Palm的世界裡一點都不實用。因此,請大家秉持著新的程式撰寫觀念進入Palm的世界。下一次我們將繼續深入Spotlet的世界,有機會的話我們還會深入KVM的核心,敬請期待,咱們下次見。Bye bye!

附錄:利用Palm模擬器測試我們所撰寫的Java程式

上面我們所討論的程式都是把程式直接下載到Palm上可是萬一讀者沒有Palm呢? 除了建議大家去買一台之外,另外的解決方案就是利用模擬器。除了CLDC內附的陽春模擬器之外(只能執行.class檔),推薦大家使用的就是POSE了。POSE 是 Palm OS Emulator 的縮寫,即Palm OS模擬器的意思。跟一般遊樂器的模擬器一樣,它能夠在您的電腦模擬出 Palm OS 的作業環境,就如同真的在使用 Palm 一樣。開發Palm應用程式的程式設計師都應該安裝POSE才對,除了可以用來測試或除錯開發中的軟體,安裝POSE也會省下程式設計師很多的時間,畢竟老是把程式下載到Palm再執行,會花掉許多時間的! 一般的使用者也可以安裝一套模擬器,直接在電腦上試用剛剛從網路上抓到的一堆軟體,既方便又簡單。對於沒有預算購買Palm的朋友們也可以先用來『聞香』一番,體驗一下 Palm 的操作介面與使用環境。所以POSE對於Palm的愛用者實在有著莫大的功勞。
目前,網路上已經有十分出色的文章在介紹有關模擬器的安裝與使用,請讀者們親自到PalmFab網站上觀賞這些文章:
相信會受益良多。
注意,當您用POSE載入模擬器的時候,預設的RAM大小只有1024K,對於KVM來說,這是不夠用的,請將RAM大小調成8192K,否則我們所撰寫好的程式無法順利執行。

附錄:相關資源

其實在各位解開CLDC的時候,裡面就已經內附了許多值得參考的文件了,請讀者們可以到c:/j2me_cldc/docs底下尋寶一番。光是讀完這些文件就足夠讓各位功力大增。
如果大家還是覺得不滿足,網路是個擁有無窮資源的地方,各位讀者可以參考以下資源去找尋資料,相信一陣瀏覽之後,會對本篇文章所討論的東西更加清楚才對:
■ Web Site
資源蒐集網站
官方網站
技術網站
■ Mail List
技術
阅读更多

没有更多推荐了,返回首页