Code Examples for starting background audio from an AppIntent

Hi all,

I'm trying to update my app to use the AppIntent framework to play an audio file (loaded from the main bundle).

I tried implementing an a PlayMusicIntent using the AudioStartingIntent protocol, but have had no luck. The intent does run, and provides the dialog response, but the music doesn't start.

struct PlayMusicIntent: AudioStartingIntent {
    static let title:LocalizedStringResource = "Play Music"
    
    @MainActor
    func perform() async throws -> some IntentResult & ProvidesDialog {
        guard let musicPath = Bundle.main.url(forResource: "moonglow", withExtension: "mp3") else { fatalError("Could not load music file") }
        do {
            let musicPlayer = try AVAudioPlayer(contentsOf: musicPath)
            musicPlayer.numberOfLoops = -1
            musicPlayer.play()
            
            return .result(dialog: "Now Playing Moonglow")
        }catch {
            print(error)
            return .result(dialog: "There was an error playing the music: \(error.localizedDescription)")
        }
        
        return .result(dialog: "Cannot play music")
    }
}

And then add this in my App Shortcuts Provider:

AppShortcut(intent: PlayMusicIntent(), phrases: [
      "Play music with \(.applicationName)"
])

I do have Audio background mode enabled. I'm thinking I need to do something with the intent's return type, but there is not a lot of documentation or online examples to implement AudioStartingIntent

Any suggestions would be appreciated.

Thanks,

Scott

Post not yet marked as solved Up vote post of sbf0202 Down vote post of sbf0202
1.2k views

Replies

I'm doing tests for a similar situation, although I only need to play a short audio instead of a full song or playlist. I finally was able to make It work by awaiting the audio to be finished before returning in the perform() method. It looks like it's not your case but it might give you at least an idea.

  • Hey, I have this same problem. Can you please share your AppIntent code that plays audio? For instance, what are you awaiting?

    It seems like the code in "Implement App Shortcuts with App Intents" WWDC22 session (https://developer.apple.com/videos/play/wwdc2022/10170/) may hold some keys.

    Thanks!

  • Basically I did a wrapper over my playing class that converted the audio player delegate methods into an async/await function that is resolved when the audio is finished. Then, inside the perform() method I use await player.startPlaying() (my custom object) and it plays normally when the automation is launched.

Add a Comment

Really very keen to understand how you've managed to get this working too - I have a button in my Widget, that I want to play a sound when pressed

Hey, I've finally got this working! I would say the key is to manage the playback in the app instead of the intent. For example, create a player object in AppDelegate that adds a notification observer for "play" requests. Then in the app intent post a "play" request notification. That should be received by the player object so it can then play what is requested.

A rudimentary code example is here: https://github.com/teaseaque/ManagingAudioWithIntents

  • This looks very promising. I'll try implementing this tonight.

    Thank you for sharing this!

    Scott

Add a Comment