iosobjective-cavplayeravaudiosession

Using Remote Control with AVPlayer in iOS 7 & 8


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.

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

Solution

  • 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.