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.");
        }
    }

}