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

Plugin.SimpleAudioPlayer切换音频时自动释放无法连续播放问题

问题描述

切换音频文件时音频播放器会被自动释放。开发的应用需要顺序播放shared\audio文件夹下的音频文件,目前首个音频文件可正常播放,但第一个音频播放结束后就会停止,无法继续播放后续内容。使用的是Plugin.SimpleAudioPlayer组件,实现代码如下:

public partial class MainPage : ContentPage
{
    private ISimpleAudioPlayer audio;
    private int pagenum;

    public MainPage()
    {
        InitializeComponent();
    }

    private void playaudio(int pgnum)
    {
        audio = CrossSimpleAudioPlayer.Current;
        audio.PlaybackEnded += cmdNextClicked; 
        
        var stream = GetStreamFromFile(string.Concat("audio.w", (pgnum + 1).ToString(), ".mp3"));
        audio.Load(stream);
        audio.Play();
    }

    Stream GetStreamFromFile(string filename)
    {
        var assembly = typeof(App).GetTypeInfo().Assembly;
        var stream = assembly.GetManifestResourceStream("App1." + filename);
        return stream;
    }

    private void cmdRunClicked(object sender, EventArgs e)//
    {
        playaudio(pagenum);
    }

    private void cmdStopClicked(object sender, EventArgs e)//
    {
       if (!(audio is null))
        {
            audio.Stop();
        }
    }

    private void cmdClicked(object sender, EventArgs e)
    {
        audio.Seek(audio.CurrentPosition + 30.0);
    }

    private void cmdNextClicked(object sender, EventArgs e)
    {
       
        pagenum++;
        lblPageNo.Text = pagenum.ToString();
        playaudio(pagenum);
    }

    private void cmdPrevClicked(object sender, EventArgs e)
    {
        pagenum--;
        lblPageNo.Text = pagenum.ToString();
        playaudio(pagenum);
    }
}
错误原因

代码存在两个核心问题,直接导致播放中断、无法顺序切歌:

  • 事件重复绑定引发逻辑混乱
    每次调用playaudio都会执行一次audio.PlaybackEnded += cmdNextClicked,反复给同一个播放器实例绑定播放结束事件。第一次音频播放完成后,事件会被触发多次,pagenum会直接累加超过实际存在的文件索引,后续加载音频时拿到空流,播放直接终止。同时重复绑定事件会造成内存泄漏,播放器实例会被GC意外回收。
  • 加载新音频前未重置播放器状态、释放资源
    Plugin.SimpleAudioPlayer加载新音频流时,如果当前处于播放状态、旧的流资源未被释放,会触发播放器的内置回收逻辑,后续Play()调用无效,播放结束事件也不会正常触发。

此外代码缺少索引边界校验,当pagenum超出实际音频文件数量范围时,GetManifestResourceStream会返回null,调用Load方法直接抛出空引用异常,中断播放流程。

修复方案

按照以下规则修改代码即可:

  • 将播放器实例初始化、事件绑定逻辑移到页面构造函数中,全生命周期只执行一次,禁止每次播放都重新赋值实例、重复绑定事件
  • 每次加载新音频前,先调用Stop()停止当前播放,释放旧的流资源
  • 增加文件索引边界判断,避免加载不存在的音频
  • 页面销毁时主动解绑事件、释放播放器资源

修复后的参考代码:

public partial class MainPage : ContentPage
{
    private ISimpleAudioPlayer audio;
    private int pagenum;
    // 修改为实际存放的音频文件总数
    private const int MaxAudioCount = 10;

    public MainPage()
    {
        InitializeComponent();
        // 仅初始化一次播放器、绑定一次事件
        audio = CrossSimpleAudioPlayer.Current;
        audio.PlaybackEnded += cmdNextClicked;
    }

    private void playaudio(int pgnum)
    {
        // 越界校验,避免加载不存在的文件
        if (pgnum < 0 || pgnum >= MaxAudioCount)
        {
            pagenum = 0;
        }
        // 停止当前播放,释放旧资源
        audio.Stop();
        
        var stream = GetStreamFromFile(string.Concat("audio.w", (pgnum + 1).ToString(), ".mp3"));
        if (stream == null) return;
        
        audio.Load(stream);
        audio.Play();
    }

    Stream GetStreamFromFile(string filename)
    {
        var assembly = typeof(App).GetTypeInfo().Assembly;
        var stream = assembly.GetManifestResourceStream("App1." + filename);
        return stream;
    }

    private void cmdRunClicked(object sender, EventArgs e)
    {
        playaudio(pagenum);
    }

    private void cmdStopClicked(object sender, EventArgs e)
    {
        audio?.Stop();
    }

    private void cmdClicked(object sender, EventArgs e)
    {
        if (audio.IsPlaying)
        {
            audio.Seek(audio.CurrentPosition + 30.0);
        }
    }

    private void cmdNextClicked(object sender, EventArgs e)
    {
        pagenum++;
        lblPageNo.Text = pagenum.ToString();
        playaudio(pagenum);
    }

    private void cmdPrevClicked(object sender, EventArgs e)
    {
        pagenum--;
        lblPageNo.Text = pagenum.ToString();
        playaudio(pagenum);
    }

    // 页面销毁时释放资源
    protected override void OnDisappearing()
    {
        base.OnDisappearing();
        audio.Stop();
        audio.PlaybackEnded -= cmdNextClicked;
        audio.Dispose();
    }
}

注意:需要确认嵌入资源的路径前缀App1.和你的项目默认命名空间一致,否则会找不到音频流返回null。

内容的提问来源于stack exchange,提问作者Isherpal Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 22:51:31