Xamarin跨平台摩尔斯翻译器播放音频触发SIGSEGV错误求助
摩尔斯翻译器Android端音频播放SIGSEGV错误排查思路
我用Xamarin + C#开发跨iOS/Android的摩尔斯翻译器,因为主项目和Android项目需要互相引用,最终用Autofac做依赖注入。主项目定义了ISoundService接口,Android项目实现了SoundService类。但在MainPage调用播放音频方法时,终端抛出错误:
Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x7ffc7ad11fb8 in tid 31167 (name.supermorse), pid 31167 (name.supermorse)
调试后发现错误出在执行var fd = Android.App.Application.Context.Assets.OpenFd("dot.mp3");(dash音频对应代码同理),已经尝试更换音频格式,问题依旧,求解决思路。
主项目接口代码
namespace SuperMorse { public interface ISoundService { void PlayDotSound(); void PlayDashSound(); int dot { get; set; } int dash { get; set; } } }
Android项目实现类代码
namespace SuperMorse.Droid { public class SoundService : ISoundService { public int dot { get; set; } public int dash { get; set; } public SoundService() { dot = Android.App.Application.Context.Resources.GetIdentifier("dot", "raw", Android.App.Application.Context.PackageName); dash = Android.App.Application.Context.Resources.GetIdentifier("dash", "raw", Android.App.Application.Context.PackageName); } public void PlayDotSound() { var fd = Android.App.Application.Context.Assets.OpenFd("dot.mp3"); MediaPlayer dotPlayer = new MediaPlayer(); dotPlayer.SetDataSource(fd.FileDescriptor, fd.StartOffset, fd.Length); dotPlayer.Prepare(); dotPlayer.Start(); } public void PlayDashSound() { var fd = Android.App.Application.Context.Assets.OpenFd("dash.mp3"); MediaPlayer dashPlayer = new MediaPlayer(); dashPlayer.SetDataSource(fd.FileDescriptor, fd.StartOffset, fd.Length); dashPlayer.Prepare(); dashPlayer.Start(); } } }
解决思路
- 统一资源访问方式:构造函数里用
Resources.GetIdentifier读取raw目录资源,但播放时却从Assets目录取文件,路径逻辑混乱。如果音频放在Resources/raw下,直接用资源ID初始化MediaPlayer即可:public void PlayDotSound() { using (var player = MediaPlayer.Create(Android.App.Application.Context, dot)) { player.Start(); player.Completion += (s, e) => player.Release(); } } - 避免资源泄漏:每次播放都新建MediaPlayer且不释放,易导致资源耗尽触发崩溃。建议复用实例,或用
using块确保播放完成后释放资源。 - 验证Context有效性:在
SoundService构造函数直接静态获取Application.Context可能时机不对(比如Context未完全就绪),可以通过依赖注入传入Context替代静态获取。 - 检查资源打包配置:确保音频文件的Build Action设置正确:放Assets目录设为
AndroidAsset,放Resources/raw设为AndroidResource,且文件名全小写(Android资源文件名不允许大写和特殊字符)。 - 改用异步准备方法:同步
Prepare()可能阻塞主线程引发异常,建议用PrepareAsync()监听Prepared事件再启动播放:public void PlayDotSound() { var player = new MediaPlayer(); player.SetDataSource(Android.App.Application.Context, Resource.Raw.dot); player.PrepareAsync(); player.Prepared += (s, e) => player.Start(); player.Completion += (s, e) => player.Release(); }
内容的提问来源于stack exchange,提问作者Сергей Хрящёв
相关产品推荐
相关产品推荐

