Android 的媒体播放器库存在问题
Issues with Android's Mediaplayer lib
我有一些相当标准的 运行 MP3 代码,但播放它需要大约 2 秒。这个应用程序非常简单。此应用程序应播放 1-2 秒的声音。另外,有没有办法在应用程序加载时将 mp3 缓冲到 RAM 或其他东西中,以便它可以非常快速地播放(w/o 延迟)?请帮忙!
import android.content.Context;
import android.media.MediaPlayer;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity1 extends ActionBarActivity {
MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_activity1);
}
public void playSound(View v)throws Exception{
mediaPlayer = MediaPlayer.create(this, R.raw.john_cena);
mediaPlayer.setLooping(false);
mediaPlayer.start();
Thread.sleep(1500);
//mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
Log.d("1234FIND", "STOP RELEASE RESET");
}
}
如果你想避免媒体文件加载时的轻微延迟,你应该提前准备你的媒体播放器实例。加载媒体文件并准备播放时会有延迟。您有几个选择:
- 继续使用
MediaPlayer.create()
,但在您准备好调用 playSound()
之前尽早使用。在您提供的简单示例中,尝试在 onCreate()
方法中调用 MediaPlayer.create()
。
- 您还可以使用
prepareAsync()
和 setOnPreparedListener()
方法在后台准备媒体文件并设置准备就绪时的通知。这更复杂,但可以为您提供更多控制和更好的用户体验。如果您需要加载一个大文件,这是使其工作的最佳方式。小的音频文件可能没什么大不了的。
- 如果您要反复播放同一个媒体文件,则无需立即释放 MediaPlayer。如果您不重置或释放,媒体仍将在内存中并可以立即再次播放。但一定要在确定完成后调用
release()
,并在 onPause()
或 onStop()
等生命周期事件中调用。
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.");
}
}
}
我有一些相当标准的 运行 MP3 代码,但播放它需要大约 2 秒。这个应用程序非常简单。此应用程序应播放 1-2 秒的声音。另外,有没有办法在应用程序加载时将 mp3 缓冲到 RAM 或其他东西中,以便它可以非常快速地播放(w/o 延迟)?请帮忙!
import android.content.Context;
import android.media.MediaPlayer;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity1 extends ActionBarActivity {
MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_activity1);
}
public void playSound(View v)throws Exception{
mediaPlayer = MediaPlayer.create(this, R.raw.john_cena);
mediaPlayer.setLooping(false);
mediaPlayer.start();
Thread.sleep(1500);
//mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
Log.d("1234FIND", "STOP RELEASE RESET");
}
}
如果你想避免媒体文件加载时的轻微延迟,你应该提前准备你的媒体播放器实例。加载媒体文件并准备播放时会有延迟。您有几个选择:
- 继续使用
MediaPlayer.create()
,但在您准备好调用playSound()
之前尽早使用。在您提供的简单示例中,尝试在onCreate()
方法中调用MediaPlayer.create()
。 - 您还可以使用
prepareAsync()
和setOnPreparedListener()
方法在后台准备媒体文件并设置准备就绪时的通知。这更复杂,但可以为您提供更多控制和更好的用户体验。如果您需要加载一个大文件,这是使其工作的最佳方式。小的音频文件可能没什么大不了的。 - 如果您要反复播放同一个媒体文件,则无需立即释放 MediaPlayer。如果您不重置或释放,媒体仍将在内存中并可以立即再次播放。但一定要在确定完成后调用
release()
,并在onPause()
或onStop()
等生命周期事件中调用。
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.");
}
}
}