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

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,提问作者Сергей Хрящёв

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 04:06:27