How to block iOS 7 control centre from controlling music app?
Asked Answered
C

2

0

Our app explicitly blocks user form using remote-control, e.g., old springboard from pre-iOS7, earbud, by becoming the first responder to the remote-control events. However, on iOS7, the same code fails to bypass the control centre music controls.

From out tests, control centre seems to have bypassed ALL music control events including UIEventSubtypeRemoteControlPause and UIEventSubtypeRemoteControlPlay, and UIEventSubtypeRemoteControlTogglePlayPause.

Is it that control centre has its own protocol for remote control or that the way to intercept remote-control events has changed in iOS7?

The same blocking code still works perfectly with iOS6 devices. Here is what we do:

  1. Added a method in our appDelegate:

    (BOOL)canBecomeFirstResponder { return YES; }

  2. Call this in applicationDidBecomeActive:

    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

    // Set itself as the first responder [self becomeFirstResponder];

  3. Call this in applicationWillResignActive

    // Turn off remote control event delivery [[UIApplication sharedApplication] endReceivingRemoteControlEvents];

    // Resign as first responder [self resignFirstResponder];

  4. Finally added

(void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {

    if (receivedEvent.type == UIEventTypeRemoteControl) {
        
        switch (receivedEvent.subtype) {
                
            case UIEventSubtypeRemoteControlTogglePlayPause:
                NSLog(@"Received: UIEventSubtypeRemoteControlTogglePlayPause\n");
                break;
                
            case UIEventSubtypeRemoteControlPreviousTrack:
                NSLog(@"Received: UIEventSubtypeRemoteControlPreviousTrack\n");
                break;
                
            case UIEventSubtypeRemoteControlNextTrack:
                NSLog(@"Received: UIEventSubtypeRemoteControlNextTrack\n");
                break;
                
            case UIEventSubtypeRemoteControlPlay:
                NSLog(@"Received: UIEventSubtypeRemoteControlPlay\n");
                break;

            case UIEventSubtypeRemoteControlPause:
                NSLog(@"Received: UIEventSubtypeRemoteControlPause\n");
                break;

            case UIEventSubtypeRemoteControlStop:
                NSLog(@"Received: UIEventSubtypeRemoteControlStop\n");
                break;
                
            default:
                NSLog(@"Received: Some remove control events\n");
                break;
        }
    }
}

Any pointer will be appreciated.

Cavour answered 30/10, 2013 at 15:16 Comment(1)
Why voting me down? This is a realistic problem.Cavour
S
1

you can't block the music app. your app can become one though (apple won't like that) and then the control center would control yours

Strick answered 30/10, 2013 at 15:20 Comment(6)
@Cavour Remote Control Event handling is so your app can be controlled by Control Center, the earbuds, ets... it is not so that your app can eat said controls, preventing control of other apps from said sources. It only worked in iOS6 because of a bug in iOS, now fixed in iOS7.Sauerbraten
@bbum, thanks for the clarification. Didn't expect that it was a bug since I got the solution on the official xcode mailing list... but what's the solution if launching a music app hijacks my app's audio under all circumstances? I guess this is worth another question.Cavour
Are you using silent audio for backgrounding?Protuberance
@LeoNatan Background audio is not allowed. We use solo-ambient as the audio-session category. So we expect that no other audio can be mixed while our app is foreground.Cavour
@Cavour I was just reading the docs; if you think the new behavior is really a bug, file one via bugreporter.apple.com, certainly!Sauerbraten
@Sauerbraten Thanks bbum. I'm more convinced that this is a bug. Please seem my own answer below.Cavour
C
1

I think I have a better idea of what happened, at least at the CoreAudio level.

When the app's audio session category is solo-ambient, the music app's play event triggers an audio session interruption similar to an alarm clock or a phone call. This will trigger app's audio session interruption listener callback with the "enter-interruption" state.

However, the music app's pause event does not trigger the listener callback with the "exit-interruption" state, as one would expect. This missing exit call effectively freezes our app's audio session. Quitting the control centre does not trigger it either. Same thing applies to a physical remote-control, except that the physical remote-control can be blocked using the firstResponder trick said in my last email. It does not work with Control Centre.

Unless I'm missing something obvious, I am more convinced that there are two bugs in either CoreAudio or other frameworks in the chain of command.

Bug 1: Audio session interruption listener's exit call cannot be made from music remote control if the entrance call is made first there.

Bug 2: Control Centre's music remote control does not conform to remote-control event mechanism.

I'm just surprised that no one ever reported this.

I think I'm going to file a bug report unless someone suggests differently.

UPDATE Bug 2 was a false alarm. After clean rebuilding everything over iOS7 SDK for a couple times, we found that the problem went away. Bug 1 still holds.

Cavour answered 31/10, 2013 at 14:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.