2016-10-12 21 views
1

私はアプリを開発しています。私はurlから音楽を再生する必要があります。 私はthisコードを使用しており、正常に動作します。 しかし、曲が再生されていて、画面がオフになると、音楽は停止します。私は、画面が消えても、音楽が終わりまで演奏を続けなければならないことが必要です。xamarin.ios画面がオフになるとmp3が停止するのを止める

私は、このファイルを変更しているとし、しかし、私は方法がわからない:

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

携帯電話がスリープ状態になると、アプリが一時停止します。あなたのアプリが実行を続けるのをやめたら、バックグラウンドで実行するために登録する必要があります。

Here is a nice guide Jonathan Sagorin(Swift/obj-cから上書きしてもかまいません)。

お探しのクラスは、基本的にAVAudioSessionとなります。SetActiveバックグラウンドオーディオセッションを有効にする方法です。

3

FinishedLaunching方法のAppDelegate.csに次のコードを入れてください。

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

AVAudioSession.SharedInstance().SetActive(true, out sessionError); 
関連する問題