There are couple of questions already on SOW,about playing audio in background, but mine is a little different(as far as I could see!)
So I've a playlist in my app, where user can choose to play an audio in a loop, or a random/continuous playback for all the audios available in the app.
Using below code, and the required Info.plist setting:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
Info.plist setting:
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
The audio works properly in the background, and even when screen is locked, but the problem arises when the audio playback gets finished.
Using NSLogs, I can see that the code reaches again the AudioPlayer's "play" method, but the audio doesn't play the next song, or the song which was to be played in the loop.
Does anyone have pointers?
Reading the documentation, the relevant paragraph:
My audios are stored locally in the app.
When the UIBackgroundModes key contains the audio value, the system’s media frameworks automatically prevent the corresponding app from being suspended when it moves to the background. As long as it is playing audio or video content or recording audio content, the app continues to run in the background.
However, if recording or playback stops, the system suspends the app.
So essentially, to hack around the setup, I used two AVAudioPlayers, and instead of waiting for the delegate callback for audioPlayerDidFinishPlaying:, I worked this out:
if ((audioPlayer1.duration - audioPlayer1.currentTime) < 1) {
//play Audio 2
}
Not too sure if there's any better suggestion than this?
Related
Referring to the document https://developer.apple.com/library/ios/qa/qa1668/_index.html ,
I have modified the info.plist to support playback for HLS stream while app is in background, and removed/restored AVPlayer when app goes to background/comes to foreground using Application delegate events(application: app didBecomeActive and application: app didEnterBackground) , am certain that code gets executed as I can see the logs. Yet when I navigate out of the app by pressing home key on actual device, Airplay stops. Also, I added a KVObserver on the rate property of AVPlayer, the rate is 1 while the app is minimized.
One thing that I noticed was for the same piece of code, on simulator, If I simulate home key press (cmd+shift+h) , the audio for the video is audible while I am outside the app, while it stops on actual device. Am I doing something wrong?
Had to put the methods :
[[AVAudioSession sharedInstance] setDelegate: self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
in the app delegate, thought they were just for audio streaming, but for video as well are required for multitasking, this resolved the issue.
I checked Google and here as well. Maybe the question hasn't been asked yet or I am just asking it in a very weird way. There are certain apps, one that I've noticed in particular is Snapchat, where when the app opens, the music continues to play even with the camera and even while taking a picture with silent switch turn on or off. The camera sound goes off as well.
So for an example, right now I am listening to music through Soundcloud and when I open my app, the music stops playing, but I can press play and continue to play music while using my app once I put this line of code in my appWillEnterForeground method: [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
When I do this in Snapchat, the music continues to play. Even when I take a video too!
How?
There has to be some code that uses the AV system for audio in the way. Check for a call like
[session addInput:audioDeviceInput];
where session is an instance of AVCaptureSession.
To demonstrate and research, you can take the Apple example AVCam (https://developer.apple.com/library/ios/samplecode/AVCam/Introduction/Intro.html) and run it from XCode. When music is playing, it will stop playing when the AVCam app starts.
Now open the source file AVCam/AVCamViewController.m and search for the line
[session addInput:audioDeviceInput];
When you delete this line or comment it out, music will continue to play when you run the app.
Off course, there may be other statements that block the sound playing in your app. Check calls to methods from AV objects and look especially for audio input and output.
I have an app that needs to use AVAudioSessionCategoryPlayback in order to play sound while the device is locked or my app is in the background. (It's an alarm feature.) So I also need to set the "audio" key in my UIBackgroundModes list.
I have put the following code in my application:didFinishLaunchingWithOptions: method:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
withOptions:AVAudioSessionCategoryOptionMixWithOthers
error:nil];
However, I don't want to interrupt any music that is already playing on the device. When my app is launched, it causes Spotify (for example) to stop playing music. I can switch to Spotify and press play, and when I switch back to my app, it continues playing.
But this is very annoying to the user - alarms are not the only thing my app does, and there are many reasons for them to launch it that don't involve setting alarms. I don't think the user would ever want my app to stop any other audio playing on the device.
Ideally I'd never interrupt already-playing audio. I could also live with stopping audio when an alarm is set (at which point I have to activate my audio session to ensure that I'm able to play it) but it seems like there is no way for me to avoid the audio stop at app launch.
Is there some way to start my app with the audio session disabled, or to start it with this option already applied?
It turns out that I was calling .prepareForPlayback() on an AVAudioPlayer in an init() method which was getting called long before my didFinishLaunchingWithOptions: fired.
I have an app that plays several webvideos like Youtube and Vimeo in a UIWebView. When the video plays it is possible to send it to an Apple TV over AirPlay.
Currently, during playback over AirPlay the video stops when I pause the app and move it to the background.
My desired result is that the video will keep playing on the Apple TV.
After some research I found out that I have to set the Required background modes in the Info.plist to App plays audio. Unfortunately this did not work.
So what does need to be set to keep the video playing over AirPlay when the app is moved to the background.
i've tested this on iOS6 with UIWebView loading video webpage, and it does the job. the audio session needed to be set as AVAudioSessionCategoryPlayback in order to be played in background.
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
We built our music-oriented app in html5 and javascript with Sencha touch. For distribution we wrapped it in xcode with UIwebView. Everything runs fine except one thing that does not work: audio playing in multitask mode.
I know the general idea: add the UIBackgroundModes in info.plist.
Done. Now we can play the audio even in background mode.
Until we reach the end of the song. To start the next song we have to bring the app to foreground again or we can hit the play or 'next song' button on the iPhone audio controller.
After some research I found a promising workaround at: " Entering background on iOS4 to play audio " where the workaround is to edit AVAudioSessionCategoryPlayback and work with the UIBackgroundTaskIdentifier.
The problem for me is (just like in any other fix I found so far) that those solutions always assume that the audio is played either with AVaudioPlayer or MPMusicPlayerController. But in my case I user neither, our audio is played by our html5 player wrapped in UIwebView.
Anyone has any advice on how to continue playing the audio in iOS multitask mode when the audio player is a html5/javascript player?
My app plays audio via an <audio> tag in html hosted in UIWebView, and it supports background playing.
As you suggest, you need to have the 'App plays audio' background mode defined in your plist.
Try adding this to your applicationDidFinishLaunching: handler:
NSError *setCategoryError = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &setCategoryError];
Thanks, guys, but I ended up simply keeping the app busy in a loop when in background mode. This was enough to bridge the time when connecting to the next song on the playlist.
The code I used is similar to this one:
iPhone - Backgrounding to poll for events
You could try this, adding a function on the onend event.