我有这个媒体播放器和其他一切正常工作,我开始歌曲,它通过两个状态,最后一个是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从未被调用。你知道为什么吗?
最佳答案
似乎只有当MediaControllerCompat.Callback.onPlaybackStateChanged(PlaybackStateCompat state)
的MediaSessionCompat
更改时才会调用PlaybackStateCompat
。如果state
的PlaybackStateCompat
更改而position
保持不变,则永远不会调用state
。所以我假设“onPlayBackstateChanged”,API更具体地指的是onPlaybackStateChanged(...)
的PlaybackStateCompat
,而不是state
本身。
为了解决这个问题,我在ui上触发PlaybackStateCompat
的seek命令之后,临时将PlaybackStateCompat
的state
更新为PlaybackStateCompat.STATE_REWINDING
或PlaybackStateCompat.STATE_FAST_FORWARDING
,以便将onPlaybackStateChanged(...)
的位置和经过的时间SeekBar
的文本更新为新的播放位置。
更新:我不能再复制这个问题。我也不知道我到底是怎么改的。我给你的第一个建议是确认你正在对TextView
对象调用setState(state)
,其中mediaSession
是包含你更新的state
值的PlaybackStateCompat
。这不是我的解决办法,但我会先看看。