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
相关产品推荐
相关产品推荐

