Видеообзор Android переносится назад во времени

#android #kotlin #android-videoview

Вопрос:

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

Изменение панели поиска:

 binding.progressBarVideo.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
        override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {


            if (underSeek) {
                binding.textViewTime.text = durationToFormat(binding.videoViewF.currentPosition)
                binding.videoViewF.seekTo(seekBar.progress)

                RLog.d("------------------")
                RLog.d("Seekbar progress: ${seekBar.progress}")
                RLog.d("videoView position: ${binding.videoViewF.currentPosition}")
                RLog.d("Time display string: ${durationToFormat(binding.videoViewF.currentPosition)}")
            }
        }

        override fun onStartTrackingTouch(seekBar: SeekBar?) {
            mainHandler.removeCallbacks(updateTextTask)
            underSeek = true
        }

        override fun onStopTrackingTouch(seekBar: SeekBar?) {
            mainHandler.post(updateTextTask)
            underSeek = false
            hideTimer = 0
        }

    })
 

Задача обновления:

 private val updateTextTask = object : Runnable {
    override fun run() {

        RLog.d("----------------------------")
        RLog.d("videoView position: ${binding.videoViewF.currentPosition}")
        RLog.d("Time display string: ${durationToFormat(binding.videoViewF.currentPosition)}")

        binding.textViewTime.text = durationToFormat(binding.videoViewF.currentPosition)
        binding.progressBarVideo.progress = binding.videoViewF.currentPosition
        mainHandler.postDelayed(this, 1000)
                }
}
 

Продолжительность для форматирования:

 @SuppressLint("DefaultLocale")
private fun durationToFormat(duration: Int): String {

    return java.lang.String.format(
        "d:d",
        TimeUnit.MILLISECONDS.toMinutes(duration.toLong()),
        TimeUnit.MILLISECONDS.toSeconds(duration.toLong()) -
                TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration.toLong()))
    )
}
 

Бревна:

 #onProgressChanged: ------------------
#onProgressChanged: Seekbar progress: 257875
#onProgressChanged: videoView position: 257875
#onProgressChanged: Time display string: 04:17
#run: ----------------------------
#run: videoView position: 257875
#run: Time display string: 04:17
#run: ----------------------------
#run: videoView position: 256957
#run: Time display string: 04:16
#run: ----------------------------
 

Как вы можете видеть, после поиска время равно 257875, первая итерация таймера также равна 257875. Затем он перескакивает на 256957, и я не понимаю, почему…

Ответ №1:

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

В этом случае вы можете отфильтровать обновление хода выполнения из кода и искать новую позицию видео только fromUser true в том случае, если она включена onProgressChanged:

 override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
    if (fromUser) {
        binding.videoViewF.seekTo(seekBar.progress)
    }
    binding.textViewTime.text = durationToFormat(binding.videoViewF.currentPosition)
}

private val updateTextTask = object : Runnable {
    override fun run() {
        binding.progressBarVideo.progress = binding.videoViewF.currentPosition
        mainHandler.postDelayed(this, 1000)
    }
}
 

Также в этом случае вы можете удалить обновление текста из выполняемого, так как оно будет вызвано обновлением позиции на панели прогресса.

Ответ №2:

я не уверен, но я думаю, что проблема в том, что postDelayed, так как на самом деле он запускается через 1 секунду. Поэтому попробуйте добавить сюда 1000 мс, надеюсь, он будет вести себя правильно.

 RLog.d("Time display string: ${durationToFormat(binding.videoViewF.currentPosition   1000)}")