Codename One中.createMedia方法播放音频文件异常问题求助
解决Codename One中
MediaManager.createMedia抛出IO异常的问题 可能的原因及修复方案
1. 确保输入流支持标记/重置
Codename One的JavaSE实现要求输入流支持mark()和reset()操作,而CN.getResourceAsStream()返回的原生流可能不具备该能力。将流包装为BufferedInputStream即可解决:
public void playAudio(String fileName) { try { if (MEDIA == null) { InputStream is = CN.getResourceAsStream(fileName); // 包装为支持标记/重置的缓冲流 BufferedInputStream bis = new BufferedInputStream(is); MEDIA = MediaManager.createMedia(bis, "audio/wav", new Runnable() { @Override public void run() { MEDIA = null; try { bis.close(); // 播放完成后关闭流 } catch (IOException e) { e.printStackTrace(); } } }); if (MEDIA != null && !MEDIA.isPlaying()) { MEDIA.setVolume(100); MEDIA.play(); } } } catch (IOException ioe) { ioe.printStackTrace(); } }
2. 验证音频文件编码兼容性
Codename One依赖底层平台的音频解码能力,JavaSE端使用Java Sound API,需确保文件编码符合要求:
- WAV文件:必须为PCM无压缩编码,避免使用压缩格式的WAV
- MP3文件:使用标准MPEG-1 Layer 3编码,避免高比特率或特殊编码的文件
可以用Audacity等工具重新导出音频,选择兼容的编码格式。
3. 延迟媒体初始化时机
在Game构造函数中调用音频播放可能过早,此时Codename One的媒体服务尚未完全初始化。改用callSerially延迟执行:
public Game() { changeState(sceneNum); // 延迟到EDT队列执行,确保媒体服务就绪 Display.getInstance().callSerially(() -> { audioPlayer.playAudio("/fluffingADuck.wav"); }); }
4. 修复逻辑缩进漏洞
原代码中播放判断的缩进错误,导致仅第一次创建媒体时才会触发播放。同时优化媒体复用逻辑:
public class AudioPlayer { private Media currentMedia = null; public void playAudio(String fileName) { try { // 停止并释放正在播放的媒体 if (currentMedia != null) { currentMedia.stop(); currentMedia = null; } InputStream is = CN.getResourceAsStream(fileName); BufferedInputStream bis = new BufferedInputStream(is); currentMedia = MediaManager.createMedia(bis, "audio/wav", () -> { currentMedia = null; try { bis.close(); } catch (IOException e) { e.printStackTrace(); } }); if (currentMedia != null) { currentMedia.setVolume(100); currentMedia.play(); } } catch (IOException ioe) { ioe.printStackTrace(); } } }
5. 启用详细日志排查
添加日志输出,获取更具体的异常原因:
// 在应用初始化时添加 Log.setLevel(Log.DEBUG); Log.addLogger(new ConsoleLog());
通过日志可以查看Java Sound API对音频格式的具体报错信息。
内容的提问来源于stack exchange,提问作者Stefan Cohn
相关产品推荐
相关产品推荐

