xamarin.ios当屏幕关闭时,mp3停止播放

时间:2016-10-12 05:18:05

标签: c# ios xamarin xamarin.ios streaming

我正在开发一款应用,我需要播放来自网址的音乐。 我正在使用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 ());
    }
}
}

如何更改代码才能允许?

提前感谢帮助。

2 个答案:

答案 0 :(得分:3)

当手机进入睡眠状态时,应用会暂停。如果您的应用程序不能继续执行,则必须注册后台执行。

Here is a nice guide Jonathan Sagorin(如果你不介意将其从Swift / obj-c中删除)。

您正在寻找的课程基本上是AVAudioSession及其table.Columns.Add("bar").SetOrdinal(table.Columns.IndexOf("foo")+1); 方法来激活背景音频会话。

答案 1 :(得分:3)

将以下代码放在AppDelegate.cs方法的FinishedLaunching中。

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

AVAudioSession.SharedInstance().SetActive(true, out sessionError);