I'm currently attempting to set up background audio for an app I'm developing for iOS 4. The app doesn't have a dedicated music player viewController
, however, unlike other background audio apps such as Pandora, which makes the task a bit more confusing.
I've set the appropriate Info.plist
settings correctly and have an AVAudioPlayer
object in my app delegate which is accessible from everywhere. When the user plays a song, I replace the AVAudioPlayer
with a new one initialized with the song and play it. This all works great, except now I have no idea how to go about supporting remote control events.
Based on Apple's documentation, I have this:
- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; [self becomeFirstResponder]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[UIApplication sharedApplication] endReceivingRemoteControlEvents]; [self resignFirstResponder]; } - (BOOL)canBecomeFirstResponder { return YES; } - (void)remoteControlReceivedWithEvent:(UIEvent *)event { switch(event.subtype) { case UIEventSubtypeRemoteControlTogglePlayPause: if([iPhoneAppDelegate backgroundAudioPlayer].playing) [iPhoneAppDelegate pauseBackgroundAudioPlayer]; else [iPhoneAppDelegate playBackgroundAudioPlayer]; break; } }
The thing is, where do I put this? Apple's documentation seems to suggest this should go in some view controller somewhere, but my app has lots of view controllers and navigation controllers. Wherever I try to put this, for some reason tapping the Toggle Play/Pause button in the multitasking tray remote controls either causes the song to just pause for a moment and then unpause, or somehow causes the song to play twice.
When you're on the phone or listening to songs, movies, or other media on iPhone, you can use the buttons on the side of your device to adjust the audio volume. Otherwise, the buttons control the volume for the ringer, alerts, and other sound effects. You can also use Siri to turn the volume up or down.
Certain apps can use your iPhone's microphone to learn what you watch, listening in the background for audio signals playing from gaming consoles, TV shows, streaming programs, and advertisements.
The documentation examples are a bit misleading, but there is no need to subclass anything anywhere. The correct place to put remoteControlReceivedWithEvent: is in the application delegate, as it remains in the responder chain regardless of whether the app is in the foreground or not. Also the begin/end receiving remote control events should be based on whether you actually need the events, not on the visibility of some random view.
I found a couple of solutions to receiving global remote control events on the Apple Developer Forums after a bit of searching.
One way is to subclass UIWindow
and override its remoteControlReceivedWithEvent:
.
The second, perhaps nicer way is to subclass UIApplication
and override sendEvent:
. That way, you can intercept all the remote control events and handle them there globally, and not have any other responders handle them later in the responder chain.
- (void)sendEvent:(UIEvent *)event { if (event.type == UIEventTypeRemoteControl) { // Handle event } else [super sendEvent:event]; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With