Java嵌入式開發(fā)之二(中) [轉(zhuǎn)自yesky]
發(fā)表時(shí)間:2024-06-21 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]第四節(jié) 談?wù)凧2ME簡表 雖然配置為一組通用設(shè)備提供了最小的 Java平臺(tái),但是應(yīng)用程序開發(fā)者感興趣的是為一個(gè)個(gè)別的設(shè)備生產(chǎn)應(yīng)用程序,當(dāng)他們只是使用配置的話,他們編寫的應(yīng)用程序就會(huì)有一些欠缺。 配置必須滿足所有的設(shè)備的最小的要求, 用戶界面、輸入機(jī)制和數(shù)據(jù)持久性有高度地設(shè)備具體性,每一種設(shè)備都有...
第四節(jié) 談?wù)凧2ME簡表
雖然配置為一組通用設(shè)備提供了最小的 Java平臺(tái),但是應(yīng)用程序開發(fā)者感興趣的是為一個(gè)個(gè)別的設(shè)備生產(chǎn)應(yīng)用程序,當(dāng)他們只是使用配置的話,他們編寫的應(yīng)用程序就會(huì)有一些欠缺。 配置必須滿足所有的設(shè)備的最小的要求, 用戶界面、輸入機(jī)制和數(shù)據(jù)持久性有高度地設(shè)備具體性,每一種設(shè)備都有自己的用戶界面、輸入機(jī)制和數(shù)據(jù)存儲(chǔ)方法,這些往往不在配置所滿足的最小要求的范圍之內(nèi)。
簡表為相同消費(fèi)電子設(shè)備的不同的生產(chǎn)商提供了標(biāo)準(zhǔn)化的 Java類庫, 事實(shí)上,雖然配置規(guī)范的開發(fā)由 Sun領(lǐng)導(dǎo),但是許多簡表規(guī)范仍將繼續(xù)由特殊設(shè)備的供應(yīng)商領(lǐng)導(dǎo)。 比如說, Motorola領(lǐng)導(dǎo)了行動(dòng)電話和呼叫器簡表規(guī)范的開發(fā),又如 Palm 領(lǐng)導(dǎo) PDA簡表的開發(fā)。
現(xiàn)在,五個(gè)已知簡表已經(jīng)有了規(guī)范, 記住,每個(gè)簡表的責(zé)任都是為了完善配置的不足,下表列出了這五個(gè)簡表:
簡 表 完善配置
Mobile information devices profile (MIDP) 移動(dòng)電話和呼叫器 CLDC
Personal digital assistant profile Palm和Handspring的PDA 設(shè)備 CLDC
Foundation profile 用于所有不需要GUI的CDC設(shè)備的標(biāo)準(zhǔn)簡表 CDC
Personal profile 替代PersonalJava的Foundation完善的簡表 CDC
RMI profile提供RMI的Foundation完善的簡表 CDC
現(xiàn)在我想談一談另一個(gè)Java類庫集,它現(xiàn)在差不多可以被認(rèn)為是另一個(gè)簡表了。當(dāng)Sun為Palm開發(fā)第一個(gè)KVM時(shí),他們需要一組類來 開發(fā)Palm的演示程序。這套類庫被封裝進(jìn) com.sun.kjava程序包, 在 CLDC早期的開發(fā)中,這些類被廣泛的使用來測試和演示 J2ME。因?yàn)?kjava是唯一的允許應(yīng)用程序開發(fā)者使用 J2ME和 KVM開發(fā)應(yīng)用程序的類,所以它就被廣泛使用了。甚至到了今天,一個(gè)用于 PDA或更特殊一點(diǎn)的 Palm的簡表多已經(jīng)在開發(fā)中,許多開發(fā)者仍然希望使用 kjava類來開發(fā) PDA應(yīng)用程序。盡管 kjava類不被支持,并且僅僅用于設(shè)計(jì)測試程序或演示程序,并且它們將被一個(gè)即將到來的簡表所替代,但是開發(fā)者們?nèi)匀粺嶂杂谑褂盟鼇黹_發(fā)。
MIDP
Mobile Information Device Profile(移動(dòng)信息設(shè)備簡表 ,簡稱 MIDP ),第一個(gè)實(shí)現(xiàn)的簡表,補(bǔ)充了 CLDC并且提供應(yīng)用程序語義和控件、用戶界面、持久存儲(chǔ)器、網(wǎng)絡(luò)和用于移動(dòng)電話的計(jì)時(shí)器、雙通道呼叫器和其他無線電設(shè)備。 因?yàn)?MIDP和 CLDC兩者都有引用實(shí)現(xiàn),我們可以使用一個(gè)例程來研究一下這個(gè)簡表。
下面的例子是一個(gè)允許用戶輸入代表想知道的基金報(bào)價(jià)的代號(hào)的例子。應(yīng)用程序然后通過 HTTP接到一個(gè)金融網(wǎng)站,獲得基金報(bào)價(jià),把價(jià)格儲(chǔ)存在一個(gè)數(shù)據(jù)庫,然后把價(jià)格返回給用戶。
// 到如需要的J2ME類
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
// 擴(kuò)展MIDlet類來構(gòu)建我們的自定義MIDlet
public class FundTracker extends MIDlet implements
CommandListener {
file://顯示管理者變量
private Display display = null;
file://MIDlet的表單變量
private RequestForm reqForm = null;
file://MIDlet構(gòu)建器
public FundTracker () {
display = Display.getDisplay(this);
reqForm = new RequestForm("Fund Tracker");
reqForm.initForm();
reqForm.setCommandListener(this);
}
file://開始 MIDlet 應(yīng)用程序
protected void startApp() {
display.setCurrent(reqForm);
}
file://暫停 Midlet
protected void pauseApp() {
}
file://銷毀Midlet
protected void destroyApp(boolean unconditional) {
}
file://通過監(jiān)聽者響應(yīng)命令
public void commandAction(Command c, Displayable s) {
if (c == reqForm.getExitCommand()) {
destroyApp(false);
notifyDestroyed();
return;
}
if ((c == reqForm.getGetCommand()) &&
(reqForm.getSymField().getString().length() > 0)) {
getAndDisplayQuote();
} else
{
reqForm.getMsgString().setText("Symbol required");
}
}
file://儲(chǔ)存由#分開的成對(duì)的基金字符串和報(bào)價(jià)字符串
private void storeQuote (String fund, String newQuote) {
file://數(shù)據(jù)庫變量
RecordStore quoteDB = null;
try {
quoteDB = RecordStore.openRecordStore(
"FundQuotes", true);
byte[] data = (fund + "#" + newQuote).getBytes();
int size = data.length;
quoteDB.addRecord(data, 0, size);
quoteDB.closeRecordStore();
}
catch (Exception recordException) {
System.out.println("Unable to store quote and/or
use Fund Quote database.");
}
}
file://通過QuoteService類取回提交的代號(hào)表示的基金報(bào)價(jià)
private void getAndDisplayQuote(){
String fundSymbol = reqForm.getSymField().getString();
if (fundSymbol.length() > 0) {
String theQuote = QuoteService.getQuote(fundSymbol);
if (theQuote != null) {
storeQuote(fundSymbol, theQuote);
reqForm.getMsgString().setText(theQuote);
}
else
reqForm.getMsgString().setText("No quote" +
'\n' + "Check Symbol");
}
}
}
MIDP應(yīng)用程序稱為 MIDlet, 為了創(chuàng)建一個(gè) MIDlet,你必須寫一個(gè)擴(kuò)展基本 MIDlet類的類 (就像我們在上面代碼段中列出的那樣)。 這有點(diǎn)類似常見的 applet或 servlet。 MIDlets獨(dú)有的東西是把多個(gè) MIDlet組成一個(gè) MIDlet套件的能力。 這就允許 MIDlet在一個(gè)單獨(dú)的 JVM環(huán)境中共享資源,比如一個(gè)數(shù)據(jù)庫等等。 事實(shí)上,我們上面給出的例子還包括一個(gè) MIDlet ( RetrieveQuote,見上段程序),用于取回所報(bào)價(jià)格。 當(dāng)MIDlet被請(qǐng)求時(shí), MIDlet通過構(gòu)造程序?qū)嵗,然后調(diào)用實(shí)例的 startApp()方法。
在 FundTracker例子中, MIDlet的用戶界面或顯示是由 Display類的一個(gè)實(shí)例管理的。 對(duì)于每個(gè) MIDlet,只有一個(gè)顯示管理器實(shí)例。 所有可以顯示的項(xiàng)目,像屏幕或畫布(canvas),通過這個(gè)管理器都能夠成為可見的。因?yàn)樾袆?dòng)電話和呼叫器能力的多樣化,又因?yàn)橛糜谶@些設(shè)備的應(yīng)用程序類型的差異, MIDP規(guī)范提供了兩種類型的用戶界面。一個(gè)可移植性稍差、明確設(shè)備、低水平的應(yīng)用程序接口,允許圖形元素精確的控制和放置。 這個(gè)接口類型是用于應(yīng)用程序特性比較典型的設(shè)備特別設(shè)計(jì)的,比如電子游戲。 一個(gè)可移植性稍好的、抽象的、高級(jí)的 GUI應(yīng)用程序接口,提供來用于商業(yè)應(yīng)用程序。
我們的例程使用的是高級(jí)的應(yīng)用程序接口和典型的用戶界面組件 (文本框,列表等等 ),是這類界面通用的。比如說,實(shí)際的表單和所有的小組件在一個(gè)單獨(dú)的文件中都已定義。 就像在代碼段一中列出的那樣,當(dāng) MIDlet創(chuàng)建時(shí),一個(gè)表單的實(shí)例與 MIDlet關(guān)聯(lián)。 在調(diào)用 MIDlet startApp()方法的時(shí)候,通過 Display對(duì)象顯示表單。 使用一個(gè)用于表單的類,允許我們在我們簡單的報(bào)價(jià)檢索應(yīng)用程序中重新使用這個(gè)表單 ( RetrieveQuote )。為了清晰性和風(fēng)格,我們通過一個(gè)單獨(dú)的類來定義報(bào)價(jià)服務(wù)。 為了演示一般連接器結(jié)構(gòu)的能力,我們的報(bào)價(jià)服務(wù)類通過一個(gè) Connector實(shí)例取回報(bào)價(jià)。
MIDP要求平臺(tái)設(shè)備提供一個(gè)機(jī)制用來儲(chǔ)存簡單的數(shù)據(jù)記錄,通過正常的平臺(tái)事件,比如重新啟動(dòng)和電池更新維護(hù)系統(tǒng)的完整性。 MIDP稱一個(gè)持久數(shù)據(jù)庫為 RecordStore。 在我們的示例中, MIDlet打開并添加一條記錄到 " MutualFundQuotes " RecordStore。 正如我們的演示程序,能添加到 RecordStore中的唯一一種類型的記錄是字節(jié)數(shù)組。 相同的 RecordStore是一個(gè)資源,它可以通過套件共享。 根據(jù) MIDP規(guī)范, 當(dāng) MIDlet從平臺(tái)中刪除后,RecordStore也會(huì)被從平臺(tái)中刪除。
PDA簡表
Palm公司是開發(fā)PDA簡表規(guī)范的領(lǐng)頭人, 這個(gè)簡表也是完善了 CLDC,在相當(dāng)長的一段時(shí)間內(nèi),它都將是 kjava類程序包的替代品。 Java規(guī)范建議這個(gè) profile至少應(yīng)當(dāng)提供兩個(gè)核心功能片段: 一個(gè)用戶界面顯示工具包,適合于 "有限的尺寸和深度顯示 "和一個(gè)持久數(shù)據(jù)存儲(chǔ)器機(jī)制。 顯示工具包應(yīng)該是抽象窗口工具包的一個(gè)子集, 而持久機(jī)制將為應(yīng)用程序、數(shù)據(jù)、配置/環(huán)境信息提供簡單的數(shù)據(jù)存儲(chǔ)。
Foundation簡表
下面三種簡表不是非常常見, 這三種簡表的職責(zé)都是為了完善 CDC。 Personal和 RMI簡表實(shí)際上是 Foundation簡表的擴(kuò)展。 Foundation簡表的任務(wù)是擔(dān)任一個(gè)基礎(chǔ)簡表,便于以后開發(fā)出來的提供圖形用戶接口、 網(wǎng)絡(luò)等功能的簡表附著在它之上。 除了用于基礎(chǔ)簡表, Foundation簡表還提供完整網(wǎng)絡(luò)的支持,不管有沒有使用圖形用戶接口。
Personal簡表
在當(dāng)前的規(guī)范需求下, Personal簡表提供下一代 PersonalJava環(huán)境。這個(gè)簡表允諾,提供互聯(lián)網(wǎng)連接性和 Web保真度以及一個(gè)能夠運(yùn)行 Java applets的 GUI。
RMI簡表
回想一下 CDC配置為共享的、固定網(wǎng)絡(luò)連接信息設(shè)備提供最小的 Java環(huán)境。 RMI簡表將通過提供 Java到 Java的RMI來協(xié)助提供更好的網(wǎng)絡(luò)連接性。 通過使用 J2SE ( 1.2.x或更高版本的 ) RMI,這個(gè)簡表將允許這些網(wǎng)絡(luò)設(shè)備與其他系統(tǒng)應(yīng)用程序交互操作 (這個(gè)系統(tǒng)不必也運(yùn)行 J2ME )。
kjava類
正如前面提到的那樣, kjava類是最初提供的一個(gè)供測試用的類,在 Palm設(shè)備上運(yùn)行早期的 KVM和配置版本。 它們將被 PDA簡表代替。 kjava類擴(kuò)展了 CLDC并且提供一個(gè)圖形用戶接口、 Palm數(shù)據(jù)庫訪問,簡單集合類和一個(gè)三角法計(jì)算器。
在代碼段2中,我使用 com.sun.kjava重寫了 MIDP FundTracker程序,讓它在 Palm上工作。 和前面的程序一樣,這個(gè)簡單的程序允許用戶輸入一個(gè)公基金代號(hào)并從WWW上的金融報(bào)價(jià)服務(wù)商那里取回報(bào)價(jià)。
kjava應(yīng)用程序被稱作 spotlet。 事實(shí)上,一個(gè)應(yīng)用程序可以由很多 spotlet組成,但是在任何時(shí)間只有一個(gè) spotlet可以顯示在 Palm屏幕上。 在我們的例子中,我們創(chuàng)建一個(gè)基本 spotlet-- RequestFormSpotlet.java,為我們的兩個(gè) spotlets子類提供用戶界面。代碼段 2擴(kuò)展了基本的 RequestFormSpotlet以便得到并儲(chǔ)存一個(gè)報(bào)價(jià)。 RetrieveSpotlet也擴(kuò)展了基本 RequestFormSpotlet并允許儲(chǔ)存的報(bào)價(jià)被取回(見圖)
代碼段2
import com.sun.kjava.*;
public final class FundSpotlet extends RequestFormSpotlet {
public static void main (String args[]) {
new FundSpotlet().draw();
}
private void draw() {
initForm();
setTitle("Fund Quote Requested");
}
public void penDown(int x, int y){
if (getExitButton().pressed(x,y)){
getGraphic().playSound(Graphics.SOUND_CONFIRMATION);
System.exit(0);
}
if (getSymField().pressed(x,y))
getSymField().setFocus();
if (getGetButton().pressed(x,y)) {
quoteRequested();
}
}
private void storeQuote (String fund, String newQuote) {
int dbType = 0x46554e44;
int dbCreator = 0x43415454;
com.sun.kjava.Database quoteDB;
try {
quoteDB = new com.sun.kjava.Database(dbType,
dbCreator, com.sun.kjava.Database.READWRITE);
if (!quoteDB .isOpen()) {
com.sun.kjava.Database.create(0, "MutualFundQuotes",
dbCreator, dbType, false);
quoteDB = new com.sun.kjava.Database(dbType,
dbCreator, com.sun.kjava.Database.READWRITE);
}
byte[] data = (fund + "#" + newQuote).getBytes();
quoteDB.addRecord(data);
quoteDB.close();
}
catch (Exception recordException) {
System.out.println("Unable to store quote and/or use
Mutual Fund Quote database.");
}
}
private void getAndDisplayQuote() {
String fundSymbol = getSymField().getText();
if (fundSymbol.length() > 0) {
String theQuote = QuoteService.getQuote(fundSymbol);
if (theQuote != null) {
storeQuote(fundSymbol, theQuote);
message(theQuote);
}
else
message("No quote. Check Symbol");
}
}
private void quoteRequested() {
message("");
getGraphic().playSound(Graphics.SOUND_STARTUP);
if ((getSymField().getText().length() > 0)) {
getAndDisplayQuote();
} else
{
message("Symbol required!");
}
}
}
在 RequestFormSpotlet程序中,類似于 MIDP中的 Display對(duì)象,單獨(dú)的 Graphics管理許多 spotlet用戶界面顯示。它考慮到了屏幕會(huì)被清除,顯示邊界會(huì)被建立。 不象 MIDlet,沒有屏幕或畫布對(duì)象來讓我們添加用戶界面小組件, 取而代之的是按鈕、文本字段等等,直接描畫在 spotlet上。 paint()方法利用圖形環(huán)境從獨(dú)一無二的 Graphics在屏幕上顯示小組件。
我們的MIDP程序的 QuoteService類的大部分可以重新使用。 因?yàn)?kjava沒有象 MIDP中HttpConnection這樣特定的連接器界面,所以我們必須利用更多標(biāo)準(zhǔn)的一般的連接器結(jié)構(gòu)表單獲取 HTTP鏈接。 為了做到這一點(diǎn),使用代碼段 3中的代碼替換 getQuotePage()方法。注意注意使用 Connector,就像在 MIDP中我們使用 HttpConnection一樣。
代碼段3
private static String getQuotePage(String symbolString) {
StringBuffer quotePage = new StringBuffer();
int ch;
try {
InputStream in = Connector.openInputStream (
"testhttp://someurl/some_application?page=++&mode=fund&symbol="+
symbolString);
while ((ch = in.read()) > 0) {
quotePage.append((char)ch);
}
in.close();
return quotePage.toString();
} catch (IOException ex) {
System.out.println("Exception reading quote from
HTTP Connection");
return null;
}
}
Palm設(shè)備廣泛利用數(shù)據(jù)庫, 你的 Palm中的通訊簿、備忘錄和記事本應(yīng)用程序都與數(shù)據(jù)庫有關(guān)。 kjava程序包提供了一個(gè)非常小的 Database類,不僅可以創(chuàng)建并保持應(yīng)用程序數(shù)據(jù),而且可以訪問現(xiàn)有的數(shù)據(jù)庫。 如果你熟悉 Palm數(shù)據(jù)庫,你可能會(huì)對(duì) kjava Database類提供的功能和信息感到失望。 然而,請(qǐng)?jiān)俅斡涀。?kjava只是一個(gè)演示的版本。
在我們的例子中,我們的 spotlet訪問一個(gè) Palm數(shù)據(jù)庫 (如果不存在的話,則創(chuàng)建一個(gè)新的數(shù)據(jù)庫)來儲(chǔ)存公基金報(bào)價(jià)。每個(gè) Palm數(shù)據(jù)庫都必須有名字、創(chuàng)建者 ID (一個(gè) Palm登記的唯一的標(biāo)識(shí)號(hào) ) 和一個(gè)指定到某個(gè)單獨(dú)應(yīng)用程序的類型號(hào)。 試圖打開數(shù)據(jù)庫要通過嘗試創(chuàng)建一個(gè)帶有 ID信息的數(shù)據(jù)庫實(shí)例來實(shí)現(xiàn)。 就象 MIDP RecordStore,記錄被添加進(jìn) kjava數(shù)據(jù)庫,通過把一個(gè)字節(jié)數(shù)組當(dāng)成記錄添加到數(shù)據(jù)庫中的形式。