You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 21:27:53