In iOS 7, after my audio interruption listener gets called, any attempt to restore the audio session seems to fail silently.
My interruption listener calls
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive:YES error:&activationError];
But the app's audio session is dead as soon as the alarm clock rings. The listener gets called with appropriate begin and end states.
It worked just fine on iOS 6.
I have heard that this is a bug in iOS 7 and that there is a workaround, but can't find it.
Does anyone know a link to a workaround or Technical Note from Apple?
EDIT: I found that I HAVE to use AVAudioSessionCategoryPlayback
instead of kAudioSessionCategory_AmbientSound
. Now it works. But it is not the category I wanted.
Based on Apple's Audio session programming guide, you should listen and react to changes in your interruption handler. This means that your code can/should handle the end of the interruptions too, based on the received parameter interruptionState.
Check out "Audio Interruption Handling Techniques" on this link, I think it will help you a lot: https://developer.apple.com/library/ios/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/HandlingAudioInterruptions/HandlingAudioInterruptions.html
Good luck, Z.
You can see my code below. But First,
You should select this bit target | Background Modes | Audio, Airplay and Picture in Picture from Capabilities.
// ViewController.m
// AVAudioPlayer
#import "ViewController.h"
@import AVFoundation;
@import MediaPlayer;
@interface ViewController ()
@property (strong, nonatomic) AVAudioPlayer *audioPlayer;
@property (weak, nonatomic) IBOutlet UISlider *volumeSlider;
@property (weak, nonatomic) IBOutlet UISlider *rateSlider;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self setupAudio];
}
- (void) setupAudio {
NSError *error;
[[AVAudioSession sharedInstance] setActive:YES error:&error];
if (error != nil) {
NSAssert(error == nil, @"");
}
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
if (error != nil) {
NSAssert(error == nil, @"");
}
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:@"SoManyTimes" withExtension:@"mp3"];
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:&error];
if (error != nil) {
NSAssert(error == nil, @"");
}
//[self.audioPlayer setVolume:0.8];
self.audioPlayer.enableRate = YES;
[self.audioPlayer prepareToPlay];
[self.audioPlayer setVolume:self.volumeSlider.value];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioInterrupt:) name:AVAudioSessionInterruptionNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChanged:) name:AVAudioSessionRouteChangeNotification object:nil];
MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
[commandCenter.playCommand addTarget:self action:@selector(playButtonPressed:)];
[commandCenter.stopCommand addTarget:self action:@selector(stopButtonPressed:)];
[commandCenter.pauseCommand addTarget:self action:@selector(stopButtonPressed:)];
}
- (void) audioRouteChanged:(NSNotification*)notification {
NSNumber *reason = (NSNumber*)[notification.userInfo valueForKey:AVAudioSessionRouteChangeReasonKey];
switch ([reason integerValue]) {
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory:
[self stopButtonPressed:nil];
break;
default:
break;
}
}
- (void) audioInterrupt:(NSNotification*)notification {
NSNumber *interruptionType = (NSNumber*)[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey];
switch ([interruptionType integerValue]) {
case AVAudioSessionInterruptionTypeBegan:
[self stopButtonPressed:nil];
break;
case AVAudioSessionInterruptionTypeEnded:
{
if ([(NSNumber*)[notification.userInfo valueForKey:AVAudioSessionInterruptionOptionKey] intValue] == AVAudioSessionInterruptionOptionShouldResume) {
[self playButtonPressed:nil];
}
break;
}
default:
break;
}
}
- (IBAction)playButtonPressed:(id)sender {
BOOL played = [self.audioPlayer play];
if (!played) {
NSLog(@"Error");
}
MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:@"CoverArt"]];
NSDictionary *songInfo = @{
MPMediaItemPropertyTitle:@"So Many Times",
MPMediaItemPropertyArtist:@"The Jellybricks",
MPMediaItemPropertyAlbumTitle:@"Soap Opera",
MPMediaItemPropertyArtwork:albumArt,
MPMediaItemPropertyPlaybackDuration:@(self.audioPlayer.duration),
MPNowPlayingInfoPropertyElapsedPlaybackTime:@(self.audioPlayer.currentTime),
};
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
}
- (IBAction)stopButtonPressed:(id)sender {
[self.audioPlayer stop];
}
- (IBAction)volumeSliderChanged:(UISlider*)sender {
[self.audioPlayer setVolume:sender.value];
}
- (IBAction)rateSliderChanged:(UISlider*)sender {
[self.audioPlayer setRate:sender.value];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With