Java嵌入式開發之二(中) [轉自yesky]
發表時間:2024-06-21 來源:明輝站整理相關軟件相關文章人氣:
[摘要]第四節 談談J2ME簡表 雖然配置為一組通用設備提供了最小的 Java平臺,但是應用程序開發者感興趣的是為一個個別的設備生產應用程序,當他們只是使用配置的話,他們編寫的應用程序就會有一些欠缺。 配置必須滿足所有的設備的最小的要求, 用戶界面、輸入機制和數據持久性有高度地設備具體性,每一種設備都有...
第四節 談談J2ME簡表
雖然配置為一組通用設備提供了最小的 Java平臺,但是應用程序開發者感興趣的是為一個個別的設備生產應用程序,當他們只是使用配置的話,他們編寫的應用程序就會有一些欠缺。 配置必須滿足所有的設備的最小的要求, 用戶界面、輸入機制和數據持久性有高度地設備具體性,每一種設備都有自己的用戶界面、輸入機制和數據存儲方法,這些往往不在配置所滿足的最小要求的范圍之內。
簡表為相同消費電子設備的不同的生產商提供了標準化的 Java類庫, 事實上,雖然配置規范的開發由 Sun領導,但是許多簡表規范仍將繼續由特殊設備的供應商領導。 比如說, Motorola領導了行動電話和呼叫器簡表規范的開發,又如 Palm 領導 PDA簡表的開發。
現在,五個已知簡表已經有了規范, 記住,每個簡表的責任都是為了完善配置的不足,下表列出了這五個簡表:
簡 表 完善配置
Mobile information devices profile (MIDP) 移動電話和呼叫器 CLDC
Personal digital assistant profile Palm和Handspring的PDA 設備 CLDC
Foundation profile 用于所有不需要GUI的CDC設備的標準簡表 CDC
Personal profile 替代PersonalJava的Foundation完善的簡表 CDC
RMI profile提供RMI的Foundation完善的簡表 CDC
現在我想談一談另一個Java類庫集,它現在差不多可以被認為是另一個簡表了。當Sun為Palm開發第一個KVM時,他們需要一組類來 開發Palm的演示程序。這套類庫被封裝進 com.sun.kjava程序包, 在 CLDC早期的開發中,這些類被廣泛的使用來測試和演示 J2ME。因為 kjava是唯一的允許應用程序開發者使用 J2ME和 KVM開發應用程序的類,所以它就被廣泛使用了。甚至到了今天,一個用于 PDA或更特殊一點的 Palm的簡表多已經在開發中,許多開發者仍然希望使用 kjava類來開發 PDA應用程序。盡管 kjava類不被支持,并且僅僅用于設計測試程序或演示程序,并且它們將被一個即將到來的簡表所替代,但是開發者們仍然熱衷于使用它來開發。
MIDP
Mobile Information Device Profile(移動信息設備簡表 ,簡稱 MIDP ),第一個實現的簡表,補充了 CLDC并且提供應用程序語義和控件、用戶界面、持久存儲器、網絡和用于移動電話的計時器、雙通道呼叫器和其他無線電設備。 因為 MIDP和 CLDC兩者都有引用實現,我們可以使用一個例程來研究一下這個簡表。
下面的例子是一個允許用戶輸入代表想知道的基金報價的代號的例子。應用程序然后通過 HTTP接到一個金融網站,獲得基金報價,把價格儲存在一個數據庫,然后把價格返回給用戶。
// 到如需要的J2ME類
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
// 擴展MIDlet類來構建我們的自定義MIDlet
public class FundTracker extends MIDlet implements
CommandListener {
file://顯示管理者變量
private Display display = null;
file://MIDlet的表單變量
private RequestForm reqForm = null;
file://MIDlet構建器
public FundTracker () {
display = Display.getDisplay(this);
reqForm = new RequestForm("Fund Tracker");
reqForm.initForm();
reqForm.setCommandListener(this);
}
file://開始 MIDlet 應用程序
protected void startApp() {
display.setCurrent(reqForm);
}
file://暫停 Midlet
protected void pauseApp() {
}
file://銷毀Midlet
protected void destroyApp(boolean unconditional) {
}
file://通過監聽者響應命令
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://儲存由#分開的成對的基金字符串和報價字符串
private void storeQuote (String fund, String newQuote) {
file://數據庫變量
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類取回提交的代號表示的基金報價
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應用程序稱為 MIDlet, 為了創建一個 MIDlet,你必須寫一個擴展基本 MIDlet類的類 (就像我們在上面代碼段中列出的那樣)。 這有點類似常見的 applet或 servlet。 MIDlets獨有的東西是把多個 MIDlet組成一個 MIDlet套件的能力。 這就允許 MIDlet在一個單獨的 JVM環境中共享資源,比如一個數據庫等等。 事實上,我們上面給出的例子還包括一個 MIDlet ( RetrieveQuote,見上段程序),用于取回所報價格。 當MIDlet被請求時, MIDlet通過構造程序實例化,然后調用實例的 startApp()方法。
在 FundTracker例子中, MIDlet的用戶界面或顯示是由 Display類的一個實例管理的。 對于每個 MIDlet,只有一個顯示管理器實例。 所有可以顯示的項目,像屏幕或畫布(canvas),通過這個管理器都能夠成為可見的。因為行動電話和呼叫器能力的多樣化,又因為用于這些設備的應用程序類型的差異, MIDP規范提供了兩種類型的用戶界面。一個可移植性稍差、明確設備、低水平的應用程序接口,允許圖形元素精確的控制和放置。 這個接口類型是用于應用程序特性比較典型的設備特別設計的,比如電子游戲。 一個可移植性稍好的、抽象的、高級的 GUI應用程序接口,提供來用于商業應用程序。
我們的例程使用的是高級的應用程序接口和典型的用戶界面組件 (文本框,列表等等 ),是這類界面通用的。比如說,實際的表單和所有的小組件在一個單獨的文件中都已定義。 就像在代碼段一中列出的那樣,當 MIDlet創建時,一個表單的實例與 MIDlet關聯。 在調用 MIDlet startApp()方法的時候,通過 Display對象顯示表單。 使用一個用于表單的類,允許我們在我們簡單的報價檢索應用程序中重新使用這個表單 ( RetrieveQuote )。為了清晰性和風格,我們通過一個單獨的類來定義報價服務。 為了演示一般連接器結構的能力,我們的報價服務類通過一個 Connector實例取回報價。
MIDP要求平臺設備提供一個機制用來儲存簡單的數據記錄,通過正常的平臺事件,比如重新啟動和電池更新維護系統的完整性。 MIDP稱一個持久數據庫為 RecordStore。 在我們的示例中, MIDlet打開并添加一條記錄到 " MutualFundQuotes " RecordStore。 正如我們的演示程序,能添加到 RecordStore中的唯一一種類型的記錄是字節數組。 相同的 RecordStore是一個資源,它可以通過套件共享。 根據 MIDP規范, 當 MIDlet從平臺中刪除后,RecordStore也會被從平臺中刪除。
PDA簡表
Palm公司是開發PDA簡表規范的領頭人, 這個簡表也是完善了 CLDC,在相當長的一段時間內,它都將是 kjava類程序包的替代品。 Java規范建議這個 profile至少應當提供兩個核心功能片段: 一個用戶界面顯示工具包,適合于 "有限的尺寸和深度顯示 "和一個持久數據存儲器機制。 顯示工具包應該是抽象窗口工具包的一個子集, 而持久機制將為應用程序、數據、配置/環境信息提供簡單的數據存儲。
Foundation簡表
下面三種簡表不是非常常見, 這三種簡表的職責都是為了完善 CDC。 Personal和 RMI簡表實際上是 Foundation簡表的擴展。 Foundation簡表的任務是擔任一個基礎簡表,便于以后開發出來的提供圖形用戶接口、 網絡等功能的簡表附著在它之上。 除了用于基礎簡表, Foundation簡表還提供完整網絡的支持,不管有沒有使用圖形用戶接口。
Personal簡表
在當前的規范需求下, Personal簡表提供下一代 PersonalJava環境。這個簡表允諾,提供互聯網連接性和 Web保真度以及一個能夠運行 Java applets的 GUI。
RMI簡表
回想一下 CDC配置為共享的、固定網絡連接信息設備提供最小的 Java環境。 RMI簡表將通過提供 Java到 Java的RMI來協助提供更好的網絡連接性。 通過使用 J2SE ( 1.2.x或更高版本的 ) RMI,這個簡表將允許這些網絡設備與其他系統應用程序交互操作 (這個系統不必也運行 J2ME )。
kjava類
正如前面提到的那樣, kjava類是最初提供的一個供測試用的類,在 Palm設備上運行早期的 KVM和配置版本。 它們將被 PDA簡表代替。 kjava類擴展了 CLDC并且提供一個圖形用戶接口、 Palm數據庫訪問,簡單集合類和一個三角法計算器。
在代碼段2中,我使用 com.sun.kjava重寫了 MIDP FundTracker程序,讓它在 Palm上工作。 和前面的程序一樣,這個簡單的程序允許用戶輸入一個公基金代號并從WWW上的金融報價服務商那里取回報價。
kjava應用程序被稱作 spotlet。 事實上,一個應用程序可以由很多 spotlet組成,但是在任何時間只有一個 spotlet可以顯示在 Palm屏幕上。 在我們的例子中,我們創建一個基本 spotlet-- RequestFormSpotlet.java,為我們的兩個 spotlets子類提供用戶界面。代碼段 2擴展了基本的 RequestFormSpotlet以便得到并儲存一個報價。 RetrieveSpotlet也擴展了基本 RequestFormSpotlet并允許儲存的報價被取回(見圖)
代碼段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對象,單獨的 Graphics管理許多 spotlet用戶界面顯示。它考慮到了屏幕會被清除,顯示邊界會被建立。 不象 MIDlet,沒有屏幕或畫布對象來讓我們添加用戶界面小組件, 取而代之的是按鈕、文本字段等等,直接描畫在 spotlet上。 paint()方法利用圖形環境從獨一無二的 Graphics在屏幕上顯示小組件。
我們的MIDP程序的 QuoteService類的大部分可以重新使用。 因為 kjava沒有象 MIDP中HttpConnection這樣特定的連接器界面,所以我們必須利用更多標準的一般的連接器結構表單獲取 HTTP鏈接。 為了做到這一點,使用代碼段 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設備廣泛利用數據庫, 你的 Palm中的通訊簿、備忘錄和記事本應用程序都與數據庫有關。 kjava程序包提供了一個非常小的 Database類,不僅可以創建并保持應用程序數據,而且可以訪問現有的數據庫。 如果你熟悉 Palm數據庫,你可能會對 kjava Database類提供的功能和信息感到失望。 然而,請再次記住, kjava只是一個演示的版本。
在我們的例子中,我們的 spotlet訪問一個 Palm數據庫 (如果不存在的話,則創建一個新的數據庫)來儲存公基金報價。每個 Palm數據庫都必須有名字、創建者 ID (一個 Palm登記的唯一的標識號 ) 和一個指定到某個單獨應用程序的類型號。 試圖打開數據庫要通過嘗試創建一個帶有 ID信息的數據庫實例來實現。 就象 MIDP RecordStore,記錄被添加進 kjava數據庫,通過把一個字節數組當成記錄添加到數據庫中的形式。