Search code examples
iosobjective-ciphoneios11

iOS control center music controls stop working in iOS 11 update (remoteControlReceivedWithEvent is not called iOS 11)


I’m having an issue with iOS control center music controls Before the iOS 11 update, the Play Pause button was enabled and worked normally, as is expected.

However, in iOS 11 it stopped working. After a research, I found that in IOS 11 the remoteControlReceivedWithEvent is never being called, but, in older iOS versions such as iOS 9 it is being called normally

I set my events on AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // Enable background audio listening
    // https://developer.apple.com/library/ios/qa/qa1668/_index.html
    NSError *error = nil;
    if (![[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error]) {
        NSLog(@"%@", error);
    }
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}


- (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {
    if (receivedEvent.type == UIEventTypeRemoteControl) {
        switch (receivedEvent.subtype) {
            case UIEventSubtypeRemoteControlPlay:
                [[NSNotificationCenter defaultCenter] postNotificationName:kCYCAppDelegatePlayPauseNotificationName object:nil];
                break;
            case UIEventSubtypeRemoteControlPause:
                [[NSNotificationCenter defaultCenter] postNotificationName:kCYCAppDelegatePlayPauseNotificationName object:nil];
                break;
            case UIEventSubtypeRemoteControlTogglePlayPause:
                [[NSNotificationCenter defaultCenter] postNotificationName:kCYCAppDelegatePlayPauseNotificationName object:nil];
                break;
            default:
                break;
        }
    }
}

also I subscribe to remote events in another class to control play/pause buttons

- (void)subscribeToRemoteControlEvents {

    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.1")) {
        // Disables the forward/backward buttons and only shows the play button.
        // You can't just enable the command, you must subscribe for this to activate, so
        // the subscription in this case doesn't do anything.
        [MPRemoteCommandCenter sharedCommandCenter].togglePlayPauseCommand.enabled = YES;
        [[MPRemoteCommandCenter sharedCommandCenter].togglePlayPauseCommand addTarget:self action:@selector(ignore_removeCommandCenterFired)];
    }

    [[NSNotificationCenter defaultCenter] addObserver:self forName:kCYCAppDelegatePlayPauseNotificationName object:nil queue:nil usingBlock:^(NSNotification *note, CYCCastManager *observer) {
        if (observer.isCastPlaying) {
            [observer pause];
        }
        else {
            [observer play:NO];
        }
    }];
}

- (void)unsubscribeFromRemoteControlEvents {
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.1")) {
        [[MPRemoteCommandCenter sharedCommandCenter].togglePlayPauseCommand removeTarget:self action:@selector(ignore_removeCommandCenterFired)];
    }
}

I want known why is not working anymore I did check in documentation for changes in the API, but I don't see changes

Note: I check the following links with no luck

iOS - UIEventTypeRemoteControl events not received

https://forums.developer.apple.com/thread/84204

Unable to receive remoteControlReceivedWithEvent - objective c - ios

remoteControlReceivedWithEvent in AVAudio is not being called

remoteControlReceivedWithEvent not Called in appDelegate


Solution

  • Finally I fix the issue by using remoteCommandCenter and play and pause buttons instead of tooglePlayPauseCommand

    if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.0")){
        //NOTE: this is the only way that I find to make this work on IOS 11 its seems to be that togglePlayPauseCommand is not working anymore
        MPRemoteCommandCenter* commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
        [commandCenter.playCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
            [[NSNotificationCenter defaultCenter] postNotificationName:kCYCAppDelegatePlayNotificationName object:nil];
            return MPRemoteCommandHandlerStatusSuccess;
        }];
    
        [commandCenter.pauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
            [[NSNotificationCenter defaultCenter] postNotificationName:kCYCAppDelegatePauseNotificationName object:nil];
            return MPRemoteCommandHandlerStatusSuccess;
        }];
    
        [[NSNotificationCenter defaultCenter] addObserver:self forName:kCYCAppDelegatePlayNotificationName object:nil queue:nil usingBlock:^(NSNotification *note, CYCCastManager *observer) {
            if (!observer.isCastPlaying) {
                [observer play:NO];
            }
        }];
    
        [[NSNotificationCenter defaultCenter] addObserver:self forName:kCYCAppDelegatePauseNotificationName object:nil queue:nil usingBlock:^(NSNotification *note, CYCCastManager *observer) {
            if (observer.isCastPlaying) {
                [observer pause];
            }
        }];
    
    
    }