Can't beginReceivingRemoteControlEvents in iOS

12,198

Solution 1

I have done the same work in my project, it's working fine. Please follow this, perhaps it will help you. Change the event name etc. In my code _audio is the object of AVAudioPlayer.

- (void)viewDidLoad {
    NSError *setCategoryErr = nil;
    NSError *activationErr  = nil;
    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &setCategoryErr];
    [[AVAudioSession sharedInstance] setActive: YES error: &activationErr];
}

- (void)viewWillAppear {

      [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    [self becomeFirstResponder];
}


- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
    switch (event.subtype) {
        case UIEventSubtypeRemoteControlPlay:
            [_audio play];
            break;
        case UIEventSubtypeRemoteControlPause:
            [_audio pause];
            break;
        default:
            break;
    }
}

Solution 2

There is a newer mechanism for listening to remote control events. For example, to execute a block when the headphone play/pause button is pressed:

    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];

    [commandCenter.togglePlayPauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        NSLog(@"toggle button pressed");
        return MPRemoteCommandHandlerStatusSuccess;
    }];

or, if you prefer to use a method instead of a block:

    [commandCenter.togglePlayPauseCommand addTarget:self action:@selector(toggleButtonAction)];

To stop:

    [commandCenter.togglePlayPauseCommand removeTarget:self];

or:

    [commandCenter.togglePlayPauseCommand removeTarget:self action:@selector(toggleButtonAction)];

You'll need to add this to the includes area of your file:

@import MediaPlayer;

For it to work in the background, you must have the background audio mode added to your app's capabilities.

Solution 3

Review this sample code from Apple for an example of usage. Likely your primary view controller is not actually becoming the first responder. An alternative usage is to place this code in your Application Delegate (which will always be the first responder) and respond to these events before they have had a chance to propagate, and potentially be consumed by other responders.

Share:
12,198

Related videos on Youtube

Nikita Pestrov
Author by

Nikita Pestrov

Skoltech student, MIPT graduate, Data Scientist CocoaHeads Moscow founder iOS developer easy ten - my educational iPhone app

Updated on June 04, 2022

Comments

  • Nikita Pestrov
    Nikita Pestrov almost 2 years

    In my app i want let user to control audio playback in background. I set backGround modes in .plist, and in plays in bg just like i wanted.But i can't get any response from touching the control buttons.

    I set the AudioSession like this

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    [[AVAudioSession sharedInstance]setActive:YES error:nil];
    

    Then, in viewContoller where my player is placed i beginReceivingRemoteControlEvents like this

     if ([[UIApplication sharedApplication] respondsToSelector:@selector(beginReceivingRemoteControlEvents)]){
        [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
        [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
        [self becomeFirstResponder];
        NSLog(@"Responds!");
    }
    

    And it prints Responds!

    But the problem is that this method is never called

        - (void)remoteControlReceivedWithEvent:(UIEvent *)event
    {
        NSLog(@"Where is my event?");
        if(event.type == UIEventTypeRemoteControl)
        {
            switch (event.subtype) {
                case UIEventSubtypeRemoteControlTogglePlayPause:
                    NSLog(@"Pause");
                    [self playWords:playButton];
                    break;
                case UIEventSubtypeRemoteControlNextTrack:
                    NSLog(@"Next");
                    [self next];
                    break;
                case UIEventSubtypeRemoteControlPreviousTrack:
                    NSLog(@"Prev");
                    [self prev];
                    break;
    
            }
        }
    

    I even tried to write a category on UIApplication to let it become the first responder, but it doesn't help

    @implementation UIApplication (RemoteEvents)
    -(BOOL)canBecomeFirstResponder
    {
        return YES;
    }
    @end
    

    Why can this happen?

    SOLUTION Here's what solved my problem Entering background on iOS4 to play audio

  • Nikita Pestrov
    Nikita Pestrov about 12 years
    Thank you,but as far as i can see,it is just the same
  • Khalid Usman
    Khalid Usman about 12 years
    Another thing is that you can't test it on simulator , use device if you are using simulator to test remove events and backgroung music.
  • arsenius
    arsenius about 11 years
    This worked for me once I added -(BOOL)canBecomeFirstResponder{return YES;}. Thanks!
  • Khalid Usman
    Khalid Usman almost 11 years
    Dear @openfrog , if you know how it work in ios 6+ then you should either change it or make a new answer with tag "IOS 6+" rather than down voting this,because there are still people on the world who use ios 5 and 4.