I have implemented Audiostreamer class of Matt Gallagher in my application and it works fine in ios4. But when I switched to iOS5 the background playing is not working in there.
I have added UIBackground Modes and Application does not run in Background plist values to my application. So I think the issue is something else.
it wont work in simulator, you're not in simulator are you?
#j_mcnally iOS5 Simulator supports background playing.
#thoughtbreaker In Matt Gallagher there are some flows. Does your audio not play in the background at all or it stops after one track is finished playing.
If its not playing at all in the background than there may be buffering related problem...
You should use Background expiration handler, in your audioStateChange method, but only when app is in the background.
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:nil]
}];
You can check the background mode by setting a global flag in applicationDidEnterBackground method
Also invalidate the handler in your audioStart Playing method
[app endBackgroundTask:bgTask];
Related
I am working on iOS app in which i am creating video from images. I am using AVAssetWriter to achieve this. Everything works fine. But When app goes in background and switched back, the video writing fails. AVAssetWriter's finishWritingWithCompletionHandler is not getting called when i switch back to app.
May be duplicate of AVAssetWriter fails when Application enters Background during Rendering , but i am not getting any help from there.
Any idea for this?
Thanks
This answer is based on the assumption that you want the video to continue rendering while in the background.
I fixed this in my app doing by asking the OS to grant the app background task permisions (for a limited amount of time). This answer might help you too
iOS generating a video in the background task
#property (nonatomic,assign) UIBackgroundTaskIdentifier __block backgroundRenderingID;
UIApplication *app = [UIApplication sharedApplication];
_backgroundRenderingID = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:_backgroundRenderingID];
_backgroundRenderingID = UIBackgroundTaskInvalid;
}];
Don't forget to let go once you are done!
[[UIApplication sharedApplication] endBackgroundTask:_backgroundRenderingID];
in my app, when I want to stop an audio recorder, works fine for iOS 5 an 6.0.x
[self.audioRecorder stop];
calling to the method audioRecorderDidFinishRecording
But in iOS 6.1.x, doesn't.
The app get stuck, and doesnt call to audioRecorderDidFinishRecording
any ideas? please
There are a lot of questions relating to background music playback in iOS on StackOverflow. None fully explore all edge cases, the aim of
this question is to be the final word in background audio question on
iOS
Definitions & Assumptions
All the code, questions and examples refer to ios5.
"background" — The state an app is put into when the user presses the home button or the power button (so the devices displays the lock screen). The app can also be put into background using the multitasking switcher or the multitasking gestures on iPad.
"audio" — Audio played back using AudioQueue (including AVAudioPlayer)
Prerequisites
As I understand it there are 2 requirements to get an app to play audio in the background.
Set UIBackgroundModes to audio in the Info.plist
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
Requirements
My use-case is playing relatively long audio in the background (music). There are potentially hundreds of tracks and the app will play them sequentially. It can be considered that the audio will play indefinitely.
The app will handle interruptions by pausing the playback.
Questions
I've had mixed success with:
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:...];
Allowing audio to play in the background. But I'm confused as to if its required and how it differs to:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
Edge Cases
Interruptions. If you register to be notified of audio interruptions (phone calls etc), by becoming the delegate of AVAudioPlayer. For example, if you then pause or stop your audio when an interruption starts and resume when it ends is your app suspended if the interruption exceeds 10 minutes (max time allowed for background tasks to complete)?
The Simulator will stop the audio if Lock or Home are invoked, while using:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
However this works on a device. Is this a known issue?
I have some experience with GPS background mode, and background audio. This is not exactly the same as your situation (you want to play a long audio file, and I play short messages) but here's what I can tell you:
beginBackgroundTaskWithExpirationHandler This selector has one purpose when being invoked when in background: avoid the application to return to the suspended state in which no code can be invoked anymore (you're "frozen"). So as long as you invoked beginBackgroundTaskWithExpirationHandler and before you terminated your long running task with beginBackgroundTaskWithExpirationHandler, you use the CPU, and consume battery.
I really doubt that playing a file in the background should use the battery of the iPhone as if it was running an app so I doubt that beginBackgroundTaskWithExpirationHandler is really involved in your flow.
Simulator: don't rely on the simulator: it does not fully implement background modes. Actually, when you click on the home button, your app goes in background, but at this stage, you may still be able to execute code in your app. After a while, then, your app will be suspended (=frozen), and your code execution will be suspended in order to save the battery.
This suspended state will never occur on the simulator.
Interruptions. It's not up to you to pause/resume the playback when a phone call comes in. the platform is in charge of this, and you can just react to this with your AVAudioSessionDelegate . However, you can influence the way your session is going to interact with other audio sounds by setting property on your audio session (see kAudioSessionProperty_OverrideCategoryMixWithOthers for instance).
So the flow is more: your describe the way your audio session should interact with the rest of the system, the system will mix the sounds accordingly to that, and if your session gets interrupted, you'll be notified with the AVAudioSessionDelegate.
Hope this helps.
I have used below code to Device Control -
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
Used to get register for listening the remote control.
Once done remove it -
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
make the App canBecomeFirstResponder-
- (BOOL)canBecomeFirstResponder {
return YES;
}
Used delegate method to handle iPhone control, like play and pause while doble tap on the home button
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
//if it is a remote control event handle it correctly
if (event.type == UIEventTypeRemoteControl) {
if (event.subtype == UIEventSubtypeRemoteControlPlay) {
[audioPlayer play];
NSLog(#"play");
} else if (event.subtype == UIEventSubtypeRemoteControlPause) {
[audioPlayer stop];
NSLog(#"pause");
} else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause) {
NSLog(#"toggle");
}
}
}
we have an app that has a specific purpose where an exit is required. After the exit a process needs to run in the background for a certain amount of time or until finished. We just need to know how to programmatically force the app to enter the background where processes can continue running. Any help on this would be great! Thanks in advance!
UPDATE: We have confirmed that there does not seem to be a programmatic way to force the app to quit / enter background and continue running background tasks. You can force the the app to exit using exit(0); but this kills the app all together. However, the bulk of this question was concerning running tasks in the background. We have found a solution that allows our app to begin processing data and handling tasks that a user has setup to be processed. Here is the code required. This needs to be added to the app delegate and multitasking is required on the device / IOS.
- (void)applicationDidEnterBackground:(UIApplication *)app{
// Check that IOS supports multitasking
if ([[UIDevice currentDevice] respondsToSelector:#selector(isMultitaskingSupported)]){
// Check that the device supports multitasking
if ([[UIDevice currentDevice] isMultitaskingSupported]) {
// Custom setting to allow users the freedom to enable or disable background tasks
BOOL enabled = [[NSUserDefaults standardUserDefaults] boolForKey:#"backgroundTasksEnabled_key"];
if ( enabled ){
//Get the shared application instance
backGroundApp = [UIApplication sharedApplication];
background_task = [backGroundApp beginBackgroundTaskWithExpirationHandler: ^ {
[backGroundApp endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
}];
// Run in background
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"\n\nProcess background tasks!\n\n");
// Do your work here
});
}
}
}
}
You can force an iOS app into the background by sending a registered URL to another app to handle, such as a web site URL to Safari.
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: myWebsiteURL ]];
Many many apps that call Safari to handle URLs are approved by Apple.
To get any time in the background, an app has to be appropriately configured using one of the allowed background modes (audio, location or VOIP); or the app can request a few minutes of extra time in the background before being suspended by calling the beginBackgroundTaskWithExpirationHandler method
You can't have a process running (doing work) in the background in iOS, you get a few seconds when the app quits to do any clean up and that's it!
You cannot force an application into the background, I'm fairly sure that Apple's guidelines prohibit you from doing that. What could your app possibly be doing that it can only do in the background and not in the foreground?
how to set iPhone device to stay active ( to not lock ) while my app is running ?
Any idea
I'm not sure if this prevents the device from locking, but you can prevent the screen from dimming with the UIApplication's idleTimerDisabled property:
[UIApplication sharedApplication].idleTimerDisabled = YES;
From the documentation:
Important: You should set this property only if necessary and should be sure to reset it to NO when the need no longer exists. Most applications should let the system turn off the screen when the idle timer elapses. This includes audio applications. With appropriate use of Audio Session Services, playback and recording proceed uninterrupted when the screen turns off. The only applications that should disable the idle timer are mapping applications, games, or similar programs with sporadic user interaction.
This code will prevent your iPhone from going to sleep while your app is running
// avoid sleeping when this application is running
UIApplication *application = [UIApplication sharedApplication];
application.idleTimerDisabled = YES;
// Or simpler
[[UIApplication sharedApplication] setIdleTimerDisabled: YES];
If you landed here looking for an answer in Swift, it's this:
UIApplication.sharedApplication().idleTimerDisabled = true
for Swift 3
UIApplication.shared.isIdleTimerDisabled = true
The warning in this comment still applies.