I am developing an iphone app which uses background audio (on an infinite loop) to continue playing after the app has entered the background.
My problem is I want to implement a "sleep timer" which stops playback after a specified period of time.
Is this possible? I have spent an hour looking for a method to do this with no avail.
EDIT: My current thought is to use a lower level API, the Audio Queue Services, and manually re-fill the queue with another instance of the loop during the AudioQueueOutputCallback. If the timer has expired I do not fill the loop. I'm assuming this should work since the documentation says audio callbacks are still fired when an app is playing multitasking background audio. Can anyone think of a better way or a reason why this wouldn't work?
While you queue sound data on the background your app remains fully functional and running as if it was in the foreground (well almost), so yes, you should just write a timer that stops the playback at a given time and it will be fired as expected.
Now to the second question: once you stop queueing things up, your app will be "frozen" until the user manually brings it to the foreground... So what you should do is start queueing audio data from the second file before the first one is done playing, and if you DO need to pause or stop, maybe a solution is to play 0 bytes (silence)?
I'm not actually sure this would be allowed in the App Store. An app is not allowed to execute at all in the background, with the exception of VoIP apps and push notifications.
Related
I have a Clock Alarm app that plays sound at certain time (Sending local notifications). Is it possible to play loop sound at certain time (when local notification comes) when app is placed in background ?
Just want to specify: I need to play loop sound, not only once
No. The reason why is because you won't be able to execute any code because of a local notification. One thing you can do, and it's totally up to you if this is something your app really needs to di, it to list this application as an audio application on the UIBackgroundModes key of your .plist file, and just change song that is playing at the time it has to. You can use a dispatch_after block to change the song at the time you want it to.
Make your app a long running background app as described in this link here
Well I am having two issues that i can't get to work, related to audio and calls.
The first one is to play a sound during a phone call. I don't want to play continuous music or stream anything, it is just a simple and short sound that the user will hear at one time during his call.
I have read some posts claiming that this is possible, and I even have an application that does so, but I can't get it to work. My app identifies the call using CTCallCenter and print the logs but never plays the sound or plays it after the app comes to foreground again. I have the .plist property of required background mode App plays audio.
The second issue, is to play the sound after some elapsed time. NSTimers doesn't work when on background mode, nor NSThread sleep on my background process or NSOperation. So how could I play this sound after say 10 seconds of the call?
Also, this behavior has to work also when the application is already on background mode. With CTCallCenter I am only getting the event when the application is interrupted from use, but I don't see any logs when i send the app to background and then begin/receive a call
.
If anyone could point me to the right direction I'll be really grateful.
I havent done this, but NSLocalNotifcation, schedule a notification to play when you app get the call to move into the background. I would expect this to work. Interested to find out if it does.
I have an audio app that is having some problems with the way iOS 5 has changed audio behaviors. When my app's audio is playing (AVAudioSessionCategoryPlayback), and a Clock.app alarm or timer is fired from the OS, the UIAlertView notification pops up, but without the audio alert. My application sound ducks fine to get out of the way of the audio alert, but the alarm app's audio alert does not sound.
Naturally, tons of support requests poured in over the iOS 5 change. I have solved this temporarily by setting kAudioSessionProperty_OverrideCategoryMixWithOthers which lets the alarm audio come through, but there are a few very undesirable side-effects when doing this:
Other app's audio can play with/over mine.
The remote control events are not routed to my app, but to iPod.app.
None of the above drawbacks are acceptable for my app's requirements. I have been hacking away at this for some time now but haven't been able to crack it. How can I setup my audio such that:
My app's audio still uses the AVAudioSessionCategoryPlayback category for background audio.
The Clock.app alarms still have their audio alerts make sound
The app still responds to remote control notifications
After writing this question I went to file a bug report on this. I created a small sample project that I thought would replicate the issue, but I could not replicate it! This caused me to dig in deep once again and try to figure out what was up here…
I fired up an iOS alarm, then I placed a break point in audioPlayerBeginInterruption: and traced through my code line by line in the debugger. I noticed that before my code ran (while I was paused in the debugger), the iOS 5 alarm was sounding! Luckily it still sounded even as I was stepping through my app, so I was able to figure out which pieces of code specifically caused it to stop sounding.
Part of my interruptionHandler is to (obviously) stop the internal audio of my app to let the interruption come through. I never thought to inspect this method before, but turns out the problem existed in there. My stop method would call prepareToPlay immediately after stopping to make resuming faster the next time.
[self.player stop];
[self.player prepareToPlay]; // <- iOS 5 alarm sound stopped here.
The docs state the prepareToPlay method
preloads buffers and acquires the audio hardware needed for playback, which minimizes the lag between calling the play method and the start of sound output.
Sounds reasonable, and this worked for lesser iOS versions. My hypothesis is that must have made a change to the Clock.app alarm system such that the new alarm sounds use the hardware, whereas before it used the software. This is what I think is causing the iOS 5 alarms to be silent in some apps.
Removing the prepareToPlay lines caused the alarm to sound without using kAudioSessionProperty_OverrideCategoryMixWithOthers, thus solving all my issues laid out in this question.
TL;DR
Remove the prepareToPlay calls from your stop sound code logic. It will take a microsecond longer to start later, but will allow interruptions to sound.
I am writing an audio application which plays media items from the iPod music library using the iPod music player.
Now I know it is possible for the iPod to carry on playing when it is in the background, but I want to also run either a Thread or a Timer in the background where a selector method periodically checks the state of the music player so that the app can apply rules in order to apply delays between tracks, and automatically load up new media collections into the player all while in the background.
Is this possible?
If not, is there any other method for achieving this functionality?
The trick is to not use MPMusicPlayerController as when your app enters the background it actually relinquishes control to the iPod app (you can check this by closing your app and opening the iPod app).
For the music app I'm currently developing I've rolled my own music player using AVAudioSession and AVPlayer (not AVAudioPlayer). I've implemented a queue on the player, and a datasource (similar to UITableViewDatasource) which feeds the queue. All of this works eloquently whilst running in the background and has no association what ever with the iPod app (and as an added bonus you apps icon appears next to the remote controls on mulitasking bar).
If you developed something similar then when you ask your datasource for the next item in the queue, you could query your rule set and take a decision on what to do next.
Sure. You can do this in the application delegate's applicationDidEnterBackground:.
From the template:
If your application supports background execution, this method is
called instead of applicationWillTerminate: when the user quits.
Well yes and now, you can't use NSTimer because they are invalidated.
You can start a block of code to run via GCD to run in background which will have the max. execute time of 10 min.
I have an alarm clock app which works on a timer. When the alarm is meant to go off and the screen is switched off, it should start playing audio from AVAudioPlayer, but it doesn't. Then when i turn the screen back on, i can see that the rest of the code fired as expected (a stop button is now on the screen). How do i get the AVAudioPlayer to play when the screen is turned off?
Is there any way for me to detect that the screen is turned off?
#zoul is correct that using the default audio session category will result in sound form your app being disabled when the user locks the screen. See the Audio Session Programming Guide for direction on which audio session category you should choose.
However, even once your audio session category is set correctly, you'll have another issue to tackle. When the screen is switched off, your application gets suspended per Apple's documentation here: Executing Code in the Background. This means that when the user locks their phone or switches to a different app, your app will stop running and stay in a freeze-dried (task-suspended) state until the user activates your app again. At that point, your app resumes execution as if nothing happened. That's why it appears that your app has continued to function when you unlock the screen.
For alarm behavior, you'll probably want to schedule the delivery of a local notification. A local notification will ensure that the system provides your alert to the user at the time you request, and allows the user to activate your app. See Scheduling the Delivery of Local Notifications for details on how to accomplish this.
Maybe you have the wrong audio category? See the documentation for AVAudioSession, especially the audio category settings.