Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of beginReceivingRemoteControlEvents

I saw people use: [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; to handle remote control event when managing audio session.

My question:

Does this code only can be used in either a UIViewController class or AppDelegate class? Because I see everyone in Internet using it in one of the two classes. Can I use it in a class which is not subclass of UIViewController or AppDelegate?

like image 698
Leem.fin Avatar asked Aug 04 '16 20:08

Leem.fin


2 Answers

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; can be used at any point in your application, such as right before starting audio playback, or on launch in application:didFinishLaunchingWithOptions: delegate method.

For applications that want to use the controls for background audio playback throughout the entire application lifecycle (and backgrounded), I would recommend calling beginReceivingRemoteControlEvents in your AppDelegate. That way, you're explicitly ready to receive remote control events at any time during the application lifecycle.

Palpatim mentioned MPRemoteCommandCenter. As someone who has built a complete application around background audio playback (think radio), I would highly recommend this method over the old UIEvent callbacks. I dive into this approach in another answer, but the gist is use MPRemoteCommandCenter.sharedCommandCenter() to enable or disable playback controls on the lock screen and control center, as well as provide selectors:

let commandCenter = MPRemoteCommandCenter.sharedCommandCenter()

commandCenter.previousTrackCommand.enabled = true;
commandCenter.previousTrackCommand.addTarget(self, action: #selector(previousTrack))

commandCenter.nextTrackCommand.enabled = false
commandCenter.nextTrackCommand.addTarget(self, action: #selector(nextTrack))

Note that if you explicitly want to disable controls, you must provide a [dummy] selector for the action in addition to setting enabled = false on the command.

To address your point about becomeFirstResponder:

Any object that inherits from UIResponder, such as a UIViewController or the UIApplicationDelegate can become the first responder, as long as that object implements the required method remoteControlReceivedWithEvent: to handle the remote control events. For example, I could have the AppDelegate become the first responder and handle all remote control events in there, and send out notifications that a UIViewController listens to to pause the player or skip to the next track. You could have a UIViewController become the first responder (the controller holding a reference to the player) and control the player directly. The architecture is pretty open and it really depends on how you structured your application. You haven't provided any code, so I don't know what your player setup looks like.

Your UIResponder handling code will probably look something like this:

- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
    if (event.type == UIEventTypeRemoteControl) {
        switch (event.subtype) {
            case UIEventSubtypeRemoteControlTogglePlayPause:
                // Pause or play action
                break;
            case UIEventSubtypeRemoteControlNextTrack:
                // Next track action
                break;
            case UIEventSubtypeRemoteControlPreviousTrack:
                // Previous track action
                break;
            case UIEventSubtypeRemoteControlStop:
                // Stop action
                break;
            default:
                // catch all action
                break;
        }
    }
}

Again, whether you place this in a controller or in your AppDelegate is up to you.

Can I use it in a class which is not subclass of UIViewController or AppDelegate?

Yes, you implement this in any class that inherits from UIResponder. People normally use the AppDelegate or a view controller for convenience.

like image 150
JAL Avatar answered Nov 15 '22 07:11

JAL


For apps that only want to handle remote control events while in a certain state--ready to play media, for example, as opposed to being on the settings or registration screen--invoking beginReceivingRemoteControlEvents from a view controller makes a certain amount of sense. Other apps may wish to suppress remote control behavior altogether (because they take over the audio session and don't want background audio being triggered by the user and corrupting session data).

However, there's nothing that prevents you from factoring that behavior into another area of the app, especially if it is shared. beginReceivingRemoteControlEvents is a method on UIApplication, so as long as you're able to get a handle to [UIApplication sharedApplication], you can flag the app to begin/end remote control event handling.

However, it's worth noting that method is deprecated:

In iOS 7.1 and later, use the shared MPRemoteCommandCenter object to register for remote control events. You do not need to call this method when using the shared command center object. [1]

My experience with remote control event handling is a couple of years old at this point, but I recall there was some non-intuitive behavior dealing with beginReceivingRemoteControlEvents. A quick glance at MPRemoteCommandCenter makes this look like a better API for handling remote control events. If your use cases don't require iOS 7.0 support, you should investigate that API.

like image 36
Palpatim Avatar answered Nov 15 '22 07:11

Palpatim