Транспортные элементы управления не обновляются после уничтожения MediaPlayerService - PullRequest
0 голосов
/ 27 ноября 2018

Хорошо.Я боролся с этой проблемой некоторое время.После последнего обновления ОС OS на панели уведомлений отображается элемент управления воспроизведением / паузой, а не элементы управления мультимедиа в уведомлении.Мой медиаплеер работает нормально до тех пор, пока он не будет приостановлен на некоторое время, и Android уничтожит его, когда он переместился на задний план.Если пользователь выбирает кнопку воспроизведения из элементов управления транспортировкой, музыка начинает воспроизводиться, как и должно, но элементы управления транспортировкой больше не обновляются, что означает, что пользователь может только нажимать кнопку воспроизведения и больше не может делать паузу.Это может быть очень неприятно, если им нужно остановить звук и не может.

Вот код, где я инициализирую медиа-сессию.Этот метод вызывается в onCreate

private void initMediaSession() {
    if (mediaSessionManager != null) return;

    mediaSessionManager = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
    //Create a new mediaSession
    mediaSession = new MediaSessionCompat(getApplicationContext(), "com.turndapage.navmusic.mediaplayer");
    //Get mediaSessions Transport Controls
    mediaSession.getController().getTransportControls();
    //Set Mediasession ready to receive media commands
    mediaSession.setActive(true);

    mediaSession.setFlags(
            MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                    MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

    callback = new MediaSessionCompat.Callback() {
        // Implement callbacks
        @Override
        public void onPlay() {
            super.onPlay();
            Cat.d("Playing from transport controls.");
            // This is the event that is triggered from the transport controls
            resumeMedia();
        }

        @Override
        public void onPause() {
            super.onPause();
            Cat.d("Pausing from transport controls");
            pauseMedia();
        }

        @Override
        public void onSkipToNext() {
            super.onSkipToNext();
            skipToNext();
        }

        @Override
        public void onSkipToPrevious() {
            super.onSkipToPrevious();
            skipToPrevious();
        }

        @Override
        public void onStop() {
            super.onStop();
            stop();
        }

        @Override
        public void onSeekTo(long position) {
            super.onSeekTo(position);
            mediaPlayer.seekTo((int)position);
        }

        @Override
        public void onFastForward() {
            super.onFastForward();
            fastForward();
        }

        @Override
        public void onRewind() {
            super.onRewind();
            rewind();
        }

        @Override
        public void onPlayFromMediaId(String mediaId, Bundle extras) {
            int id = Integer.parseInt(mediaId.replace("song", ""));
            int thisIndex = 0;
            for(Song song : songLibrary.getSongs()) {
                if(song.getID() == id) {
                    ArrayList<Song> songs = getCurrentList();
                    thisIndex = songs.indexOf(song);
                    break;
                }
            }
            int[] ids = new int[getCurrentList().size()];
            for(int i = 0; i < ids.length; i++) {
                ids[i] = getCurrentList().get(i).getID();
            }
            startPlaying(ids, thisIndex);
        }

        @Override
        public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
            KeyEvent event = mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
            Cat.e("onMediaButtonEvent called: " + event);
            if (event.getAction() == KeyEvent.ACTION_UP) {
                switch (event.getKeyCode()) {
                    case KeyEvent.KEYCODE_MEDIA_PAUSE:
                        pauseMedia();
                        break;
                    case KeyEvent.KEYCODE_MEDIA_PLAY:
                        playMedia();
                        break;
                    case KeyEvent.KEYCODE_MEDIA_NEXT:
                        //skipToNext();
                        break;
                    case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
                        //skipToPrevious();
                        break;
                }
            }
            return super.onMediaButtonEvent(mediaButtonEvent);
        }
    };

    // Attach a callback to receive MediaSession update
    mediaSession.setCallback(callback);
    setSessionToken(mediaSession.getSessionToken());
}

. Этот метод вызывается, когда пользователь щелкает элемент управления воспроизведением транспорта

public void resumeMedia() {
    wasPlaying = true;
    if(mediaPlayer != null) {
        try {
            if (!getPlaying()) {
                mediaPlayer.seekTo(resumePosition);
                mediaPlayer.start();
                sendPlayPauseUpdate(true);
                buildNotification(true);
            }
            ComplicationHelper.updatePlayPause(this, true);
        } catch (IllegalStateException ex) {
            ex.printStackTrace();
            //restoreState();
            startMediaPlayer();
        }
    }
}

. При отправке обновления воспроизведения / паузы отправляется широковещательная рассылка действию для обновления.управления там.

Внутри кода уведомления, у меня есть это, чтобы обновить состояние воспроизведения медиа-сессии.Как видите, действия паузы или воспроизведения добавляются только в зависимости от того, воспроизводится медиаплеер или нет.Несмотря на это, действие воспроизведения все еще отображается:

long actions = MEDIA_SESSION_ACTIONS;
    if(isPlaying)
        actions |= PlaybackStateCompat.ACTION_PAUSE;
    else
        actions |= PlaybackStateCompat.ACTION_PLAY;
    mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
            .setActions(actions)
            .setState(isPlaying ? PlaybackStateCompat.STATE_PLAYING :
                    PlaybackStateCompat.STATE_PAUSED, resumePosition, 1)
            .build());

, а вот действия медиа-сессии:

// Media Session Actions
private static final long MEDIA_SESSION_ACTIONS =
        PlaybackStateCompat.ACTION_SEEK_TO |
                PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
                PlaybackStateCompat.ACTION_SKIP_TO_NEXT |
                PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH |
                PlaybackStateCompat.ACTION_PREPARE |
                PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH |
                PlaybackStateCompat.ACTION_PLAY_PAUSE |
                PlaybackStateCompat.ACTION_STOP |
                PlaybackStateCompat.ACTION_FAST_FORWARD |
                PlaybackStateCompat.ACTION_REWIND;

Что я пробовал:

  • Изменение сеанса мультимедиа на статический и обратно
  • превращение обратного вызова в переменную, а не создание нового при создании.
  • Ручная установка состояния воспроизведения медиасессии для воспроизведения после воспроизведения с помощью элементов управления транспортом

Это работает в приложении для телефона, хотя я использую ожидающее намерение отправить команду запуска для запуска функции возобновления, а не управления транспортом.Я также могу возобновить воспроизведение с органов управления транспортом часов, если я использую телефон для воспроизведения звука, и элементы управления корректно обновляются, даже если приложение телефона использует тот же класс.

Пожалуйста, дайте мне знать, если таковые имеютсяможет быть полезна другая информация.

Спасибо!

-Joel

...