早期 J2ME 手機(MIDP 1.0 為主)音頻 API 極度碎片化:Nokia 用 OTT、Samsung 用 MMF、NEC 自有 API、標準 MIDP 2.0 用 MIDI。硬編碼導致每機型必須維護獨立代碼分支,移植成本極高。
public class MyPlayer {
// 播放器類型常量
static final int STANDARD = 0; // MIDI
static final int NOKIA = 1; // OTT
static final int SAMSUNG = 2; // MMF
static final int NEC = 3; // MIDI
// 按優先級排序的播放器類全名
static final String[] supportedPlayerTypes = {
"javax.microedition.media.Player", // 標準 API
"com.nokia.mid.sound.Sound", // Nokia
"com.samsung.util.AudioClip", // Samsung
"com.nec.media.AudioClip" // NEC
};
// 對應音頻文件後綴
static final String[] supportedSoundTypes = {"mid", "mmf", "ott"};
private static MyPlayer mp = null;
private static int playerType;
private static boolean isSupportSound = true;
private static boolean isSoundOn = true;
// 各平台播放器實例
private Player player; // Standard
private Sound nokiaPlayer; // Nokia
private com.samsung.util.AudioClip samsungPlayer;
private com.nec.media.AudioClip necPlayer;
}
public void determinePlayerType() {
isSupportSound = true;
for (int i = 0; i < supportedPlayerTypes.length; i++) {
try {
Class.forName(supportedPlayerTypes[i]); // 反射加載
playerType = i; // 記錄成功類型
return; // 找到即返回
} catch (Exception e) {
e.printStackTrace(); // 繼續嘗試下一個
}
}
isSupportSound = false; // 全部失敗
}
public void createPlayer(String name) {
if (!isSupportSound) return;
switch (playerType) {
case STANDARD: case NEC:
createPlayerFactory("/" + name + ".mid"); break;
case NOKIA:
createPlayerFactory("/" + name + ".ott"); break;
case SAMSUNG:
createPlayerFactory("/" + name + ".mmf"); break;
}
}
private void createPlayerFactory(String url) {
// 各平台差異化實例化邏輯
// Standard: Manager.createPlayer(is, "audio/midi")
// Nokia: Sound(byte[], FORMAT_TONE)
// Samsung: new AudioClip(TYPE_MMF, url)
// NEC: Media.getAudioClip(url)
}
public void play(int loop) { /* 統一委派各平台 play */ }
public void stopSound() { /* 統一委派各平台 stop + gc */ }
| 問題 | 現象 | 規避方案 |
|---|---|---|
| NEC N820 JVM Bug | 載入標準 Player 類直接崩潰,不拋 ClassNotFoundException | 針對 NEC 專版註釋掉標準 Player 相關代碼,或調整檢測順序將 NEC 放在前面 |
| 機型識別不可靠 | System.getProperty("microedition.platform") 返回通用字串 | 完全依賴反射檢測 API 存在性,不依賴機型字串 |