5

私はこのメディア プレーヤーを持っており、他のすべては正常に動作します。曲を開始すると、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 が新しい値を返す場所ですが、onPlaybackStateChanged が呼び出されないため、常に 0 を返します。理由はありますか?

4

2 に答える 2

2

が変更されたMediaControllerCompat.Callback.onPlaybackStateChanged(PlaybackStateCompat state)場合にのみ呼び出されるようMediaSessionCompatです。が変更されずに が変更された場合、呼び出されることはありません。したがって、「onPlaybackStateChanged」によって、API はそれ自体ではなく、より具体的に参照していると思います。PlaybackStateCompatstatePlaybackStateCompatpositionstateonPlaybackStateChanged(...)PlaybackStateCompatstatePlaybackStateCompat

これを回避するために、の位置と経過時間のテキストを新しい再生位置に更新できるように、シーク コマンドPlaybackStateCompatの前後に を一時的に更新stateして、UI でトリガーします。PlaybackStateCompat.STATE_REWINDINGPlaybackStateCompat.STATE_FAST_FORWARDINGonPlaybackStateChanged(...)SeekBarTextView

更新: この問題を再現できなくなりました。それを修正するために正確に何を変更したのかもわかりません。あなたへの私の最初の提案は、更新された値が含まれているオブジェクトを呼び出していることを確認することですsetState(state)。これは私にとっての解決策ではありませんでしたが、最初に見た場所です。mediaSessionstatePlaybackStateCompatposition

于 2016-12-20T21:00:16.687 に答える