Skip to main content
 首页 » 编程设计

c#之xamarin.ios mp3 在屏幕关闭时停止播放

2024年01月26日44qq号

我正在开发一个应用程序,我需要从 url 播放音乐。 我正在使用 this代码,它工作正常。 但是,当正在播放歌曲时,屏幕关闭,然后音乐停止。我需要音乐继续播放直到结束,即使屏幕关闭也是如此。

我想我必须更改此文件,但我不知道如何:

using System; 
using AudioToolbox; 
using System.Threading; 
using System.Collections.Generic; 
using System.Linq; 
 
namespace SecondoSenso 
{ 
/// <summary> 
/// A Class to hold the AudioBuffer with all setting together 
/// </summary> 
internal class AudioBuffer 
{ 
 
    public IntPtr Buffer { get; set; } 
 
    public List<AudioStreamPacketDescription> PacketDescriptions { get; set; } 
 
    public int CurrentOffset { get; set; } 
 
    public bool IsInUse { get; set; } 
} 
 
/// <summary> 
/// Wrapper around OutputQueue and AudioFileStream to allow streaming of various filetypes 
/// </summary> 
public class StreamingPlayback : IDisposable 
{ 
    public bool boolDispose = false; 
 
    public event EventHandler Finished; 
    public event Action<OutputAudioQueue> OutputReady; 
 
    // the AudioToolbox decoder 
    AudioFileStream fileStream; 
    int bufferSize = 128 * 256; 
    List<AudioBuffer> outputBuffers; 
    AudioBuffer currentBuffer; 
    // Maximum buffers 
    int maxBufferCount = 4; 
    // Keep track of all queued up buffers, so that we know that the playback finished 
    int queuedBufferCount = 0; 
    // Current Filestream Position - if we don't keep track we don't know when to push the last uncompleted buffer 
    long currentByteCount = 0; 
    //Used to trigger a dump of the last buffer. 
    bool lastPacket; 
 
    public OutputAudioQueue OutputQueue; 
 
    public bool Started  { get; private set; } 
 
    public float Volume { 
        get { 
            return OutputQueue.Volume; 
        } 
 
        set { 
            OutputQueue.Volume = value; 
        } 
    } 
 
    /// <summary> 
    /// Defines the size forearch buffer, when using a slow source use more buffers with lower buffersizes 
    /// </summary> 
    public int BufferSize { 
        get { 
            return bufferSize; 
        } 
 
        set { 
            bufferSize = value; 
        } 
    } 
 
    /// <summary> 
    /// Defines the maximum Number of Buffers to use, the count can only change after Reset is called or the 
    /// StreamingPlayback is freshly instantiated 
    /// </summary> 
    public int MaxBufferCount { 
        get { 
            return maxBufferCount; 
        } 
 
        set { 
            maxBufferCount = value; 
        } 
    } 
 
    public StreamingPlayback () : this (AudioFileType.MP3) 
    { 
    } 
 
    public StreamingPlayback (AudioFileType type) 
    { 
        fileStream = new AudioFileStream (type); 
        fileStream.PacketDecoded += AudioPacketDecoded; 
        fileStream.PropertyFound += AudioPropertyFound; 
    } 
 
    public void Reset () 
    { 
        if (fileStream != null) { 
            fileStream.Close (); 
            fileStream = new AudioFileStream (AudioFileType.MP3); 
            currentByteCount = 0; 
            fileStream.PacketDecoded += AudioPacketDecoded; 
            fileStream.PropertyFound += AudioPropertyFound; 
        } 
    } 
 
    public void ResetOutputQueue () 
    { 
        if (OutputQueue != null) { 
            OutputQueue.Stop (true); 
            OutputQueue.Reset (); 
            foreach (AudioBuffer buf in outputBuffers) { 
                buf.PacketDescriptions.Clear (); 
                OutputQueue.FreeBuffer (buf.Buffer); 
            } 
            outputBuffers = null; 
            OutputQueue.Dispose (); 
        } 
    } 
 
    /// <summary> 
    /// Stops the OutputQueue 
    /// </summary> 
    public void Pause () 
    { 
        OutputQueue.Pause (); 
        Started = false; 
    } 
 
    /// <summary> 
    /// Starts the OutputQueue 
    /// </summary> 
    public void Play () 
    { 
        OutputQueue.Start (); 
        Started = true; 
    } 
 
    /// <summary> 
    /// Main methode to kick off the streaming, just send the bytes to this method 
    /// </summary> 
    public void ParseBytes (byte[] buffer, int count, bool discontinuity, bool lastPacket) 
    { 
        this.lastPacket = lastPacket; 
        fileStream.ParseBytes (buffer, 0, count, discontinuity); 
    } 
 
    public void Dispose () 
    { 
        Dispose (true); 
        GC.SuppressFinalize (this); 
    } 
    public void Dispose(int tt) {  
 
    } 
    /// <summary> 
    /// Cleaning up all the native Resource 
    /// </summary> 
    protected virtual void Dispose (bool disposing) 
    { 
        if (disposing) { 
 
            if (OutputQueue != null) 
                OutputQueue.Stop(true); 
 
            if (outputBuffers != null) { 
                foreach (var b in outputBuffers) 
                    OutputQueue.FreeBuffer (b.Buffer); 
 
                outputBuffers.Clear (); 
                outputBuffers = null; 
            } 
 
            if (fileStream != null) { 
                fileStream.Close (); 
                fileStream = null; 
            } 
 
            if (OutputQueue != null) { 
                OutputQueue.Dispose (); 
                OutputQueue = null; 
            } 
        } 
    } 
 
    /// <summary> 
    /// Saving the decoded Packets to our active Buffer, if the Buffer is full queue it into the OutputQueue 
    /// and wait until another buffer gets freed up 
    /// </summary> 
    void AudioPacketDecoded (object sender, PacketReceivedEventArgs args) 
    { 
        foreach (var p in args.PacketDescriptions) { 
            currentByteCount += p.DataByteSize; 
 
            AudioStreamPacketDescription pd = p; 
 
            int left = bufferSize - currentBuffer.CurrentOffset; 
            if (left < pd.DataByteSize) { 
                EnqueueBuffer (); 
                WaitForBuffer (); 
            } 
 
            AudioQueue.FillAudioData (currentBuffer.Buffer, currentBuffer.CurrentOffset, args.InputData, (int)pd.StartOffset, pd.DataByteSize); 
            // Set new offset for this packet 
            pd.StartOffset = currentBuffer.CurrentOffset; 
            // Add the packet to our Buffer 
            currentBuffer.PacketDescriptions.Add (pd); 
            // Add the Size so that we know how much is in the buffer 
            currentBuffer.CurrentOffset += pd.DataByteSize; 
        } 
 
        if ((fileStream != null && currentByteCount == fileStream.DataByteCount) || lastPacket) 
            EnqueueBuffer (); 
    } 
 
    /// <summary> 
    /// Flush the current buffer and close the whole thing up 
    /// </summary> 
    public void FlushAndClose () 
    { 
        if (OutputQueue != null) { 
            EnqueueBuffer (); 
            OutputQueue.Flush (); 
        } 
 
        Dispose (); 
    } 
 
    /// <summary> 
    /// Enqueue the active buffer to the OutputQueue 
    /// </summary> 
    void EnqueueBuffer () 
    { 
        currentBuffer.IsInUse = true; 
        OutputQueue.EnqueueBuffer (currentBuffer.Buffer, currentBuffer.CurrentOffset, currentBuffer.PacketDescriptions.ToArray ()); 
        queuedBufferCount++; 
        StartQueueIfNeeded (); 
    } 
 
    /// <summary> 
    /// Wait until a buffer is freed up 
    /// </summary> 
    void WaitForBuffer () 
    { 
        int curIndex = outputBuffers.IndexOf (currentBuffer); 
        currentBuffer = outputBuffers [curIndex < outputBuffers.Count - 1 ? curIndex + 1 : 0]; 
 
        lock (currentBuffer) { 
            while (currentBuffer.IsInUse) 
                Monitor.Wait (currentBuffer); 
        } 
    } 
 
    void StartQueueIfNeeded () 
    { 
        if (Started) 
            return; 
 
        Play (); 
    } 
 
    /// <summary> 
    /// When a AudioProperty in the fed packets is found this callback is called 
    /// </summary> 
    void AudioPropertyFound (object sender, PropertyFoundEventArgs args) 
    { 
        if (args.Property == AudioFileStreamProperty.ReadyToProducePackets) { 
            Started = false; 
 
            if (OutputQueue != null) 
                OutputQueue.Dispose (); 
 
            OutputQueue = new OutputAudioQueue (fileStream.StreamBasicDescription); 
            if (OutputReady != null) 
                OutputReady (OutputQueue); 
 
            currentByteCount = 0; 
            OutputQueue.BufferCompleted += HandleBufferCompleted; 
            outputBuffers = new List<AudioBuffer> (); 
 
            for (int i = 0; i < MaxBufferCount; i++) { 
                IntPtr outBuffer; 
                OutputQueue.AllocateBuffer (BufferSize, out outBuffer); 
                outputBuffers.Add (new AudioBuffer () { 
                    Buffer = outBuffer, 
                    PacketDescriptions = new List<AudioStreamPacketDescription> () 
                }); 
            } 
 
            currentBuffer = outputBuffers.First (); 
 
            OutputQueue.MagicCookie = fileStream.MagicCookie; 
        } 
    } 
 
    /// <summary> 
    /// Is called when a buffer is completly read and can be freed up 
    /// </summary> 
    void HandleBufferCompleted (object sender, BufferCompletedEventArgs e) 
    { 
        queuedBufferCount--; 
        IntPtr buf = e.IntPtrBuffer; 
 
        foreach (var buffer in outputBuffers) { 
            if (buffer.Buffer != buf) 
                continue; 
 
            // free Buffer 
            buffer.PacketDescriptions.Clear (); 
            buffer.CurrentOffset = 0; 
            lock (buffer) { 
                buffer.IsInUse = false; 
                Monitor.Pulse (buffer); 
            } 
        } 
 
        if (queuedBufferCount == 0 && Finished != null) 
            Finished (this, new EventArgs ()); 
    } 
} 
} 

我怎样才能更改代码以允许这样做?

在此先感谢您的帮助。

请您参考如下方法:

将以下代码放入 AppDelegate.csFinishedLaunching 方法中。

NSError sessionError = null; 
                AVAudioSession.SharedInstance().SetCategory(AVAudioSession.CategoryAmbient, out sessionError); 
 
AVAudioSession.SharedInstance().SetActive(true, out sessionError);