android – SeekTo不会在MediaControllerCompat中触发onPlaybackStateChanged

我有这个媒体播放器,其他一切正常,我启动歌曲,它通过2个状态,最后一个是PlaybackStateCompat.STATE_PLAYING

因此我们可以说回调已注册.问题是每当我触发SeekBar监听器时,方法seekTo都不会触发onPlaybackStateChanged,因为这不会发生,我无法将SeekBar更新为新的进度.这仅涉及UI.在修改SeekBar进度后,音乐实际上是从进度中播放的.而且,trackDurationTextView也不会更新.当我将拇指拖过搜索栏时它会改变它的值,但是一旦我释放它,它就会进入其初始进度,与搜索栏相同.

这是回调注册的地方.

@Override
    public void onServiceConnected(ComponentName componentName, IBinder service) {
        if (service instanceof MediaPlayerService.ServiceBinder) {
            try {
                mediaController = new MediaControllerCompat(this, ((MediaPlayerService.ServiceBinder) service).getService().getMediaSessionToken());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            mediaController.registerCallback(mMediaControllerCallback);
        }
    }

这是回调初始化的方式:

 private MediaControllerCompat.Callback mMediaControllerCallback = new MediaControllerCompat.Callback() {
        @Override
        public void onPlaybackStateChanged(@NonNull PlaybackStateCompat state) {
            updatePlaybackState(state);
        }

        @Override
        public void onMetadataChanged(MediaMetadataCompat metadata) {
            if (metadata != null) {
                updateMediaDescription(metadata.getDescription());
                updateDuration(metadata);
            }
        }
    };

这是OnSeekBarChangeListener

trackSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                trackDurationTextView.setText(DateUtils.formatElapsedTime(progress / 1000));
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                stopSeekbarUpdate();
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                //TODO: look here! the seek bar position is not kept when the user slides it!
                mediaController.getTransportControls().seekTo(seekBar.getProgress());
                scheduleSeekBarUpdate();
            }
        });


 private void updateProgress() {
        if (mLastPlaybackState == null) {
            return;
        }
        long currentPosition = mLastPlaybackState.getPosition();
        if (mLastPlaybackState.getState() != PlaybackStateCompat.STATE_PAUSED) {
            // Calculate the elapsed time between the last position update and now and unless
            // paused, we can assume (delta * speed) + current position is approximately the
            // latest position. This ensure that we do not repeatedly call the getPlaybackState()
            // on MediaControllerCompat.
            long timeDelta = SystemClock.elapsedRealtime() -
                    mLastPlaybackState.getLastPositionUpdateTime();

            currentPosition += (int) timeDelta * mLastPlaybackState.getPlaybackSpeed();
        }
        trackSeekBar.setProgress((int) currentPosition);
    }

这是更新搜索栏后mLastPlayBackState.getPosition应返回新值的位置,但它始终返回0,因为onPlaybackStateChanged永远不会被调用.有什么想法吗?

最佳答案 只有MediaSessionCompat的PlaybackStateCompat状态发生变化时,才会调用MediaControllerCompat.Callback.onPlaybackStateChanged(PlaybackStateCompat状态).如果PlaybackStateCompat的位置在状态保持不变的情况下发生变化,则永远不会调用onPlaybackStateChanged(…).所以我假设“onPlaybackStateChanged”,API更具体地指的是PlaybackStateCompat的状态而不是PlaybackStateCompat本身.

为了解决这个问题,我在一个搜索命令后暂时将PlaybackStateCompat的状态更新为PlaybackStateCompat.STATE_REWINDING或PlaybackStateCompat.STATE_FAST_FORWARDING,以便在UI上触发onPlaybackStateChanged(…),以便我可以将SeekBar的位置和已用时间TextView的文本更新为新的播放位置.

更新:我再也无法重现这个问题了.我不确定我究竟改变了什么来修复它.我的第一个建议是验证您是否在mediaSession对象上调用setState(state),其中state是包含更新位置值的PlaybackStateCompat.这不是我的解决方案,但它是我先看的地方.

点赞