Skip to content

Instantly share code, notes, and snippets.

@nevyn
Created March 27, 2013 15:49
Show Gist options
  • Save nevyn/5255286 to your computer and use it in GitHub Desktop.
Save nevyn/5255286 to your computer and use it in GitHub Desktop.
Example of an imo correct way to handle audio sessions in iOS apps with streaming music that will sometimes have pauses between audio playback.
@interface SPAudioSessionManager ()
{
__weak PlayController *_playController;
BOOL _audioSessionIsConfiguredForPlayback;
UIBackgroundTaskIdentifier _playbackBackgroundTask;
}
@end
@interface PlayController : NSObject
@property BOOL playing;
@end
@implementation SPAudioSessionManager
- (id)initWithPlayController:(PlayController*)playController
{
if(!(self = [super init]))
return nil;
_playController = playController;
// Register to know whenever the user semantically wants to start or stop playback.
[_playController addObserver:self forKeyPath:@"playing" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionPrior context:NULL];
return self;
}
- (void)dealloc
{
[_playController removeObserver:self forKeyPath:@"playing"];
}
typedef enum { NoExtraKnowledge, WillPlay } AudioSessionStateMatchingOptions;
- (void)playingChanged:(NSDictionary*)change
{
BOOL isPrior = [change[NSKeyValueChangeNotificationIsPriorKey] boolValue];
// We're just guessing here that a prior change while paused means we will start playing. It is almost always true.
// Even if it's not, it will just start a redundant audio session that will be torn down during the Did callback
if (isPrior && !_playController.playing) {
[self matchAudioSessionWithPlayState:WillPlay];
} else if(!isPrior) {
[self matchAudioSessionWithPlayState:NoExtraKnowledge];
}
}
-(void)matchAudioSessionWithPlayState:(AudioSessionStateMatchingOptions)options;
{
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *err = nil;
BOOL playing = _playController.playing || options == WillPlay;
if(playing && !_audioSessionIsConfiguredForPlayback) {
// Going from a paused state to a playing state
_audioSessionIsConfiguredForPlayback = YES;
if(![session setCategory:AVAudioSessionCategoryPlayback error: &err])
NSLog(@"Failed to set audio category: %@", err);
if(![session setActive:YES error:&err])
NSLog(@"Failed to activate audio session: %@", err);
NSAssert(_playbackBackgroundTask == UIBackgroundTaskInvalid, @"SPAudioSessionManager background task already running!");
_playbackBackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^ {
NSLog(@"WARNING: Still playing music but background task expired!!");
[[UIApplication sharedApplication] endBackgroundTask:_playbackBackgroundTask];
_playbackBackgroundTask = UIBackgroundTaskInvalid;
}];
} else if(!playing && _audioSessionIsConfiguredForPlayback) {
// Going from a playing state to a paused state
_audioSessionIsConfiguredForPlayback = NO;
if(![session setActive:NO error:&err])
NSLog(@"Failed to deactivate audio session: %@", err);
if(_playbackBackgroundTask != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:_playbackBackgroundTask];
_playbackBackgroundTask = UIBackgroundTaskInvalid;
}
}
}
@end
@ankitbukshete108
Copy link

I want music player who streams for 10sec and then play....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment