AVAudioPlayer Play fails after returning to the app from Locked state or just app sleeping for some time

82 Views Asked by At

I need to play a lot of short sounds quickly and using a separate AVAudioPlayer for each sound. I am using here C# because I use .Net MAUI but it doesn't matter. Everything works like on native iOS. Preloading sounds. AVAudioPlayer object is stored for later use (it is not garbage collected because it is stored on the singleton that is alive as long as the app is running).

var player = new AVAudioPlayer(url, null, out _);
player.PrepareToPlay();

I don't need to play them in background so initialization of the session looks like this

AVAudioSession.SharedInstance().SetCategory(AVAudioSessionCategory.Playback);
AVAudioSession.SharedInstance().SetActive(true);

Playing a sound

audioPlayer.Play();

It works fine but when I lock the screen and unlock it and then call Play() it returns false from Play() and not playing any sounds. Is there a way to get an error message about the problem that prevents it playing?

audioPlayer.Play(); // Returns false

I tried to initialize session again by setting category but that doesn't fix the problem.

Recreating AVAudioPlayer fixes the problem but that isn't a good fix because I would like fixing the problem before user taps on a button to play a sound.

I haven't found any way to know beforehand that after returning into the app playing sounds is broken. Because a lot of times it works fine even after lock/unlock. Reloading all the sounds (which are 88 in my case) upon every user is returning to the foreground isn't a good idea because playing sounds isn't the core functionality of the app.

Any ideas how to fix it properly?

1

There are 1 best solutions below

4
Liqun Shen-MSFT On

According to the iOS lifecycle events, the app comes to Background modes thus DidEnterBackground is invoked when the screen is locked.

When it is unlocked, the app will enter foreground and WillEnterForeground method is invoked.

Recreating AVAudioPlayer fixes the problem but that isn't a good fix because I would like fixing the problem before user taps on a button to play a sound.

So you may override the WillEnterForeground method and recreate AVAudioPlayer in it,

[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate
{
    protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

    public override void WillEnterForeground(UIApplication application)
    {
        //Console.WriteLine("App entering background state.");
        //You may active or initialize the session here
        //AVAudioSession.SharedInstance().SetActive(true);

    }
    public override void DidEnterBackground(UIApplication application)
    {
        // When the screen is locked, this method is invoked
        Console.WriteLine("App entering background state.");
    }

Hope it helps!