【问题标题】:Android audio seekbar delayAndroid 音频搜索栏延迟
【发布时间】:2023-03-28 08:02:01
【问题描述】:

刚开始学习 Java,目前正在学习一些媒体基础知识。 我创建了一个小应用程序(播放音乐文件),带有一个可以正常工作的音量控制器搜索栏,一个播放和一个也可以正常工作的停止按钮。当音乐播放时,我设法到达那个点,进度搜索栏更新并向右移动,因为它需要在播放歌曲时做。当想要添加代码以实际能够改变音乐的进度时,每次搜索更新(每 1000 毫秒/1 秒)时,我都会暂停(延迟)。如果我添加

mplayer.seekTo(progress);

对于代码,每次搜索栏更新(每秒)时,我都会收到音乐延迟。

这是我的代码:

package com.dionisie.sounddemo;

import android.content.Context; import android.media.AudioManager;
import android.support.v7.app.AppCompatActivity; import
android.os.Bundle; import android.media.MediaPlayer; import
android.view.View; import android.widget.SeekBar; import
android.widget.SeekBar.OnSeekBarChangeListener; import
android.util.Log;

import java.util.Timer; import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    MediaPlayer mplayer;

    AudioManager audioManager;

    public void playAudio(View view) {
        mplayer.start();
    }


    public void pauseAudio(View view) {
        mplayer.pause();
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mplayer = MediaPlayer.create(this, R.raw.joanna);

        audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        int curVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

        SeekBar volumeControl = (SeekBar) findViewById(R.id.seekBar);
        volumeControl.setMax(maxVolume);
        volumeControl.setProgress(curVolume);

        volumeControl.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

                audioManager.setStreamVolume(audioManager.STREAM_MUSIC, progress, 0);

            }
        });


        final SeekBar scrubber = (SeekBar) findViewById(R.id.scrubber);

        scrubber.setMax(mplayer.getDuration());

        new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                scrubber.setProgress(mplayer.getCurrentPosition());
            }
        }, 0, 1000);

        scrubber.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                mplayer.seekTo(progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

    } }

【问题讨论】:

    标签: java android android-mediaplayer android-seekbar


    【解决方案1】:

    函数“setProgress”在 Seek 栏中进行更改,并由 Timer 每 x 毫秒调用一次。在搜索栏中所做的任何更改都将被“seekbarchangeListener”捕获。在更改 seekbarChangeListener 中,我们添加了 seekTo 函数,它将音乐移动 x+dx 秒。这个额外的 dx 秒是由于导致滞后效应的延迟而增加的。

    下面的实现会检查 isSongRunning 布尔值,以便如果 Seekbar 中的 Timer 发生更改,如果由于 seekbar 中的移动而发生更改,则不会执行 seekTo,这将是错误的。

    final SeekBar sngbar = (SeekBar) findViewById(R.id.player); sngbar.setMax(song.getDuration());

        new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                isSongRunning = true;
                sngbar.setProgress(song.getCurrentPosition());
    
            }
        }, 0, 100);
    
    
        sngbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    
            @Override
            public void onProgressChanged(SeekBar seekBar, int sngchg, boolean b) {
                if(!isSongRunning){
                    song.seekTo(sngchg);
                }else
                {
                    isSongRunning = !isSongRunning;
                }
    
            }
    
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
    
            }
    
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
    
            }
        });
    

    您还可以将计时器中的 x 毫秒增加到 10000,延迟将非常小并且不容易识别。但是这样一来,seek bar状态的反映就不会很快了。

    【讨论】:

      【解决方案2】:

      首先,定义一个 public int 和一个 public boolean int save, boolean flag

      把你的setOnSeekBarChangeListener改成这个

       volumeControl.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
              @Override
              public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                  save = progress;
      
              }
      
              @Override
              public void onStartTrackingTouch(SeekBar seekBar) {
                  mplayer.pause();
                  flag = true;
      
      
              }
      
              @Override
              public void onStopTrackingTouch(SeekBar seekBar) {
                  mplayer.seekTo(save);
                  mplayer.start();
                  flag = false;
              }
          });
      

      然后将您的 Timer().scheduleAtFixedRate 更改为此(添加一个 if 语句)

      new Timer().scheduleAtFixedRate(new TimerTask() {
              @Override
              public void run() {
      
                  if (!flag) 
                      scrubber.setProgress(mplayer.getCurrentPosition());
      
              }
          },0 ,1000);
      

      完成! 希望了解改变的原因。但如果你不只是问的话。

      【讨论】:

        【解决方案3】:

        onProgressChanged(), 把代码写成:

        if(fromUser)
            mplayer.seekTo(progress);
        

        因此 seekTo 只会在用户触发时触发,而不是因为 Timer。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-12-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-21
          • 1970-01-01
          相关资源
          最近更新 更多