刚开始学习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) {
}
});
} }
答案 0 :(得分:0)
首先,定义一个public int和一个公共布尔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();
}
});
然后将Timer().scheduleAtFixedRate
更改为此(添加if语句)
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (!flag)
scrubber.setProgress(mplayer.getCurrentPosition());
}
},0 ,1000);
并完成! 希望了解改变的原因。但如果你没有问过。
答案 1 :(得分:0)
函数“ setProgress”在“搜索”栏中进行了更改,计时器每x毫秒调用一次。在搜索栏中进行的任何更改都将由“ seekbarchangeListener”捕获。在更改seekbarChangeListener中,我们添加了seekTo函数,该函数会将音乐移动x + dx秒。由于造成延迟效应的延迟,增加了额外的dx秒。
下面的实现检查isSongRunning布尔值,以便如果Timer的Seekbar中发生更改,则不会完成seekTo,如果由于seekbar中的移动而进行了更改,则将为false。
最终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,该延迟将非常小,并且很难识别。但是通过这种方式,搜索栏状态的反映将不会很快。
答案 2 :(得分:0)
在 onProgressChanged()
中,
将代码写成:
if(fromUser)
mplayer.seekTo(progress);
因此,只有当用户这样做时,seekTo 才会被触发,而不是因为计时器。