Quantcast
Channel: Recent Threads — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 204402

Background Audio no longer works

$
0
0

This was working before the update, but now no matter what I do, the audio will not continue to play once the app is backgrounded...

Here is a snippet of my code:

Info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <!-- removed for clarity -->
    <key>MinimumOSVersion</key>
    <string>6.1</string>
    <key>UIBackgroundModes</key>
    <array>
        <string>audio</string>
    </array>
</dict>
</plist>

AppDelegate.cs

using System;
using MonoTouch.AVFoundation;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using Dervish.Midi;
using Dervish.Controllers;

namespace Dervish
{
    [Register ("AppDelegate")]
    public partial class AppDelegate : UIApplicationDelegate
    {
        NSError _error;
        UIWindow _window;
        Metronome _metronome;
        DervishViewController _viewController;

        public event EventHandler<AppStateEventArgs> OnApplicationStateChanged;

        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            //commented-out due to iOS 7 deprecation (not sure what the new alternative is supposed to be)
            //this was working in iOS 6.1, but is now broken in iOS7, so trying AVAudioSession instead...

            //AudioSession.Initialize();
            //AudioSession.Category = AudioSessionCategory.MediaPlayback;
            //AudioSession.OverrideCategoryMixWithOthers = true;

            AVAudioSession audioInstance = AVAudioSession.SharedInstance();

            //Event Handling...
            audioInstance.BeginInterruption += delegate {...};
            audioInstance.CategoryChanged += delegate {...};
            audioInstance.EndInterruption += delegate {...};
            audioInstance.OutputChannelsChanged += delegate => {...};
            audioInstance.SampleRateChanged += delegate => {...};

            //set audio buffer size
            audioInstance.SetPreferredIOBufferDuration(0.005, out _error);
            if (_error != null) {...}

            audioInstance.SetActive(true, AVAudioSessionSetActiveOptions.NotifyOthersOnDeactivation, out _error);
            if (_error != null) {...}

            audioInstance.SetCategory(new NSString("AVAudioSessionCategoryPlayback"), out _error);
            if (_error != null) {...}

            _window = new UIWindow(UIScreen.MainScreen.Bounds);
            _window.MakeKeyAndVisible();

            _metronome = new Metronome();
            _viewController = new DervishViewController(_metronome);
            _window.RootViewController = _viewController;

            //communicates app state change to view controller
            OnApplicationStateChanged += _viewController.ApplicationStateChangeHandler;

            //MIDI setup
            new NSObject().BeginInvokeOnMainThread(delegate {
                MidiHelper.Midi.Initialize();
            });

            //global exception handler...
            AppDomain.CurrentDomain.UnhandledException += delegate => {...};

            return true;
        }

        //Application Lifecycle / State Change Event Handlers... (i.e. OnActivated, WillEnterForeground, etc...)
    }
}

Metronome

using System;
using System.IO;
using System.Text;
using MonoTouch.AVFoundation;
using MonoTouch.AudioToolbox;
using MonoTouch.Foundation;
using Dervish.Enums;
using Dervish.EventArgs;
using Dervish.Interfaces;
using Dervish.Midi;

namespace Dervish
{
    public class Metronome : IDisposable
    {
        int _bpm = 120;

        NSError _err;
        AVAudioPlayer _player;

        HighPrecisionTimer _timer;
        public HighPrecisionTimer Timer { get { return _timer; }}

        public event EventHandler<BeatEventArgs> OnBeat;
        public event EventHandler<EventArgs> OnStop;

        public Metronome()
        {
            _timer = new HighPrecisionTimer(_bpm);
            _timer.OnPulse += HandlePulse;

            //loads sound from base64 file as binary array into memory to reduce HD access
            var base64 = File.ReadAllText("click_base64.txt", Encoding.UTF8);
            var data = new NSData(base64, NSDataBase64DecodingOptions.IgnoreUnknownCharacters);

            _player = AVAudioPlayer.FromData(data, out _err);
            if (_err == null)
            {
                _player.BeginInterruption += delegate {...};
                _player.DecoderError += delegate => {...};
                _player.EndInterruption += delegate {...};
                _player.FinishedPlaying += delegate => {...};

                //play once silently to initialize (otherwise there is significant lag on first use) 
                _player.Volume = 0.0f;
                _player.Play();

                this.OnBeat += (s, e) =>
                {
                    _player.Play();
                };
            }
        }

        public void Start(Status mode)
        {
            MidiHelper.SendStartMessage();

            _player.Volume = 1.0f;
            _timer.Start();
        }

        public void Stop()
        {
            MidiHelper.SendStopMessage();

            OnStop(this, null);

            _timer.Stop();
            _player.Stop();
        }

        void HandlePulse (object sender, PulseEventArgs e)
        {
            MidiHelper.SendClockMessage();

            if (e.CurrentPulsePerQuarterNote == 1)
            {
                OnBeat(this, new BeatEventArgs(BeatType.Down));
            }
        }

        public void Dispose()
        {
            if (_timer != null) { _timer.Stop(); }
            if (_player != null) { _player.Stop(); }
        }
    }
}

If I can't get this working, I'm dead in the water...


Viewing all articles
Browse latest Browse all 204402

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>