I have a iOS/watchOS app that gives audio cues, like a metronome, on specific patterns. The intent of the watch app is to have it at the same time as a workout app (ie Strava, Apple Fitness) and/or a music app (Spotify/Apple Music). The app works in the foreground just fine. But if I start another app (i.e. Strava) the haptic feedback and a "ding" continues to play in the background, but the "beep or voice" stops. Beep/voice works fine in iOS when in the background, just not in watchOS.
Audio cues not working when app is in the background
Thanks for the post. I'm not an expert on audio and less when that involves watchOS. So other watchOS engineers are hopefully jumping into the thread soon.
What I know is the behavior you are seeing is due to the strict differences in how watchOS handles background execution and audio compared to iOS.
When your app goes into the background on watchOS, custom audio playback like AVAudioPlayer or AVAudioEngine playing a voice or beep is immediately suspended unless specific background modes and sessions are active. The reason the ping sound and haptics continue is likely because you are triggering them via WKInterfaceDevice.current().play(.notification) or similar system-level calls, which are handled by a separate system and can fire as long as your app has any background execution time.
Since you want your app to play over music apps without stopping them, you must configure your AVAudioSession to mix with other audio. You should also consider using https://developer.apple.com/documentation/avfaudio/avaudiosession/categoryoptions-swift.struct/duckothers if you want music volume to temporarily lower.
What about workout apps? This is the most critical hurdle for your specific use case. If you are currently using an HKWorkoutSession to keep your app alive in the background, it will break when the user opens Apple Fitness or other workout session apps as watchOS only allows one active workout session at a time. If your app has an active workout session and the user starts a run in another workout app, watchOS terminates your workout session, which suspends your app. Extended runtime sessions have time limits, so keep this in mind for long workouts.
Albert Pascual Worldwide Developer Relations.
Hi and thanks for the additional information. WKExtendedRuntimeSession was added but that didn't help and I'm not using HKWorkoutSession so to not conflict with other workout apps. Hopefully a watchOS person will have an idea.
@sdgnetwork Thanks for the post, without that api looks like the watchOS is working correctly. Lets see what other ideas other developers have to help you.
Albert Worldwide Developer Relations.
To play audio in the background on watchOS:
- Your app must be running in the background at the moment.
- The audio session (AVAudioSession) needs to be configured with the right session category.
- The audio session needs to be activated when your app runs in the foreground.
Based on your description, I am wondering how you keep your app running in the background – are you using audio background mode, and what API you use to play a voice, if you don't mind to share.
After an app entered to the background, watchOS suspends it more aggressively. That may lead to subtly different behaviors on the two platforms, depending on how you test.
Best,
——
Ziqiao Chen
Worldwide Developer Relations.
We keep the app running in the background using WKExtendedRuntimeSession (with self-care background mode). The audio session is configured with .playback category, .longFormAudio policy, and .mixWithOthers + .duckOthers options, and activated while the app is in the foreground. For audio playback we use AVAudioPlayer(data:) with in-memory WAV data for metronome ticks, and AVSpeechSynthesizer for voice counts. We also run a continuous near-silent AVAudioPlayer loop to keep the audio session active between beeps.
Two specific questions:
Is WKExtendedRuntimeSession the correct mechanism for this use case, or should we use something else? (We can't use HKWorkoutSession since users run this alongside other workout apps.) Does .longFormAudio work correctly with .mixWithOthers, or are those contradictory?
As documented here, WKExtendedRuntimeSession is meant to be used with self care, mindfulness, physical therapy, or smart alarm. Using the API in other use case will risk an App Review rejection.
Will your use case be considered as self care (or other session type)? I can't speak for the App Review team, but you can probably start with contacting the team here to see what they have to say.
As documented here, WKExtendedRuntimeSession + self care is a frontmost session, which will expire in 10 minutes. Also, the session will be terminated if you explicitly leave your app by pressing the digital crown or switching to a different app. If that happens, your app will be suspended soon after, which may explain why your app can't play audio from background.
The other option is to use audio background mode, as described here, but again, I can't speak for App Review if your use case is qualified to use the mode.
Does .longFormAudio work correctly with .mixWithOthers, or are those contradictory?
My experience on audio is quite limited, but the community seems to be able to make it work. See here.
Best,
——
Ziqiao Chen
Worldwide Developer Relations.