События дистанционного управления iOS Media Player (MPRemoteCommand) не работают с Unity

Недавно я обнаружил, что обработчики событий дистанционного управления MediaPlayer (MPRemoteCommand) не вызываются в приложении iOS со встроенным проигрывателем Unity. Я использую Xcode 6.3.1 и Unity 5.0.1f1, однако, похоже, что он может быть воспроизведен с любой комбинацией доступных в настоящее время версий.

Это официальная документация Apple по обработке событий удаленного управления на iOS: https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/Remote-ControlEvents/Remote-ControlEvents.html

Эту проблему очень легко воспроизвести - всего лишь 24 строки кода добавляются в пустой проект.

  1. Создайте новое приложение Single View в Xcode (чтобы сделать рабочий пример без плеера Unity) или создайте пустой проект в Unity и сразу же создайте его для платформы iOS (Файл -> Настройки сборки..., iOS, Сборка) со всеми настройками, оставленными с их значения по умолчанию, чтобы получить проект Xcode, сгенерированный Unity (чтобы сделать неработающий пример со встроенным проигрывателем Unity).

  2. Импортируйте заголовочный файл платформы MediaPlayer в AppDelegate.h (например, без Unity) или UnityAppController.h (например, с Unity):

    #import <MediaPlayer/MediaPlayer.h>
    
  3. Объявите свойство для объекта MPMoviePlayerController в интерфейсе класса, расположенном в AppDelegate.h/UnityAppController.h:

    @property (strong, nonatomic) MPMoviePlayerController *player;
    
  4. Вставьте этот код, который создает проигрыватель с URL-адресом (это прямая радиостанция, вы можете использовать любой другой источник живого аудио HTTP, который вы хотите), регистрирует обработчики для событий дистанционного управления play, pause и togglePlayPause и начинает воспроизведение звука (делая приложение "Now Playing" в начале приложения:didFinishLaunchingWithOptions: метод, расположенный в AppDelegate.m/UnityAppController.mm (вы также можете добавить его непосредственно перед оператором возврата этого метода - это не имеет значения):

    self.player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:@"http://81.9.96.34/eldoradio-64k"]];
    
    [[MPRemoteCommandCenter sharedCommandCenter].playCommand addTarget:self action:@selector(playCommand)];
    [[MPRemoteCommandCenter sharedCommandCenter].pauseCommand addTarget:self action:@selector(pauseCommand)];
    [[MPRemoteCommandCenter sharedCommandCenter].togglePlayPauseCommand addTarget:self action:@selector(togglePlayPauseCommand)];
    
    [self.player play];
    
  5. Добавьте реализацию обработчиков в AppDelegate.m/UnityAppController.mm:

    - (void)playCommand {
        [self.player play];
    }
    
    - (void)pauseCommand {
        [self.player pause];
    }
    
    - (void)togglePlayPauseCommand {
        if (self.player.playbackState == MPMoviePlaybackStatePlaying) {
            [self.player pause];
        } else {
            [self.player play];
        }
    }
    
  6. Создайте и запустите приложение. Вы должны услышать, как играет музыка, как только она началась

  7. Запустите некоторые события дистанционного управления. Самый простой способ - подключить стандартные Apple EarPods и нажать на них кнопку play-pause, которая должна генерировать событие togglePlayPause, но открыть Центр управления iOS (интерфейс, который вы получаете, проведя пальцем по экрану снизу) и нажав кнопку Play / Pause из там тоже все в порядке (они должны генерировать отдельные события play и pause соответственно).

В приложении без Unity аудио останавливается и начинается воспроизведение в соответствии с отправляемыми событиями дистанционного управления. В приложении с обработчиками Unity никогда не вызывается (вы можете установить в них контрольные точки и увидеть это в отладчике), и ничего не происходит вообще. Вы также можете заметить, что внешний вид iOS Control Center совершенно другой: в приложении со встроенным проигрывателем Unity есть кнопка воспроизведения и две кнопки перемотки назад, независимо от состояния звука, но в приложении без Unity при воспроизведении звука отображается просто кнопка паузы или просто нажмите кнопку, когда она не играет.

Вы также можете заменить MPMoviePlayerController на AVPlayer из среды AVFoundation - результат будет точно таким же.

Кто-нибудь знает причину такого поведения и / или обходной путь для него? Это очень сильно влияет на наше приложение.

PS: я уже задавал подобный вопрос раньше, но не получил никаких ответов. Пример в этом как можно более прост.

1 ответ

Мое приложение имеет почти те же настройки, что и у вас, - и та же проблема. Пока я использовал смешанный аудио сеанс

    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions: [.DuckOthers, .InterruptSpokenAudioAndMixWithOthers])

мое приложение не будет вызывать какой-либо из обработчиков MPRemoteCommand.

Когда я превратил свой аудио сеанс в не смешиваемый (убрав опции)

    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)

мои обработчики MPRemoteCommand будут вызываться всякий раз, когда я нажимаю кнопку воспроизведения / паузы на своей гарнитуре.

Таким образом, решение состоит в том, чтобы использовать несмешиваемый аудиосеанс, в котором PlayAndRecord не имеет явных параметров микширования, вместо смешиваемого аудиосеанса.

Другие вопросы по тегам