C# 当屏幕关闭时,mp3停止播放
我正在开发一个应用程序,我需要从url播放音乐。 我使用的是代码,它工作得很好。 但是,当播放歌曲时,屏幕关闭,音乐停止。我需要音乐继续播放直到结束,即使屏幕关闭 我想我必须更改此文件,但我不知道如何:C# 当屏幕关闭时,mp3停止播放,c#,ios,xamarin,xamarin.ios,streaming,C#,Ios,Xamarin,Xamarin.ios,Streaming,我正在开发一个应用程序,我需要从url播放音乐。 我使用的是代码,它工作得很好。 但是,当播放歌曲时,屏幕关闭,音乐停止。我需要音乐继续播放直到结束,即使屏幕关闭 我想我必须更改此文件,但我不知道如何: using System; using AudioToolbox; using System.Threading; using System.Collections.Generic; using System.Linq; namespace SecondoSenso { /// <sum
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 ());
}
}
}
使用系统;
使用音频工具箱;
使用系统线程;
使用System.Collections.Generic;
使用System.Linq;
名称空间SecondoSenso
{
///
///将所有设置保存在一起的AudioBuffer的类
///
内部类音频缓冲区
{
公共IntPtr缓冲区{get;set;}
公共列表包描述{get;set;}
public int CurrentOffset{get;set;}
公共布尔值为{get;set;}
}
///
///包装OutputQueue和AudioFileStream,以允许各种文件类型的流
///
公共类StreamingPlayback:IDisposable
{
public bool boolDispose=false;
公共事件事件处理程序已完成;
公共事件行动输出;
//音频工具箱解码器
音频文件流;
int bufferSize=128*256;
列出输出缓冲区;
音频缓冲器;
//最大缓冲区
int maxBufferCount=4;
//跟踪所有排队的缓冲区,以便我们知道播放已完成
int queuedBufferCount=0;
//当前文件流位置-如果我们不跟踪,我们不知道何时推送最后一个未完成的缓冲区
长currentByteCount=0;
//用于触发最后一个缓冲区的转储。
bool-lastpack;
公共输出队列;
公共bool已启动{get;private set;}
公众浮存量{
得到{
返回OutputQueue.Volume;
}
设置{
OutputQueue.Volume=值;
}
}
///
///定义搜索缓冲区的大小,当使用较慢的源时,使用缓冲区大小较低的更多缓冲区
///
公共int缓冲区大小{
得到{
返回缓冲区大小;
}
设置{
缓冲区大小=值;
}
}
///
///定义要使用的最大缓冲区数,只有在调用重置或
///StreamingPlayback是新实例化的
///
公共整数MaxBufferCount{
得到{
返回maxBufferCount;
}
设置{
maxBufferCount=值;
}
}
public StreamingPlayback():这个(AudioFileType.MP3)
{
}
公共流媒体播放(AudioFileType)
{
fileStream=新的音频fileStream(类型);
fileStream.PacketDecoded+=音频包解码;
fileStream.PropertyFound+=AudioPropertyFound;
}
公共无效重置()
{
if(fileStream!=null){
Close();
fileStream=新的音频文件流(AudioFileType.MP3);
currentByteCount=0;
fileStream.PacketDecoded+=音频包解码;
fileStream.PropertyFound+=AudioPropertyFound;
}
}
public void ResetOutputQueue()
{
if(OutputQueue!=null){
OutputQueue.Stop(true);
Reset();
foreach(输出缓冲区中的音频缓冲区buf){
buf.PacketDescriptions.Clear();
OutputQueue.FreeBuffer(buf.Buffer);
}
outputBuffers=null;
Dispose();
}
}
///
///停止输出队列
///
公共空白暂停()
{
Pause();
开始=错误;
}
///
///启动输出队列
///
公共虚空游戏()
{
OutputQueue.Start();
开始=真;
}
///
///Main方法要启动流,只需将字节发送到此方法
///
public void ParseBytes(字节[]缓冲区、整数计数、bool不连续性、bool lastPacket)
{
this.lastPacket=lastPacket;
fileStream.ParseBytes(缓冲区、0、计数、不连续);
}
公共空间处置()
{
处置(真实);
GC.1(本);
}
公共无效处置(int tt){
}
///
///清理所有本机资源
///
受保护的虚拟void Dispose(bool disposing)
{
如果(处置){
if(OutputQueue!=null)
OutputQueue.Stop(true);
如果(outputBuffers!=null){
foreach(outputBuffers中的变量b)
OutputQueue.FreeBuffer(b.Buffer);
Clear();
outputBuffers=null;
}
if(fileStream!=null){
Close();
fileStream=null;
}
if(OutputQueue!=null){
Dispose();
OutputQueue=null;
}
}
}
///
///将解码的数据包保存到活动缓冲区,如果缓冲区已满,则将其排入OutputQueue
///并等待另一个缓冲区释放
///
void AudioPacketDecoded(对象发送方,PacketReceivedEventArgs参数)
{
foreach(args.PacketDescriptions中的变量p){
currentByteCount+=p.DataByteSize;
AudioStreamPacketDescription pd=p;
int left=bufferSize-currentBuffer.CurrentOffset;
if(左NSError sessionError = null;
AVAudioSession.SharedInstance().SetCategory(AVAudioSession.CategoryAmbient, out sessionError);
AVAudioSession.SharedInstance().SetActive(true, out sessionError);