首页 文章

iOS 4:背景音频的遥控器

提问于
浏览
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的文档似乎暗示这应该放在某个视图控制器的某个地方,但我的应用程序有很多视图控制器和导航控制器 . 无论我试图把它放在哪里,出于某种原因,在多任务托盘遥控器中点击切换播放/暂停按钮会导致歌曲暂停片刻然后取消暂停,或以某种方式使歌曲播放两次 .

7 回答

  • 4

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

  • 3

    经过一些搜索后,我找到了几个在Apple Developer论坛上接收全局远程控制事件的解决方案 .

    一种方法是子类 UIWindow 并覆盖其 remoteControlReceivedWithEvent: .

    第二种,也许更好的方法是子类 UIApplication 并覆盖 sendEvent: . 这样,您可以拦截所有远程控制事件并在全局处理它们,并且以后没有任何其他响应程序在响应程序链中处理它们 .

    - (void)sendEvent:(UIEvent *)event {
         if (event.type == UIEventTypeRemoteControl) {
              // Handle event
         }
         else
              [super sendEvent:event];
    }
    
  • 37

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

  • 0

    我挣扎了一段时间,上面的答案都没有奏效 . 我的代码中的错误,我希望它能帮助读取此内容的人,是因为我将AudioSession设置为与其他人混合 . 您希望成为获得远程控制事件的前台音频播放器 . 检查你是否有这样的INCORRECT代码:

    [[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 .

  • 0

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

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

  • 0

    似乎影响此行为的一件事是您使用setCategory为AVAudioSession设置的任何类别选项:withOptions:error:而不仅仅是setCategory:error: . 特别是,从试验和错误看,如果您设置AVAudioSessionCategoryOptionMixWithOthers,您将无法获得远程控制事件;现在播放的控件仍将控制iPod应用程序 . 如果您设置了AVAudioSessionCategoryOptionDuckOthers,您将获得远程控制事件,但似乎可能存在一些关于控制哪个应用程序的模糊性 . 将categoryOptions设置为0或只调用setCategory:error:效果最好 .

相关问题