J2ME入門:建立一個(gè)MIDlets
作者:Jonathan Knudsen,Sing Li
翻譯:rochy
版權(quán)聲明:可以任意轉(zhuǎn)載,轉(zhuǎn)載時(shí)請務(wù)必以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明
原文地址:
http://www.javaworld.com/javaworld/jw-05-2005/jw-0502-midlet.Html
中文地址:
http://www.matrix.org.cn/resource/article/43/43796_MIDlets_J2me.html
關(guān)鍵詞: J2ME MIDlets
移動信息設(shè)備簡表MIDP(Mobile Information Device PRofile)應(yīng)用程序,即MIDlets,它的命名延續(xù)了applets和servlets的風(fēng)格。對于一個(gè)有經(jīng)驗(yàn)的java程序員來說寫MIDlets程序相對容易的多。畢竟編程語言仍是java,而且,MIDP中很多來自java.lang和java.io的基本API和J2SE中的一樣,學(xué)習(xí)新的API(主要來自javax.microedition的)也不是很難。
然而實(shí)際運(yùn)行起來,比起J2SE來,MIDlets顯得稍微復(fù)雜一點(diǎn)。除了基本編譯環(huán)境,MIDlets還需要一些額外的開發(fā)包。完整的編譯過程包含:編輯,源碼,編譯,類包,測試。
為了說明MIDlets的開發(fā)過程,這篇文章將建立和運(yùn)行一個(gè)簡單的MIDlet,讀完這篇文章你應(yīng)該對MIDlet開發(fā)有個(gè)全局上的了解。
工具準(zhǔn)備
MIDlets可以在一般的桌面系統(tǒng)上開發(fā),盡管它本身是專門為小設(shè)備設(shè)計(jì)的。首先你需要從Sun或者其他廠商那里獲得一些工具。記住MIDP只是一種規(guī)范,所有廠商都可以自由選擇自己的實(shí)現(xiàn)方式。現(xiàn)在有很多MIDlet的開發(fā)工具并且一般都是免費(fèi)的。
最主要的工具應(yīng)當(dāng)是sun的MIDP標(biāo)準(zhǔn)實(shí)現(xiàn),它包含一個(gè)預(yù)審工具(preverify tool),一個(gè)MIDP設(shè)備模擬器,部分源碼和說明文檔。可以從sun的官方下載。但通常我們都不用這些標(biāo)準(zhǔn)實(shí)現(xiàn),除非你對MIDlets編譯和打包特別感興趣。(當(dāng)然如果你想要把MIDP運(yùn)行時(shí)環(huán)境移植到一個(gè)新的設(shè)備或者平臺就去深入鉆研吧。)
對于初學(xué)者另外一個(gè)較好用的工具是J2ME 的無線工具包WTK(WirelessToolKit)。WTK中的GUI接口隱藏了多數(shù)的MIDlets實(shí)現(xiàn)和打包細(xì)節(jié),提供了從源碼到實(shí)現(xiàn)MIDlets的簡單方法。而且WTK占用資源很小,可以說是一個(gè)微型的IDE,幾乎不會影響到你的機(jī)器性能。
其他還有很多來自設(shè)備制造商,無線運(yùn)營商,IDE開發(fā)商和一些開源組織的大一點(diǎn)的IDE工具,典型的幾個(gè)列在下面(包含可用鏈接):
Borland JBuilder X Mobile Edition
IBM WebSphere Studio Device Developer
Research In Motion BlackBerry Java Development Environment
Sun Java Studio Mobility
NetBeans IDE 4.x
Eclipse J2ME plug-in
Nokia Developer's Suite for J2ME
實(shí)際上你可以用任何你認(rèn)為合適的開發(fā)工具,不過我們這里建議使用WTK,我們一下的內(nèi)容將以WTK2.2進(jìn)行講解。畢竟其他的IDE都是用WTK作為Plug-in的,這樣一來你的開發(fā)經(jīng)驗(yàn)并不取決于你用的什么工具。在這篇文章里我們將詳細(xì)介紹開發(fā)環(huán)境,開發(fā)工具以及模擬器的詳細(xì)細(xì)節(jié)。
調(diào)試你的MIDlets
上文中提到的任何一款I(lǐng)DE都集成了完整的調(diào)試工具。如果單獨(dú)使用WTK外加一個(gè)文本編輯器,你可以使用System.out.println()方法將調(diào)試結(jié)果在控制臺中輸出,WTK中的控制臺可以顯示給你所有的調(diào)試信息。
編寫代碼
我們?nèi)匀幌裨谄渌h(huán)境一樣編寫代碼:用你最喜愛的文本編輯器編寫擴(kuò)展名為.java的文件。后面我們會給出一個(gè)可以加深你對黑客詞典理解的的MIDlet程序?qū)嵗齁argoneer,主要是在Jargon文件中查找特定的單詞。當(dāng)你在Jargoneer中輸入一個(gè)詞,它會連接到服務(wù)器去查找定義。這個(gè)MIDlet會讓你公司里的黑客朋友覺得你很“cool”哦,呵呵。當(dāng)有人使用一些例如“cruft”或者“grok”等不常見的詞語時(shí),你就可以通過在你的手機(jī)里面輸入它并且在很短的時(shí)間里找到它的解釋。下面就是Jargoneer的完整代碼(你可以到Apress網(wǎng)站下載這個(gè)程序)。
源碼如下:
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Jargoneer extends MIDlet
implements CommandListener, Runnable {
private Display mDisplay;
private Command mExitCommand, mFindCommand, mCancelCommand;
private TextBox mSubmitBox;
private Form mProgressForm;
private StringItem mProgressString;
public Jargoneer() {
mExitCommand = new Command("Exit", Command.EXIT, 0);
mFindCommand = new Command("Find", Command.SCREEN, 0);
mCancelCommand = new Command("Cancel", Command.CANCEL, 0);
mSubmitBox = new TextBox("Jargoneer", "", 32, 0);
mSubmitBox.addCommand(mExitCommand);
mSubmitBox.addCommand(mFindCommand);
mSubmitBox.setCommandListener(this);
mProgressForm = new Form("Lookup progress");
mProgressString = new StringItem(null, null);
mProgressForm.append(mProgressString);
}
public void startApp() {
mDisplay = Display.getDisplay(this);
mDisplay.setCurrent(mSubmitBox);
}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) {
if (c == mExitCommand) {
destroyApp(false);
notifyDestroyed();
}
else if (c == mFindCommand) {
// Show the progress form.
mDisplay.setCurrent(mProgressForm);
// Kick off the thread to do the query.
Thread t = new Thread(this);
t.start();
}
}
public void run() {
String Word = mSubmitBox.getString();
String definition;
try { definition = lookUp(word); }
catch (IOException ioe) {
Alert report = new Alert(
"Sorry",
"Something went wrong and that " +
"definition could not be retrieved.",
null, null);
report.setTimeout(Alert.FOREVER);
mDisplay.setCurrent(report, mSubmitBox);
return;
}
Alert results = new Alert("Definition", definition,
null, null);
results.setTimeout(Alert.FOREVER);
mDisplay.setCurrent(results, mSubmitBox);
}
private String lookUp(String word) throws IOException {
HttpConnection hc = null;
InputStream in = null;
String definition = null;
try {
String baseURL = "http://65.215.221.148:8080/wj2/jargoneer?word=";
String url = baseURL + word;
mProgressString.setText("Connecting...");
hc = (HttpConnection)Connector.open(url);
hc.setRequestProperty("Connection", "close");
in = hc.openInputStream();
mProgressString.setText("Reading...");
int contentLength = (int)hc.getLength();
if (contentLength == -1) contentLength = 255;
byte[] raw = new byte[contentLength];
int length = in.read(raw);
// Clean up.
in.close();
hc.close();
definition = new String(raw, 0, length);
}
finally {
try {
if (in != null) in.close();
if (hc != null) hc.close();
}
catch (IOException ignored) {}
}
return definition;
}
}
編譯MIDlet
寫MIDlets應(yīng)用程序是一種交叉編譯,意味著你要在一個(gè)平臺編譯而在另外一個(gè)平臺運(yùn)行。
具體說就是要在我們自己的電腦平臺上使用J2SE編譯MIDlets,編譯好的MIDlet可以運(yùn)行于移動電話,尋呼機(jī),或者其他支持MIDP的移動信息設(shè)備。只要你將源程序放在正確的目錄下,WTK可以完成所以的細(xì)節(jié)工作。
1 啟動Ktoolbar
2 從工具欄選擇新建工程命令建立一個(gè)新項(xiàng)目。
3 看到WTK提示,輸入Jargoneer作為工程名MIDlet類名。
4 點(diǎn)擊建立工程按鈕,然后“OK”來關(guān)閉工程設(shè)定窗口。
圖示如下:

圖1 新建工程對話框
WTK將工程保存在默認(rèn)目錄/apps下。以下是目錄說明:
<J2ME Wireless Toolkit Directory>
apps
Jargoneer
bin
lib
res
src
將上文源碼命名Jargoneer.java保存到src目錄下,你可以簡單的單擊工具欄上的Build按鈕編譯已經(jīng)打開的MIDlet工程。接著,WTK使用J2SE的編譯器進(jìn)行編譯。一般說來,如果你編譯J2SE程序,classpath環(huán)境變量會指向所有你程序需要聯(lián)系的類。當(dāng)你使用javac命令進(jìn)行編譯文件的時(shí)候,一些例如java.lang的API就會被導(dǎo)入,意思即是說在你的MIDlet中使用了類java.lang.System。那么怎樣才能讓編譯器知道你要使用的是這個(gè)類的MIDP版本而不是J2SE版本呢?其實(shí)我們有一個(gè)命令行選項(xiàng)-bootclasspath,它允許你指出描述你將要使用的基礎(chǔ)API的classpath。這個(gè)選項(xiàng)這個(gè)時(shí)候就用來改變MIDP安裝默認(rèn)的classes目錄。例如如下的命令所示:
javac -bootclasspath/midp/classes Jargoneer.java
如果你的MIDP安裝在不同的路徑,你需要把它調(diào)整到classes路徑下。
預(yù)審類文件
下一個(gè)全新的編譯步驟就是預(yù)審了。由于小設(shè)備的存儲限制,MIDP(確切的說CLDC,即Connected Limited Device Configuration,受限設(shè)備配置簡表)詳細(xì)說明了比特碼的驗(yàn)證被分成兩個(gè)部分,preverify將在設(shè)備以外的那部分起作用。而設(shè)備本身僅僅用來在加載class以前做一些輕松的二次驗(yàn)證工作。如果使用WTK,你完全不用擔(dān)心預(yù)審,你單擊Build的時(shí)候它會幫你自動完成,你甚至都無法意識到。如果你想要了解更多關(guān)于預(yù)審器的東西,就繼續(xù)看下去,否則可以直接跳過這一節(jié)。比特碼驗(yàn)證在java運(yùn)行時(shí)安全模型中是很基礎(chǔ)的步驟。在一個(gè)class被動態(tài)的加載之前,比特碼驗(yàn)證器會檢查類文件以確定它工作正常并且不會對JVM(java Virtual Machine)造成危害。但是同時(shí)完成比特碼驗(yàn)證任務(wù)的代碼又太大了,無法在類似移動電話的小設(shè)備上面運(yùn)行。CLDC執(zhí)行了下面的兩步驗(yàn)證:
1設(shè)備以外的部分,類文件被預(yù)審。執(zhí)行指定的檢查步驟并且把類文件轉(zhuǎn)化成下一步驗(yàn)證器可以輕松操作的格式,同時(shí)預(yù)審器在里面加了一些額外的數(shù)據(jù)。
2設(shè)備上,類加載的時(shí)候執(zhí)行第二步驗(yàn)證。如果類文件沒有被預(yù)審,這一步拒絕執(zhí)行。MIDP參考實(shí)現(xiàn)和WTK包含了一個(gè)叫做預(yù)審器的工具在上面的第一步里面起作用。
預(yù)審器以類文件作為輸入,輸出一個(gè)審查類文件。在使用預(yù)審器之前,你需要設(shè)置classpath到相應(yīng)路徑下,就好像設(shè)置其他類路徑那樣。最后,可以利用參數(shù)-d更改輸出路徑。如果使用預(yù)審器覆蓋一個(gè)已經(jīng)存在的類文件,你可以使用一下所示的命令:
preverify -classpath .;/ midp/ classes -d . Jargoneer
這個(gè)示例中,-d告訴預(yù)審器將預(yù)審類文件寫到正確的目錄下。同時(shí)別忘了要將內(nèi)類(inner class)一同預(yù)審。
注意:像這樣把比特碼驗(yàn)證分開為兩部分存在嚴(yán)重的安全漏洞。設(shè)備應(yīng)該通過安全的方式只從可信的來源下載代碼,因?yàn)橐徊糠直忍卮a是在設(shè)備以外檢查的。攻擊者可能提供看起來已經(jīng)通過驗(yàn)證的惡意代碼,即使它是無法通過J2SE驗(yàn)證器的。而對于MIDP第二步驗(yàn)證來說,它看起來可能是完全正確的并且會被加載和執(zhí)行。
Sun’s J2ME WTK 模擬器
WTK包含了許多不同類型的模擬器,你可以選擇任何一個(gè)測試你的程序。當(dāng)Run按鈕被單擊的時(shí)候,默認(rèn)的模擬器被加載。
WTK設(shè)備
WTK2.2含有一下四個(gè)主要設(shè)備模擬器:
1.DefaultColorPhone,240*320彩屏,下圖2示意。
2.DefaultGrayPhone,108*208黑白屏幕。
3.MediaControlSKIN,類似于默認(rèn)手機(jī)模擬器,108*208caise 屏幕,帶有音樂效果的標(biāo)簽等。
4.QwertyDevice,是個(gè)smartphone,636*235彩屏,一個(gè)小型QWERTY鍵盤。
運(yùn)行MIDlets
sun 的MIDP參考實(shí)現(xiàn)包含一個(gè)名為midp的模擬器。
它模擬一個(gè)圖形MID,一個(gè)移動電話,一些標(biāo)準(zhǔn)按鍵和一個(gè)182*210的屏幕。WTK包含了類似的模擬器,其他第三方模擬器也都差不多。一旦得到預(yù)審類文件,你就可以在模擬器上面運(yùn)行了。模擬器是在J2SE環(huán)境下運(yùn)行的應(yīng)用程序,就像一個(gè)MIDP設(shè)備。它在你電腦屏幕上面顯示為一個(gè)普通的的移動設(shè)備。如果你已經(jīng)將/midp/bin加進(jìn)PATH中,那么就可以在命令行中輸入命令midp Jargoneer來運(yùn)行應(yīng)用程序了。
如果使用WTK,你只要選擇一個(gè)模擬器然后單擊run按鈕就ok了。假設(shè)一切運(yùn)行正常,你會看到類似于下一節(jié)中圖2 示意的那種效果,那么恭喜你,你已經(jīng)成功完成了你的第一個(gè)MIDlet應(yīng)用。
使用模擬器控制
下圖是一個(gè)模擬器的示意圖

圖2 WTK 模擬器
Sun的WTK帶有的模擬器可以模擬很多真實(shí)設(shè)備的功能:
1.一個(gè)小規(guī)格屏幕,一定的輸入容量。
2.兩個(gè)可用的軟鍵(soft button),沒有固定的功能。一般說來,它們各自的功能被顯示在屏幕靠近它們的地方。在MIDlets種,軟鍵用來操作命令。
3.方向鍵提供用戶滾動瀏覽和選擇多項(xiàng)的功能。
4.一個(gè)選擇鍵允許用戶確認(rèn)選擇的項(xiàng)目。
小結(jié)
本文引導(dǎo)讀者做了一次MIDP開發(fā)的觀光。對于編碼,還是和在J2SE環(huán)境下一樣,但是編譯的過程截然不同。首先,源碼必須使用javac的-bootclasspath命令編譯為MIDP識別的文件。其次,類文件必須經(jīng)過命令行工具預(yù)審器的預(yù)審。(在WTK中,這個(gè)步驟是被自動執(zhí)行的,用戶只要點(diǎn)擊build按鈕就好)。而且,在WTK中,應(yīng)用程序可以很輕松的在模擬器上測試。
關(guān)于作者
Jonathan Knudsen是一個(gè)Java開發(fā)人員,也是一位知名作者,其作品包括Wireless Java: Developing with J2ME, 第二版, Mobile Java, The Unofficial Guide to LEGO MINDSTORMS Robots, Learning Java, 以及Java 2D Graphics。Knudsen最初從NeXT OS中的Objective-C開始他的面向?qū)ο缶幊躺模蟛痪镁徒?jīng)歷了在微軟的Visual C++的幾年煉獄般的時(shí)間,并在1996年轉(zhuǎn)向Java。關(guān)于Java及LEGO機(jī)器人,他寫了大量的書。其成績包括5本書,一個(gè)名為“Bite-Size Java”的聯(lián)機(jī)月刊欄目,并在JavaWorld, EXE, NZZ Folio, 以及O'Reilly Network上發(fā)表的一些文章。Jonathan擁有普林斯頓大學(xué)的機(jī)械工程學(xué)的學(xué)位。
1978年在遭遇到計(jì)算機(jī)的bug的困擾后,Sing Li對微機(jī)技術(shù)變得精通起來。他的第一臺PC機(jī)是一個(gè)99美元的COSMIC ELF組裝機(jī),有256字節(jié)的內(nèi)存,以及一個(gè)1位的液晶顯示器。在接下來的二十多年時(shí)間里,Li先后當(dāng)過開發(fā)人員,作家,顧問,演講家,導(dǎo)師,以及企業(yè)家。他的豐富經(jīng)驗(yàn)涉及到分布式架構(gòu),Web應(yīng)用/服務(wù)系統(tǒng),計(jì)算機(jī)與電信集成,以及嵌入式系統(tǒng)。自從Java, Jini以及Jxtar的第一個(gè)alpha版本發(fā)布以來,Li就一直使用它們(并寫這些方面的書及文章)。他既是P2P技術(shù)的傳道者,還是Jxta社區(qū)里的參與人員。
資源
本文是Beginning J2ME, Jonathan Knudsen and Sing Li (Apress, April 2005; ISBN: 1590594797)中第2章"Building MIDlets"的節(jié)選。
http://java.apress.com/book/bookDisplay.html?bID=426
下載本文的源碼:
http://java.apress.com/book/download.html?APRESSESSID=f887f2ef01605e5c12b5f1135e6a37c8
下載MIDP參考實(shí)現(xiàn):
http://java.sun.com/prodUCts/midp/
Sun的J2ME 無線工具:
http://java.sun.com/products/j2mewtoolkit/
Borland JBuilder X 移動版本:
http://www.borland.com/mobile/jbuilder/index.html
IBM WebSphere Studio Device Developer:
http://www-306.ibm.com/software/wireless/wsdd/
Motion BlackBerry Java 開發(fā)環(huán)境的研究:
http://www.blackberry.com/developers/na/java/tools/jde/index.shtml
Sun Java Studio Mobility:
http://wwws.sun.com/software/products/jsmobility/index.html
NetBeans IDE 4.x:
http://www.netbeans.org/
Eclipse J2ME 插件:
http://eclipseme.org/
Nokia 關(guān)于J2ME的Developer's Suite:
http://www.forum.nokia.com/main/0,6566,034-2,00.html
Jargon文件是黑客術(shù)語的全面詞典:
http://www.catb.org/~esr/jargon/
更多關(guān)于加強(qiáng)MIDlets安全性的內(nèi)容, 閱讀 "Secure Data Files Embedded in MIDP applications," Simon Ru (JavaWorld, 2005年5月):
http://www.javaworld.com/javaworld/jw-05-2005/jw-0502-midp.html
J2ME開發(fā)的更多文章,瀏覽JavaWorld主題索引的Java 2 Platform, Micro Edition (J2ME) 部分:
http://www.javaworld.com/channel_content/jw-j2me-index.shtml?
設(shè)備開發(fā)的更多文章,瀏覽JavaWorld主題索引的Devices部分:
http://www.javaworld.com/channel_content/jw-devices-index.shtml (出處:http://www.companysz.com)