代码之家  ›  专栏  ›  技术社区  ›  Anshu Chimala

iOS 4:背景音频遥控器

  •  31
  • Anshu Chimala  · 技术社区  · 15 年前

    我正在尝试为我正在为iOS 4开发的应用程序设置背景音频。应用程序没有专用的音乐播放器 viewController 但是,与其他后台音频应用程序(如Pandora)不同,Pandora会让任务更加混乱。

    我已经安排好了 Info.plist 正确设置并具有 AVAudioPlayer 我的应用程序代理中的对象,可从任何地方访问。当用户播放歌曲时,我将替换 音频播放器 用一首新的歌来初始化并播放它。这一切都很好,除了现在我不知道如何去支持远程控制事件。

    根据苹果的文档,我有:

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

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

    7 回复  |  直到 11 年前
        1
  •  37
  •   Brian Dam Pedersen    14 年前

    文档示例有点误导性,但不需要在任何地方对任何内容进行子类化。将RemoteControlReceivedWithEvent:放置在应用程序委托中的正确位置,因为不管应用程序是否在前台,它都将保留在响应程序链中。另外,接收远程控制事件的开始/结束应该基于您是否实际需要这些事件,而不是基于某些随机视图的可见性。

        2
  •  19
  •   Anshu Chimala    15 年前

    经过一番搜索,我在苹果开发者论坛上找到了一些接收全球远程控制事件的解决方案。

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

    第二种可能更好的方法是子类 UIApplication 超驰 sendEvent: . 这样,您就可以截获所有的远程控制事件,并在全局范围内处理它们,而在响应程序链的后面,没有任何其他响应程序处理它们。

    - (void)sendEvent:(UIEvent *)event {
         if (event.type == UIEventTypeRemoteControl) {
              // Handle event
         }
         else
              [super sendEvent:event];
    }
    
        3
  •  4
  •   Stelian Iancu    15 年前

    第二种方法不适合我, sendEvent 从未打过电话。但是第一个方法工作得很好(子类化 UIWindow )

        4
  •  3
  •   Sherwin Zadeh    14 年前

    我为此挣扎了一段时间,上面的答案都不管用。我的代码中的bug,我希望它能帮助阅读本文的人,是我将音频会话设置为与其他人混合。您希望成为前台音频播放器以获取远程控制事件。检查代码是否不正确,如下所示:

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

        5
  •  0
  •   slf    15 年前

    无需子类化窗口或转发事件。只需从主视图控制器处理即可。有关详细信息,请参见音频混音器(MixerPost)示例。

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

        7
  •  0
  •   Jimmy Dee    11 年前

    似乎影响此行为的一件事是使用setCategory:WithOptions:Error:而不仅仅是setCategory:Error:为您的AvaudioSession设置的任何类别选项。特别是,从试用版和错误版来看,如果您设置了AvaudioSessionCategoryOption与其他人混合,您将无法获得远程控制事件;现在播放的控件仍将控制iPod应用程序。如果将AvaudioSessionCategoryOptionDuckOthers设置为“其他”,您将获得远程控制事件,但似乎对控制哪个应用程序存在一些模糊性。将categoryOptions设置为0或仅调用setCategory:error:最有效。