MPMusicPlayerController Play music while app is in background - ios

Hope this question doesn't get down voted - I haven't seen anything in the documentation.
I want to play music from the ipod library while the app is in the back ground.
I am creating the music player using the default mechanism.
-(void)viewWillAppear:(BOOL)animated
{
MPMusicPlayerController *myPlayer =
[MPMusicPlayerController applicationMusicPlayer];
// assign a playback queue containing all media items on the device
[myPlayer setQueueWithQuery: [MPMediaQuery songsQuery]];
// start playing from the beginning of the queue
[myPlayer play];
}
As soon as the app enters the background the music stops playing. I would like it to continue playing though.
I do not want to use the iPodMusicPlayer option
How can I do this?

You should set background audio mode in the project settings (Project settings > Capabilities > Background modes > Audio and AirPlay) like it's shown on the screenshot below:
Also you should set Audio Session Category in the appDelegate (in the didFinishLaunching method). Example is shown below:
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];

I have same issue. I searched even after added flag in plist. It will not work because :
The applicationMusicPlayer does not support background music. Use
MPMusicPlayerController's systemMusicPlayer instead. It shares the
state with the built-in System player and music will continue to play
when your app enters the background.
Other Solution is :
You can use AVAudioPlayer to play either streamed or local(bundle) audio. It even allows you to play multiple audio file at the same time having an AVAudioPlayer instance for each.
Note : iPodMusicPlayer is deprecated. so Instead of this use systemMusicPlayer.

Related

Audio Player play in background and should work based off of hardware mute switch

I want to play audio file in the foreground, background and it should work with mute switch i.e. if mute switch is on, then it should not play, if mute switch is off should play audio.
**I'm developing an SIP call application. App should play sound/ringtone when user receives a call. It should play if app is in background/foreground, it should mute/unmute if hardware mute switch is ON/OFF.
For this I used AVPlyaer with below code.
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:&error];
[session setActive:YES error:nil];
NSURL * audioFileUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"test1" ofType:#"mp3"]];
AVPlayer *player = [[AVPlayer alloc] initWithURL: audioFileUrl];
[player play];
And also I added "App plays audio or streams audio/video using AirPlay" to background modes in info.plist
This is playing in both modes but not mute when hardware mute switch is ON.
If I use AVAudioSessionCategoryAmbient not playing on the background mode.
I used AVAudioPlayer but not able to find mute when hardware switch is ON
Your Audio Session Category might be set incorrectly.
Since you want to respect the mute switch, you should use SoloAmbient
AVAudioSessionCategorySoloAmbient
The category for default category,
used unless you set a category with the setCategory:error: or
setCategory:withOptions:error: method.
Your audio is silenced by screen locking and by the Silent switch (called the Ring/Silent switch on iPhone).
By default, using this category implies that your app’s audio is
nonmixable—activating your session will interrupt any other audio
sessions which are also nonmixable. To allow mixing, use the
AVAudioSessionCategoryAmbient category instead.
Available in iOS 3.0 and later.
You appear to have used this category:
AVAudioSessionCategoryPlayback
The category for playing recorded music or other sounds that are central
to the successful use of your app.
When using this category, your app audio continues with the Silent switch set to silent or when the screen locks. (The switch is called
the Ring/Silent switch on iPhone.) To continue playing audio when your
app transitions to the background (for example, when the screen
locks), add the audio value to the UIBackgroundModes key in your
information property list file.
By default, using this category implies that your app’s audio is
nonmixable—activating your session will interrupt any other audio
sessions which are also nonmixable. To allow mixing for this category,
use the AVAudioSessionCategoryOptionMixWithOthers option.
Available in iOS 3.0 and later.
Source:
https://developer.apple.com/library/prerelease/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/index.html#//apple_ref/doc/constant_group/Audio_Session_Categories
Am happy to say, I found how skype is achieving this feature.
In foreground we can use AVAudioSession with any one category to play ringtone.
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory: AVAudioSessionCategorySoloAmbient error:&error];
[session setActive:YES error:nil];
NSURL * audioFileUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"test1" ofType:#"mp3"]];
AVPlayer *player = [[AVPlayer alloc] initWithURL: audioFileUrl];
[player play];
In background we have to use local notification with custom sound. This will work with hardware mute switch. But here sound file length should not exceed 30 seconds.
UILocalNotification* notification = [[UILocalNotification alloc] init];
[notification #"Title"];
[notification setAlertBody:#"Body"];
[notification setAlertAction:noteAction];
[notification setSoundName:#"ringtone.mp3"];
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
Hope this will be useful :).
Here's a library used to detect mute switch state: http://sharkfood.com/content/Developers/content/Sound%20Switch/.
It is based on Apple's Public APIs. It just plays system sound and measures amount of time used to complete playing. It was used in Instagram iOS app.

iOS: Keep playing music in background with Spotify SDK

I'm using the Spotify iOS SDK and have a question about the background music.
When a user locks the phone or presses the Home button I want my app to continue to play the music. How is this possible?
I've tested
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
Together with adding "Required background modes" to the apps plist.
Does this require that the AVAudioPlayer is used? Since I'm using the Spotify streamingPlayer its not possible.
Background playback should work just fine. You do need the audio item in your UIBackgroundModes Info.plist entry, though. Also, make sure you test on a device - I know remote control events don't work in the iOS Simulator, and that might be the case for background audio as well.
The iOS SDK will automatically set up the AVAudioSession for you, so you don't need to do that.
You might find this answer helpful, which is more in-depth: Background Audio with cocoalibspotify.

AVPlayer not play the next song when screen goes lock

Im using AVPlayer to play song from URLs. I need to play songs continously when user play one song (all songs in the list one after the other) even when the screen doing to lock. But my problem is, when I play a song, after screen is lock current song is playing but the next song is not plays. This is my code.
Appdelegate.m
`
// Registers this class as the delegate of the audio session.
[[AVAudioSession sharedInstance] setDelegate: self];
// Allow the app sound to continue to play when the screen is locked.
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof(doChangeDefaultRoute), &doChangeDefaultRoute);`
also set the info-plist Required background modes to App plays audio
If screen is not lock it plays allsongs one after the other. Only screen lock it plays the currently playing song only. How can I correct this issue.
Please help me,
Thanks

Background Audio in iOS

I'm trying to build an iOS App (iOS > 5.0). It should play music files when a timer, set by the user, ends. Here is my setup what if done so far:
I use avplayer
I've set Background Modes in my plist to "App plays Audio"
in my appDelegate I have:
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&sessionError];
before a song is going to be played a set:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&sessionError];
[[AVAudioSession sharedInstance] setActive:YES error:&sessionError];
i notify my application on "playerItemDidPlayToEnd", stop the player and tell other apps like the music.app to become active again
_avPlayer = nil;
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setActive:NO withFlags:AVAudioSessionSetActiveFlags_NotifyOthersOnDeactivation error:&sessionError];
This works fine. You can have your music app playing in background. My App starts to play a song the music app fades away. My song is played and if its finished the music app continues to play. But only as long as my app isn't in background.
In background I get the error:
Error Domain=NSOSStatusErrorDomain Code=560161140 "The operation couldn\u2019t be completed. (OSStatus error 560161140.)"
Is it possible that both combinations of, playing in background (on custom events) and switching between f.e. music.app and my app in background isn't possible?
Here a the code of my player model: http://pastie.org/4830995
I think your problem might be with background handling. You need to override this function on app delegate.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
__block UIBackgroundTaskIdentifier task = 0;
task=[application beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"Expiration handler called %f",[application backgroundTimeRemaining]);
[application endBackgroundTask:task];
task=UIBackgroundTaskInvalid;
}];
}
your application will get killed after 6 minutes unless sound is played. If your user set timer for more then 6 minutes, what you could do is to play short quite sound every 5.5 minutes to keep you app alive and start new background task. Also you have to consider that lot of thing will not get executed in background. I did some stuff somewhat similar to what you are doing. What I did was created custom subclass of NSObject witch handled music playback and application expiration stuff. And made it a strong property on my delegate as lot of functions and notifications will not run on you VC in the background.
Although if you just want to play a sound this might not be the best approach. Maybe just sending local notification would do.
Hope this helped.
Did you register your app to keep running in the background as an audio app? To do so, add the UIBackgroundModes key to your Info.plist file and set its value to audio.

AVAudioSession - Seems to Think I'm Always Playing Audio

I'm using background audio in my iOS app. When the app launches there is no audio playing, but the status bar shows the play icon & the pause button is shown on the remote control. The app seems to think I'm already playing audio.
viewDidLoad
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
viewWillAppear
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
Any ideas why iOS thinks I'm playing audio? How can I fix this?
I'm receiving the remote events with no problem.
I figured it out... I'm using the Finch iOS audio library & part of its initialization convinces iOS that audio is playing.
FIFactory *soundFactory = [[FIFactory alloc] init];
FISoundEngine *engine = [soundFactory buildSoundEngine];
[engine activateAudioSessionWithCategory:AVAudioSessionCategoryPlayback];
[engine openAudioDevice];
I would like to use Finch & would like to preload my sound effect so it's ready to go. Unfortunately this doesn't appear to be possible without the play icon showing up.

Resources