J2ME 移植最大痛點在聲音 API:各廠商實作不同 (MIDP 1.0 無標準音訊),圖形尚可自適應,聲音通常得改碼。目標:運行時自動偵測並載入該機型支援的聲音 API 與資源,免修改代碼即可跨機型運行。
static final int STANDARD = 0; // javax.microedition.media.Player (MIDI)
static final int NOKIA = 1; // com.nokia.mid.sound.Sound (OTT)
static final int SAMSUNG = 2; // com.samsung.util.AudioClip (MMF)
static final int NEC = 3; // com.nec.media.AudioClip (MIDI)
static final String[] playerClasses = {
"javax.microedition.media.Player", // 標準 API 優先
"com.nokia.mid.sound.Sound", // Nokia
"com.samsung.util.AudioClip", // Samsung
"com.nec.media.AudioClip" // NEC
};
public void determinePlayerType() {
isSupportSound = true;
for (int i = 0; i < playerClasses.length; i++) {
try {
Class.forName(playerClasses[i]);
currentPlayerType = i;
return; // 找到第一個可用即停止
} catch (ClassNotFoundException e) {
// 繼續嘗試下一個
}
}
isSupportSound = false; // 皆不支援
}
定義介面 SoundPlayer,各廠商實作一個具體類別 (如 StandardPlayer, NokiaPlayer),運行時實例化對應類別,上層統一呼叫 play(), stop()。
sound.mid, sound.ott, sound.mmf)。Class.forName("javax.microedition.media.Player") 直接拋 "Application Error" 而非例外,導致偵測失敗。解法:針對 NEC 版本註釋掉標準 Player 偵測代碼 (違背初衷,無奈之舉)。三星 E708、Moto V600、Nokia 7650、NEC N820 (需註釋標準 Player)。
將各廠商 API 做為 Library 加入 Eclipse 專案,編譯時不打包進 JAR,僅供編譯參考。
透過反射動態載入、統一介面隔離、資源多格式內建,可最大程度實現 J2ME "Write Once Run Anywhere",大幅降低移植成本。雖有極少數 JVM Bug 需特殊處理,但整體策略在實務上證明有效。