31

我目前正在尝试为我正在为 iOS 4 开发的应用程序设置背景音频。viewController但是,该应用程序没有专用的音乐播放器,这与 Pandora 等其他背景音频应用程序不同,这使得任务更多令人困惑。

我已经Info.plist正确设置了适当的设置,并且AVAudioPlayer在我的应用程序委托中有一个可以从任何地方访问的对象。当用户播放歌曲时,我用AVAudioPlayer歌曲初始化的新歌曲替换并播放。这一切都很好,除了现在我不知道如何支持远程控制事件。

根据Apple的文档,我有这个:

- (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;
    }
}

问题是,我把这个放在哪里?Apple 的文档似乎建议这应该放在某个视图控制器中,但我的应用程序有很多视图控制器和导航控制器。无论我试图把它放在哪里,出于某种原因,点击多任务托盘遥控器中的切换播放/暂停按钮要么导致歌曲暂停片刻然后取消暂停,要么以某种方式导致歌曲播放两次。

4

7 回答 7

37

文档示例有点误导,但没有必要在任何地方子类化任何东西。放置 remoteControlReceivedWithEvent: 的正确位置是在应用程序委托中,因为无论应用程序是否在前台,它都保留在响应者链中。此外,开始/结束接收远程控制事件应该基于您是否真的需要这些事件,而不是基于某些随机视图的可见性。

于 2012-01-14T23:09:27.800 回答
19

经过一番搜索,我在 Apple Developer Forums 上找到了一些接收全局远程控制事件的解决方案。

一种方法是继承UIWindow并覆盖它的remoteControlReceivedWithEvent:.

第二种可能更好的方法是子类化UIApplication和覆盖sendEvent:。这样,您可以拦截所有远程控制事件并在那里全局处理它们,而不需要任何其他响应者稍后在响应者链中处理它们。

- (void)sendEvent:(UIEvent *)event {
     if (event.type == UIEventTypeRemoteControl) {
          // Handle event
     }
     else
          [super sendEvent:event];
}
于 2010-08-11T17:51:40.050 回答
4

第二种方法对我不起作用,sendEvent从未被调用过。然而,第一种方法工作得很好(子类化UIWindow)。

于 2010-12-19T09:59:22.653 回答
3

我在这个问题上挣扎了一段时间,上面的答案都没有奏效。我的代码中的错误,我希望它能帮助阅读本文的人,是我将 AudioSession 设置为与其他人混合。您想成为获取远程控制事件的前台音频播放器。检查您是否有这样的错误代码:

    [[AVAudioSession sharedInstance] setDelegate: self];
    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
    UInt32 doSetProperty = 0;
    AudioSessionSetProperty (
                             kAudioSessionProperty_OverrideCategoryMixWithOthers,
                             sizeof (doSetProperty),
                             &doSetProperty
                             );
    NSError *activationError = nil;
    [[AVAudioSession sharedInstance] setActive: YES error: &activationError];       

并删除 AudioSessionSetProperty,或将 doSetProperty 更改为 1。

于 2012-05-29T20:33:28.437 回答
0

无需子类化 Window 或转发事件。只需从您的主视图控制器处理它。有关详细信息,请参阅混音器 (MixerHost) 示例。

http://developer.apple.com/LIBRARY/IOS/#samplecode/MixerHost/Listings/Classes_MixerHostViewController_m.html

于 2011-07-27T02:19:37.120 回答
0

似乎会影响此行为的一件事是您使用 setCategory:withOptions:error: 为 AVAudioSession 设置的任何类别选项,而不仅仅是 setCategory:error:。特别是,从反复试验来看,如果您设置 AVAudioSessionCategoryOptionMixWithOthers ,您将不会获得远程控制事件;正在播放的控件仍将控制 iPod 应用程序。如果您设置 AVAudioSessionCategoryOptionDuckOthers 您将获得远程控制事件,但似乎对于控制哪个应用程序可能存在一些歧义。将 categoryOptions 设置为 0 或只调用 setCategory:error: 效果最好。

于 2014-09-21T22:37:48.693 回答