官术网_书友最值得收藏!

2.2 建立MIDlet類

Midlet Suite中至少要包含一個MIDlet類,它是整個程序執行的入口處,由于MIDlet類是抽象類,所以需要定義一個類來繼承MIDlet類。

首先由于MIDlet類位于包javax.microedtion.midlet中,因此第一步需要在代碼程序中引入這個包:

import javax.microedtion.midlet.*;

注意:不要寫成“import javax.microedtion.MIDlet.*;”。

接著需要擴展MIDlet類,它的類名就是要編寫的主類名,擴展后的代碼如下:

import javax.microedition.midlet.MIDlet;
public class MyMIDlet extends MIDlet {
}

從Java語法上說,這樣一個空類是可以編譯的,但實際上用Eclipse試圖編譯的時候會拒絕通過,這是因為MIDlet類有3個抽象方法是必須實現的:

protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
}
    protected void pauseApp() {
    }
    protected void startApp() throws MIDletStateChangeException {
    }

當然,可以選擇直接新建MIDlet類,那樣就簡單很多了。

選擇“新建”→“J2ME Midlet”命令,如圖2-6所示,就會打開如圖2-7所示的“J2ME Midlet”設置向導,設置類的名稱和相關屬性。

圖2-6 建立MIDlet類

圖2-7 “J2ME Midlet”設置向導

注意:由于建立的是MIDlet類,所以在超類處已經直接顯示為“javax.microedition.midlet.MIDlet”類,通過選擇“Unimplemented abstract methods”選項可以實現MIDlet類的3個抽象方法。

當設置結束完成后,系統會自動生成如下代碼:

import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class Demo extends MIDlet {
public Demo() {
        // TODO 自動生成構造函數存根
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
        // TODO 自動生成方法存根
    }
    protected void pauseApp() {
        // TODO 自動生成方法存根
    }
    protected void startApp() throws MIDletStateChangeException {
        // TODO 自動生成方法存根
    }
}

2.2.1 midlet包介紹

通過javax.microedition.midlet包,MIDP定義了MIDlet的生命周期,以及MIDlet與運行環境的交互方式。javax.microedition.midlet包總共包含兩個類:MIDlet和MIDletStateChangeException。

(1)MIDlet是一個抽象類,它是所有MIDP應用程序必須要擴展的父類。MIDlet類確保在運行環境中應用程序的必要方法在適當的時機被執行。開發者必須要實現MIDlet中定義的3個抽象方法,即startApp()、pauseApp()和destroyApp()。

(2)MIDletStateChangeException是一個異常類。它是用來監測MIDP應用程序狀態的改變的,當MIDlet從一個狀態轉移到另外一個狀態失敗的情況下就會被拋出。

midlet包整個層次結構如圖2-8所示。

圖2-8 midlet包層次結構

MIDlet是MIDP應用程序的入口類,與Java應用程序中含有main()方法的類相似,在J2ME中管理MIDlet的是應用程序管理軟件。

MIDlet初始化后需要有其他的資源與之配合才能正常工作。例如,創建所需的對象(用戶界面及功能類等)、從持久性存儲空間讀取數據、新建線程并行處理任務及建立網絡連接讀取數據等。

2.2.2 MIDlet類的生命周期

1.MIDlet的狀態

J2ME程序都是從MIDlet類開始執行的,系統規定了MIDlet的生命周期。規定MIDlet程序有3種狀態:運行狀態、暫停狀態和銷毀狀態。

(1)運行狀態。當一個MIDlet進入運行狀態時,它將獲得用于執行任務的所有資源。轉移到運行狀態之后,所需的線程應該被啟動。

(2)暫停狀態。當一個MIDlet進入暫停狀態時,它應該釋放所有持有的資源并停止活動的線程。如果有需要,則應該把數據保存到持久性存儲器中,這樣在程序重新進入活動狀態時可以重用。

(3)銷毀狀態。當一個MIDlet進入銷毀狀態時,它應該釋放所有資源、停止正在執行的線程并保存持久性的數據。

系統在執行MIDlet程序時,首先構造一個MIDlet類型的對象,然后使程序進入到暫停狀態,按照生命周期的規定,系統會自動調用MIDlet對象的startApp()方法使程序進入到運行狀態,開始程序的執行。如果在創建MIDlet對象的過程中,或者是調用startApp()的方法中發生了異常,則系統會自動調用MIDlet對象的destroyApp()方法進行到銷毀狀態,也就是使程序退出。

2.狀態轉換

應用程序管理軟件(AMS)使用如圖2-9所示的生命周期方法來控制MIDlet的狀態。

默認構造器。當用戶啟動一個MIDlet時,AMS創建一個新的MIDlet實例,通過調用默認構造器來執行初始化工作。當構造器返回后,MIDlet被置于暫停狀態。如果在構造器執行期間拋出異常,那么MIDlet立即進入銷毀狀態。

圖2-9 MIDlet類的生命周期

public void startApp()方法。在MIDlet處于暫停狀態的時候,AMS調用startApp()方法指示MIDlet應該進入活動狀態。startApp()方法可能會拋出MIDletStateChangeException,這個異常說明MIDlet現在不能啟動,但是可能稍后會啟動。如果阻止MIDlet啟動的錯誤是短暫性的,那么可以捕獲這個異常并從錯誤中恢復。如果這個錯誤是非短暫性的,那么應該調用notifyDestroyed()方法,MIDlet進入銷毀狀態。

public void pauseApp()方法。當MIDlet在活動狀態時,AMS調用這個方法指示MIDlet將從活動狀態進入暫停狀態。

public void destroyApp(boolean unconditional)方法。AMS可以在MIDlet處于活動或者暫停時調用這個方法,指示MIDlet將進入銷毀狀態。參數unconditional代表了終止請求的類型,如果unconditional為true,那么終止請求是強制執行的。如果unconditional為false,那么終止請求是可自由決定的,MIDlet可以拋出MIDletStateChangeException而持續運行。

需要說明的狀態是暫停狀態,系統在程序運行過程中,如果手機有來電,則系統會自動地使MIDlet程序進入到暫停狀態,在進入到暫停狀態以前,系統會自動調用MIDlet對象的pauseApp()方法。當電話接聽完畢以后,系統會自動使MIDlet程序進入到運行狀態,在進入到運行狀態以前,系統還會自動調用startApp()方法使系統進入到運行狀態。

3.控制MIDlet的狀態改變

AMS控制MIDlet的狀態改變,在代碼執行到某一點可能需要狀態的改變。MIDlet類提供了如下3個方法來允許一個MIDlet來控制它自己的狀態。

(1)resumeRequest()方法。MIDlet調用這個方法表明它本身已經準備好進入活動狀態了。

(2)notifyPaused()方法。該方法允許MIDlet主動暫停自己。當MIDlet處于活動狀態時,它可以調用notifyPaused()方法通知AMS MIDlet已經主動進入暫停狀態。在必要的時候,AMS可以調用startApp()方法重新啟動MIDlet,也可以調用destroyApp()方法來終止MIDlet。

(3)notifyDestroyed()方法。該方法允許MIDlet主動銷毀自己。當MIDlet處于活動狀態時,它可以調用notifyDestroyed()方法通知AMS MIDlet已經主動進入了銷毀狀態。

必須注意的是,如果上述的3個通知方法被調用,那么AMS就不會再調用相應的生命周期方法。例如,如果已經調用了notifyPaused()方法,那么pauseApp()方法就不會主動被調用。也就是相關的生命周期方法應該先于通知方法之前調用。因此,經常在退出應用程序的代碼中看到如下的方法:

public void exitMIDlet(){
    try{
        destroyApp(false);
        notifyDestroyed();
    }catch(MIDletStateChangeException ex){
        ex.printStackTrace();
    }
}

如果exitMIDlet()方法中只是調用notifyDestroyed()方法,那么destroyApp()方法就不會被AMS方法自動調用,這樣本來由destroyApp()方法完成的銷毀和狀態保存工作都沒有被完成。

2.2.3 編寫并運行MIDlet應用程序

這里只是編寫一個最簡單的J2ME應用程序,在自動生成的框架內輸入如下代碼:

import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class Demo extends MIDlet {
    Display display;
    Form form;
    public Demo() {
        display=Display.getDisplay(this);
        form=new Form("第一個實例");
    }
    protected void destroyApp(boolean arg0) throws MIDletStateChange Exception {
    }
    protected void pauseApp() {
    }
    protected void startApp() throws MIDletStateChangeException {
        display.setCurrent(form);
    }
}

說明:

Display display; 定義Display對象display,是每個J2ME程序必有的對象,用于顯示手機屏幕。

Form form;定義Form對象form,是被顯示的對象。

display=Display.getDisplay(this);通過調用Display類中的靜態方法getDisplay()生成display對象。

form=new Form("第一個J2ME程序!");調用Form類中的構造方法生成form對象。

display.setCurrent(form);display對象調用setCurrent()方法將form對象顯示在手機屏幕上。

選擇運行菜單下的運行命令,配置運行環境如圖2-10所示。或者在左側包資源管理器中選中MIDlet類并單擊鼠標右鍵選擇運行方式中的“Emulated J2ME Midlet”命令,運行結果如圖2-11所示。

圖2-10 配置運行環境

圖2-11 運行結果

2.2.4 打包與混淆

為了在J2ME設備上安裝J2ME MIDlet套件,首先必須把它部署為JAD和JAR文件,這一過程稱為打包。EclipseME內建了打包生成JAD和JAR文件的支持。有兩種打包選項:創建包(Create Package)和創建混淆包(Create Obfuscated Package)。

1.創建包

如果使用創建包,那么將把JAD和JAR文件輸出到在首選項(Preferences)中配置的部署目錄中。部署的JAR文件包含校驗過的類文件和資源文件。在J2ME項目上單擊鼠標右鍵選擇“J2ME”下的“Create Package”命令即可,如圖2-12所示。

打包之后可以看到輸出目錄如圖2-13所示,在deployed文件夾中生成與項目同名的JAR文件和JAD文件。JAR文件是項目的安裝文件,可以將JAR文件復制到終端設備上,并進行安裝。JAD文件是項目的信息描述文件,有的手機只需要JAR文件,有的兩者都需要。

圖2-12 打包菜單

2.創建混淆包

如果使用創建混淆包,則需要安裝混淆器,EclipseME會使用在首選項中指定的Proguard工具來混淆部署的JAR文件。混淆能夠對MIDlet進行一定程度的保護,增加反編譯的難度。更重要的是,混淆后的包通常會更小。

為了產生混淆包,需要正確安裝Proguard工具,并在混淆首選項(Obfuscation Preferences)中正確設置其安裝目錄。Proguard是一個免費、開源的工具,可以從http://proguard.sourceforge.net/下載。

在Eclipse環境下打包,右鍵單擊項目名稱,選擇“J2ME”→“Create Obfuscated Package”命令后就彈出一個警告框,如圖2-14所示。

圖2-13 打包后的菜單

圖2-14 “Obfuscation Error”對話框

這是因為沒有安裝混淆器,安裝混淆器Proguard至Eclipse的步驟如下。

(1)下載Proguard4.7.zip包,下載地址為http://sourceforge.net/projects/proguard/files/

(2)將下載后的Proguard4.7.zip包解壓縮。在Eclipse中操作如下:“窗口”→“首選項”→“J2ME”→“Packaging”→“Obfuscation”,在Proguard Root Directory增加混淆包路徑如圖2-15所示。

(3)J2ME項目打包:右鍵單擊項目名,選擇“J2ME”→“Create Obfuscated Package”命令。

JAR和JAD文件是在MIDP兼容的設備上部署應用所必需的。除此之外,在混淆過程中還產生了一定數量的其他文件。這些文件和生成的JAR文件、JAD文件一起,被放在部署目錄中,如圖2-16所示。

*_base.jar:這個JAR文件包含混淆之前的初始包,被作為混淆處理的源。

*_base_obf.jar:這個JAR文件包含混淆后的class文件。對這個JAR文件進行預校驗處理就產生了最終的混淆并校驗過的JAR文件。

pro_map.txt:這個文件包含了類中原名和混淆后的名字的對應關系。利用這個文件,就可以使用Proguard的ReTrace命令,來根據混淆后的追蹤輸出(stack trace)來重建原始的追蹤輸出。

pro_seeds.txt:這個文件列出了作為混淆種子(seed)的MIDlet子類。

proguard.cfg:這個文件包含Proguard的混淆參數設置。

圖2-15 添加混淆器

圖2-16 混淆包文件目錄

主站蜘蛛池模板: 咸宁市| 徐闻县| 嘉鱼县| 钦州市| 介休市| 唐山市| 麦盖提县| 芦山县| 香港 | 文成县| 余庆县| 浙江省| 屏山县| 乌鲁木齐市| 鄂托克前旗| 福泉市| 边坝县| 巴里| 鄂尔多斯市| 墨江| 太仓市| 西平县| 凤台县| 嘉荫县| 德清县| 平泉县| 鄂托克前旗| 靖宇县| 兰溪市| 乌兰县| 桃源县| 阳泉市| 青海省| 宝兴县| 剑阁县| 崇阳县| 大港区| 阿勒泰市| 墨玉县| 香河县| 新安县|