I am trying to write a simple personal radio app, and had an annoying problem.
I try to play a .pls (stream) file from a remote server with AVPlayer and I successfully managed to make it work. I can now play the stream but as I mentioned in the title, I can not remotely control the play/pause option when the app is in background.
I searched a lot on Internet about that topic and found two solutions.
1- As in Apple's Remote Control Events Documentation, using "MPRemoteCommandCenter" class to handle this, but for this solution I cannot find any good explanation that how am I going to use AVPlayer with it. This brings me to the second solution since I have no idea how to use MPRemoteCommandCenter class.
2- As almost all people mentioned about remoteControlReceivedWithEvent: method. However when I try to use that approach I cannot get a respond. My remoteControlReceivedWithEvent: method is never been called. Here is my code's that how I implemented the behavior:
I have two classes, one called EGPlayRadio.m which contains the AVPlayer and AVAudioSession stuff, the other one is the EGMainMenuViewController.m which displays a play button and pause button to stream the radio.
I payed attention to first call [AVSession sharedInstance] before calling [[UIApplication sharedApplication] beginReceivingRemoteControlEvents] method.
Also I payed attention on that Giving the app background audio playing permission from build settings of the project.
However, after searching a lot on Internet I can not find a suitable solution for my problem. Here are my two classes that I implemented:
EGPlayRadio.m
#import "EGPlayRadio.h"
#import <MediaPlayer/MediaPlayer.h>
#import <AVFoundation/AVFoundation.h>
@interface EGPlayRadio () <AVAudioPlayerDelegate>
@property (nonatomic, strong) AVAudioSession *audioSession;
@property (nonatomic, strong) AVPlayer *player;
@end
@implementation EGPlayRadio
- (id)initDefault
{
self = [super init];
if (self)
{
_audioSession = [AVAudioSession sharedInstance];
[_audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
NSURL *url = [[NSURL alloc] initWithString:@"http://LINK-OF-THE-PLS-FILE"];
_player = [[AVPlayer alloc] initWithURL:url];
}
return self;
}
- (void)playRadio
{
[self.player play];
}
- (void)pauseRadio
{
[self.player pause];
}
EGMainMenuViewController.m
@interface EGRMainMenuViewController ()
@property (nonatomic, strong) IBOutlet UIButton *playButton;
@property (nonatomic, strong) IBOutlet UIButton *pauseButton;
@property (nonatomic, strong) EGPlayRadio *radioControl;
@end
@implementation EGRMainMenuViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.radioControl = [[EGPlayRadio alloc] initDefault];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
self.pauseButton.enabled = NO;
self.pauseButton.alpha = 0.3f;
}
- (BOOL)canBecomeFirstResponder
{
return YES;
}
- (IBAction)musicInteracted:(id)sender
{
if (sender == self.playButton)
{
self.pauseButton.enabled = YES;
self.pauseButton.alpha = 1.0f;
self.playButton.enabled = NO;
self.playButton.alpha = 0.3f;
[self.radioControl playRadio];
}
else
{
self.pauseButton.enabled = NO;
self.pauseButton.alpha = 0.3f;
self.playButton.enabled = YES;
self.playButton.alpha = 1.0f;
[self.radioControl pauseRadio];
}
}
-(void)remoteControlReceivedWithEvent:(UIEvent *)event
{
switch (event.subtype) {
case UIEventSubtypeRemoteControlTogglePlayPause:
//[streamer pause];
break;
case UIEventSubtypeRemoteControlPlay:
//[streamer start];
break;
case UIEventSubtypeRemoteControlPause:
//[streamer pause];
break;
case UIEventSubtypeRemoteControlStop:
//[streamer stop];
break;
default:
break;
}
}
@end
For others having the same issue, I solved my problem by following:
In EGPlayRadio.m class, I allocated AVAudioSession by using
[_audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
Insted of it we have to use:
[_audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
That is the problem for me, after changing this, I can successfully receive the remote notifications.