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

Codename One音频播放异常:模拟器正常,Android真机无响应

问题原因分析

这个问题我之前也碰到过,核心原因是Codename One模拟器和Android真机的资源加载逻辑差异,导致getResourceAsStream()返回null,进而触发NullPointerException:

  • 在Codename One模拟器里,资源文件是按照项目原始路径(根目录下的资源)直接读取的,所以/notification_sound_bell.mp3能正常获取到输入流。
  • 但打包成Android APK后,Codename One会自动把项目资源迁移到Android标准的res/raw目录下。这时候Java原生的getResourceAsStream()方法没法按原来的根路径定位到文件,返回了null,后续调用MediaManager.createMedia()自然就抛出空指针异常了。
解决方案

这里提供两种可行的解决方式,你可以根据需求选择:

方式一:跨平台通用方案(推荐)

用Codename One的FileSystemStorage API访问资源,它会自动适配不同平台的资源存储位置,代码如下:

try {
    // 获取APP私有存储目录,拼接音频文件路径
    String audioPath = FileSystemStorage.getInstance().getAppHomePath() + "notification_sound_bell.mp3";
    Media m = MediaManager.createMedia(audioPath, false);
    m.play();
} catch (IOException err) {
    Log.e(err);
}

注意:确保你的音频文件放在Codename One项目的src目录(或项目指定的资源目录)下,打包时会被自动复制到设备的APP私有目录中。

方式二:Android平台专属方案

如果你的APP只针对Android平台,可以直接利用Android原生的资源ID加载音频,代码如下:

try {
    // 获取Android原生资源ID,注意文件名要去掉后缀,且全小写(符合Android资源命名规范)
    int audioResId = AndroidNativeUtil.getActivity().getResources()
            .getIdentifier("notification_sound_bell", "raw", AndroidNativeUtil.getActivity().getPackageName());
    Media m = MediaManager.createMedia(audioResId);
    m.play();
} catch (IOException err) {
    Log.e(err);
}
额外注意事项
  • 文件名要保持完全一致,Android文件系统区分大小写,而模拟器可能不区分,避免因大小写问题导致文件找不到。
  • 若使用跨平台方案,不要手动修改APK中的res/raw目录结构,Codename One的打包工具会自动处理资源迁移。

内容的提问来源于stack exchange,提问作者Francesco Galgani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:04:24