"Write once,run anywhere" 是JAVA的口號,但在J2ME平台上做的應用,要想不改動代碼就run anywhere,難度是很大的。如果要把一個應用程式做到讓大多數的機型都適用,就要考慮到方方面面,其難度是相當大的。
比如給百寶箱做遊戲,上線機型大多是MIDP1。0的機器,感覺移植中最麻煩的還要數聲音部分的API,必鬚根據各個機型來改動。雖然圖象還比較容易做成自適應的,但聲音部分就一般就只能根據各個機型來改動。
下面提供一種解決方案,可以讓J2ME程式在運行時自動載入該機型支援的聲音資源並用該
機型的聲音API來播放。
關鍵問題:
1.各機型提供的播放音樂的API都有所不同,特別是較老的機型。
需要在運行時根據機型自動載入。
2.各機型支援的聲音的資源檔也不同。需要在運行時根據機型自動載入。
3.各機型的JVM不同,多多少少有一些比較特別的BUG。
解決方案:
1. 原則:能用標準API就用標準API,不能用的話,就用各個機型自身的API。
// Player types
static final int STANDARD = 0; //For MIDI
static final int NOKIA = 1; //For ott
static final int SAMSUNG = 2; //For mmf
static final int NEC = 3; //For MIDI
static final String[] supportedPlayerTypes = {
"javax.microedition.media.Player", //STANDARD API
"com.nokia.mid.sound.Sound", // Nokia
"com.samsung.util.AudioClip", //samsung
"com.nec.media.AudioClip", //nec
}; |
下面利用反射機制來動態載入:
public void determinePlayerType() {
// use most -> less use
isSupportSound = true;
for (int i = 0; i < supportedPlayerTypes.length; i++) {
// try to load a proper sound Player
try {
Class.forName(supportedPlayerTypes[i]); //載入當前的Player類型
playerType = i; //儲存載入成功的類的類型
return;
} catch (Exception e) { //載入不成功,說明不支援,繼續載入下一種
e.printStackTrace();
}
}
isSupportSound = false;
} |
2. 下面就可以根據在載成功的類型來載入可以播放的聲音資源了
public void createPlayer(String name) {
if (!isSupportSound)
return;
switch (playerType) {
case STANDARD: // for MIDI
case NEC:
createPlayerFactory("/" + name + ".mid");
break;
case NOKIA: //for ott
createPlayerFactory("/" + name + ".ott");
break;
case SAMSUNG: // for mmf
createPlayerFactory("/" + name + ".mmf");
break;
} |
3. 對各個機型特有的BUG,是沒有什麼特別好的辦法的,只能各個機型調試。這隻能怪廠商了...
該方案優點:在移植的時候就不用改動代碼。只要在相應的機型JAR包中保留相關的資源就可以了。這樣就不用為了各個機型都折騰一遍了。
注意 :用 System.getProperty("microedition.platform")來確定機型是不保險的,因為有的機型只是簡單地返回J2ME platform。
遺留問題:
[1] NecN820 在運行 Class.forName("javax.microedition.media.Player");時候會立刻報“應用程式出錯”,而不是拋出 “ClassNotFoundException”異常。這是該機型JVM的特性(BUG),所以給NecN820的代碼中必須注釋掉 javax.microedition.media.Player的一切資訊。這就得改動代碼,有違我們的初衷,的確是個遺憾。(估計NEC的機型都素這 樣的)
[2] 這個類還有待擴充,以支援更多機型。並加入震動部分的API。理論上可以包含所有的機型。但實際應用中只要包含需要用到的機型相關API就可以了。
測試機型: 在 三星E708,MOTOV600,NOKIA 7650 ,NecN820(注釋掉javax.microedition.media.Player相關內容)上均測試通過。