Элемент управления WebView с фокусом блокирует события медиа-кнопок в Android 5

Редактировать 8 мая 2016 г.

Я нашел причину своих проблем с получением событий мультимедийных кнопок в моем приложении. Смотрите ответ ниже. Я отредактировал название этого вопроса, чтобы облегчить поиск проблемы. Первоначальное название было "Что может блокировать мультимедийные кнопки на Android Lollipop".

Оригинальный вопрос, апрель 2015 года:

Почесывая голову и глядя на весь код в течение 2 дней, но безрезультатно... Предполагается, что мое приложение Android реагирует на мультимедийные кнопки (например, с гарнитуры, проверьте их с помощью гарнитуры Bluetooth), например, воспроизведение / пауза, затем перемотка назад., Прекрасно работает на KitKat и ниже. Клянусь, он даже работал на Lollipop еще несколько дней назад. Теперь ничего, нет никаких следов, что он слышит нажатия кнопок мультимедиа. У кого-нибудь будет быстрое предложение, где искать проблему? Протестировано с двумя телефонами Lollipop, одной и той же гарнитурой Bluetooth и одной и той же гарнитурой, которая отлично работает для более низких версий Android. Также работает та же гарнитура, нажатия кнопок мультимедиа слышны в других приложениях. Что возможно я мог сломать???

Сейчас я проверил как старые, так и новые способы прослушивания мультимедийных кнопок. В AndroidManifest.xml:

<receiver android:name=".MediaButtonIntentReceiver" android:enabled="false">
  <intent-filter>
      <action android:name="android.intent.action.MEDIA_BUTTON" />
  </intent-filter>
</receiver>

Тот факт, что он говорит, что enabled="false" в порядке - я включаю и отключаю приемник по мере необходимости, и MediaButtonIntentReceiver.java получает события прекрасно в KitKat и ниже, полное молчание в Lollipop.

Затем я переключился на последний appcompat (v22.1) и попытался использовать объект MediaSessionCompat и связанный код следующим образом. Это прекрасно работало в небольшом тестовом приложении, только одно из написанных мною действий - мои сообщения Logcat подтверждали, что он слышит нажатие клавиш мультимедиа на Lollipop. Но при вставке в мое приложение снова не работает на Lollipop. Какого черта???

private MediaSessionCompat _mediaSession;
final String MEDIA_SESSION_TAG = "some_tag";

void initMediaSessions(Context context) {
    // Start a new MediaSession
    if (context == null)
        return;
    Lt.d("initMediaSession()...");
    ComponentName eventReceiver = new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName());
    PendingIntent buttonReceiverIntent = PendingIntent.getBroadcast(
            context,
            0,
            new Intent(Intent.ACTION_MEDIA_BUTTON),
            PendingIntent.FLAG_UPDATE_CURRENT
    );

    // Parameters for new MediaSessionCompat():
    // context  The context.
    // tag  A short name for debugging purposes.
    // mediaButtonEventReceiver     The component name for your receiver. This must be non-null to support platform
    // versions earlier than LOLLIPOP. May not be null below Lollipop.
    // mbrIntent    The PendingIntent for your receiver component that handles media button events. This is optional
    // and will be used on JELLY_BEAN_MR2 and later instead of the component name.
    _mediaSession = new MediaSessionCompat(context, MEDIA_SESSION_TAG, eventReceiver, buttonReceiverIntent);
    _mediaSession.setCallback(new MediaSessionCallback());
    _mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                            MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
    _mediaSession.setActive(true);
    PlaybackStateCompat state = new PlaybackStateCompat.Builder()
            .setActions(
                    PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PLAY_PAUSE |
                            PlaybackStateCompat.ACTION_PAUSE |
                            PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
            .setState(PlaybackStateCompat.STATE_STOPPED, 0, 1, SystemClock.elapsedRealtime())
            .build();
    _mediaSession.setPlaybackState(state);
}


final class MediaSessionCallback extends MediaSessionCompat.Callback {
    @Override
    public void onPlay() {
        Lt.d("play");
    }

    @Override
    public void onPause() {
        Lt.d("pause");
    }

    @Override
    public void onStop() {
        Lt.d("stop.");
    }

    @Override
    public void onSkipToNext() {
        Lt.d("skipToNext");
    }

    @Override
    public void onSkipToPrevious() {
        Lt.d("skipToPrevious");
    }

    @Override
    public boolean onMediaButtonEvent(final Intent mediaButtonIntent) {
        Lt.d("GOT MediaButton EVENT");
        KeyEvent keyEvent = (KeyEvent) mediaButtonIntent.getExtras().get(Intent.EXTRA_KEY_EVENT);
        // ...do something with keyEvent, super... does nothing.
        return super.onMediaButtonEvent(mediaButtonIntent);
    }
}

2 ответа

Решение

8 мая 2016: Решил наверняка, я наконец нашел причину, по которой кнопки мультимедиа не работали с моим приложением, когда был включен главный экран. Позже я заметил, что они работали, если какое-либо другое приложение было активно, или экран выключен и т. Д., Но не тогда, когда моя основная активность была активна. Оказывается, что по крайней мере в Android 5 элемент управления WebView, который я использую на своем главном экране, блокирует мультимедийные кнопки, если он имеет фокус. Вызов:

webView.setFocusable(false);

или же

webView.setFocusableInTouchMode(false);

или установка того же атрибута в макете, решает проблему. В Android 6 настраиваемая настройка WebView не имела значения для получения событий мультимедийных кнопок.

24 апреля 2015 г.: решено? - не совсем... Из комментария к этому посту: Обработка мультимедийных кнопок в Android 5.0 Lollipop от @mangini:

Чтобы получать события мультимедийных кнопок, когда ваша активность находится на переднем плане, вызовите setMediaController() для вашей активности с экземпляром MediaController, подключенным к вашей активной MediaSession. - Манджини 23 января в 18:35

Я все время проводил тестирование с включенным экраном, и на нем открывалась моя активность, так как она всегда работала таким же образом и в более старых версиях Android... Как только я нажал кнопку "Домой" или выключил экран, мой старый MediaButtonIntentReceiver запустился работает нормально.

События кнопки " Обновить мультимедиа" поступают в мое приложение только в том случае, если включен диспетчер экрана блокировки с использованием устаревшего RemoteControlClient, и, конечно, моя деятельность находится не на переднем плане. Если я отключу диспетчер экрана блокировки (который есть в моем приложении) и удалю RemoteControlClient, я снова не получу никаких событий мультимедиа.

Эта проблема под Lollipop - полный беспорядок. Или по крайней мере полный беспорядок об этом существует в моей голове прямо сейчас. Желаю, чтобы кто-то опубликовал пример кода для работы с мультимедийными кнопками, который будет работать в старых версиях Android и Lollipop...

Greg

Просьба переопределить функцию возврата false.

@Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        return false;
    }
Другие вопросы по тегам