4
votes

So the idea is - when we play audio in Music app in iPhone and press home button then swipe from bottom of the screen, we can see the audio playing in default OS player with play/pause controls and audio continue play.

Now what i need to do, i play an audio by using AVAudioPlayer in my app and if user press home button, the audio need to play continue as in case of music app. But i have no idea how to add audio in OS default player? Any help or suggestion would be highly appreciated.

Edit: I need to play audio using streaming so i guess i need to use AVPlayer instead of AVAudioPlayer

2

2 Answers

3
votes

You could use an MPMovieplayerController since you'll be more than likely be using an M3U8 playlist.

Here's the documentation http://developer.apple.com/library/ios/documentation/MediaPlayer/Reference/mpmovieplayercontroller_class/index.html

But it basically goes like this:

Initialize the MPMoviePlayerController, assign a file type (stream), put the source url, and present it in the view stack.

For the background audio, you'd have to use AudioSession like in this answer iOS MPMoviePlayerController playing audio in background

1
votes

You can do this as a background audio task so that the audio keeps playing even after the user presses the home button and your app goes into the background. First you create an AVAudioSession. Then you set up an array of AVPlayerObjects and a AVQueuePlayer in your viewDidLoad method. There's a great tutorial by Ray Wenderlich that discusses all of this in detail http://www.raywenderlich.com/29948/backgrounding-for-ios. You can set up a callback method (observer method) so that the app is sent additional audio data as it streams in - (void)observeValueForKeyPath.

Here's how the code looks (from Ray Wenderlich's tutorial):

in viewDidLoad:

// Set AVAudioSession
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance]     setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];

// Change the default output audio route
UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
  sizeof(doChangeDefaultRoute), &doChangeDefaultRoute);

NSArray *queue = @[
[AVPlayerItem playerItemWithURL:[[NSBundle mainBundle]  URLForResource:@"IronBacon" withExtension:@"mp3"]],
[AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"FeelinGood" withExtension:@"mp3"]],
[AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"WhatYouWant" withExtension:@"mp3"]]];

self.player = [[AVQueuePlayer alloc] initWithItems:queue];
self.player.actionAtItemEnd = AVPlayerActionAtItemEndAdvance;

[self.player addObserver:self
              forKeyPath:@"currentItem"
                 options:NSKeyValueObservingOptionNew
                 context:nil];

in a callback method:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"currentItem"])
    {
        AVPlayerItem *item = ((AVPlayer *)object).currentItem;
        self.lblMusicName.text = ((AVURLAsset*)item.asset).URL.pathComponents.lastObject;
        NSLog(@"New music name: %@", self.lblMusicName.text);
    }
}

Don't forget to add the member variables in your view controller's private API in the implementation file:

@interface TBFirstViewController ()

@property (nonatomic, strong) AVQueuePlayer *player;
@property (nonatomic, strong) id timeObserver; 
@end