如果您希望避免媒体文件加载时出现轻微延迟,您应该提前准备媒体播放器实例。您的媒体文件加载并准备播放时有延迟。您有几种选择:
- 继续使用
MediaPlayer.create()
,但这样做的越早,你就可以打电话playSound()
之前。在您提供的简单示例中,请尝试在onCreate()
方法中调用MediaPlayer.create()
。
- 您也可以使用
prepareAsync()
和setOnPreparedListener()
方法在后台准备媒体文件,并在准备就绪时设置通知。这更复杂,但为您提供更多的控制和更好的用户体验。如果你需要加载一个大文件,这是使它工作的最好方法。小型音频文件可能不是什么大问题。
- 如果您要一遍又一遍播放同一个媒体文件,则无需立即释放MediaPlayer。如果您没有重置或释放,媒体将仍然在内存中,并可以立即再次播放。但是一定要在之后以及
onPause()
或onStop()
等生命周期事件中致电release()
。
See the documentation for details。
让它几秒钟播放,然后停止,使用Android的CountDownTimer:
// Will call onFinish() after 2 seconds. Second parameter is
// for onTick() which we don't need and can ignore.
new CountDownTimer(2000, 2000) {
public void onTick(long millisUntilFinished) {
// Do nothing...
}
public void onFinish() {
mediaPlayer.stop();
// Decide here if you need to prepare a new clip
// or release the media player
}
}.start();
下面是一个完整的例子:
package com.example.matthew.somediaplayer;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "TEST";
private MediaPlayer mediaPlayer;
private boolean isMediaPlayerPrepared = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setEnabled(false);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mediaPlayer.isPlaying() == false) {
playSound();
}
}
});
}
@Override
public void onResume(){
super.onResume();
Log.d(TAG, "In onResume()");
createAndPrepareMediaPlayer();
}
@Override
public void onStop() {
super.onStop();
Log.d(TAG, "In onStop()");
mediaPlayer.release();
isMediaPlayerPrepared = false;
}
@Override
public void onPause(){
Log.d(TAG, "In onPause()");
super.onPause();
}
public void createAndPrepareMediaPlayer() {
Log.d(TAG, "In createAndPrepareMediaPlayer()");
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
if(isMediaPlayerPrepared == false) {
try {
AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.test);
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG, "Media player is prepared.");
isMediaPlayerPrepared = true;
Button button = (Button) findViewById(R.id.button);
button.setEnabled(true);
}
});
Log.d(TAG, "Beginning to prepare media player.");
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void playSound() {
Log.d(TAG, "In playSound()");
if(isMediaPlayerPrepared) {
// Will call onFinish() after 2 seconds. Second parameter is
// for onTick() which we don't need and can ignore.
new CountDownTimer(2000, 2000) {
public void onTick(long millisUntilFinished) {
// Do nothing...
}
public void onFinish() {
Log.d(TAG, "In onFinish()");
// We can't call a method like pause on an unprepared MediaPlayer instance.
if(isMediaPlayerPrepared) {
mediaPlayer.pause();
} else {
Log.d(TAG, "Media player isn't prepared, and isn't allowed to pause.");
}
}
}.start();
mediaPlayer.setLooping(false);
mediaPlayer.seekTo(0); // set to beginning of track (if not already)
mediaPlayer.start();
Log.d(TAG, "Starting to play a sound.");
}
}
}
应该在哪里prepareAsync()去?在oncreate/resume/start方法中? – Bobdabiulder
这取决于您的应用程序,但我可能会使用onResume()来准备并发布onPause()。 – matsuzine