一个接一个地播放mp3文件,延迟较少,代码更优雅?

时间:2015-06-11 10:59:25

标签: android

单击按钮时,我需要播放从我的资源加载的多个(正确的:2)mp3文件。如果再次点击该按钮,则应播放2首新歌,并且应立即停止旧歌。过程正在进行中...... 目前,我通过愚蠢地在两个基本上具有相同主体的独立方法中创建2个mediaPlayer实例来实现这一目标。  调用者是onTouch方法,在其中,首先我调用方法1,然后休眠2秒,然后调用方法2.我确定必须有一种方法可以使代码更优雅吗?例如,我已经实现了一些只是坐在那里的听众(实际上试图使this工作但完全搞砸了非法国家。)理想情况下,我想使用1个MediaPlayer和一种方法在我的应用中播放每个声音。

int carouzelIndex = 0

@Override
public boolean onTouch(MotionEvent e, int scaledX, int scaledY) {
     ...
    if (e.getAction() == MotionEvent.ACTION_UP) {
        carouzelIndex++;
        Assets.playMusic1("music1.ogg",false);
        Thread thread = new Thread(){                   
            public void run(){
                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {          
                    e.printStackTrace();
                }
                Assets.playMusic2("music2.ogg",false);
            }
        }
    }
}

现在我的播放器方法1和2(playMusic1()和playMusic2())是相同的。两者都是不同的MediaPlayers,为了简单起见我只在帖子中写了一个副本

Public class Assets
     MediaPlayer mediaPlayer;

    public static void playMusic(String filename, boolean looping) {

        AssetFileDescriptor afd = null;

        Log.d("Assets", "playing music");
        if (mediaPlayer == null) {
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setLooping(looping);
        }
        try {

            if (mediaPlayer != null) {
                mediaPlayer.stop();
                mediaPlayer.release();
                mediaPlayer = new MediaPlayer();
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mediaPlayer.setLooping(looping);
            }

            afd = GameMainActivity.assets.openFd(filename);
            mediaPlayer.setDataSource(afd.getFileDescriptor(),
                    afd.getStartOffset(), afd.getLength());
            afd.close();   
            mediaPlayer.prepareAsync();   
            mediaPlayer.setOnPreparedListener(new OnPreparedListener() {    
                @Override
                public void onPrepared(MediaPlayer mp) {
                    if (!mp.isPlaying())
                        mp.start();
                }
            });

            mediaPlayer.setOnErrorListener(new OnErrorListener() {

                @Override
                public boolean onError(MediaPlayer mp, int what, int extra) {               
                    return false;
                }
            });

            mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer mp) {
                    mediaPlayerIsFinished = true;
                    mp.reset();
                }

            });

            mediaPlayer.setOnInfoListener(new OnInfoListener() {

                @Override
                public boolean onInfo(MediaPlayer mp, int what, int extra) {
                    // TODO Auto-generated method stub
                    return false;
                }

            });

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2 个答案:

答案 0 :(得分:1)

要立即播放,您需要设置两个MediaPlayer并通过OnCompletionListener

链接在一起

你可以这样做:

请注意,我还删除了一些不必要的覆盖,如果需要,可以再次添加它们。

    Public class Assets{
         MediaPlayer mediaPlayer;
         MediaPlayer mediaPlayer2;
         boolean mediaplayer2prepared = false;
         boolean mediaplayer1finished = false;

    public static void playMusic(String filename, boolean looping, String filename2, boolean looping2) {

        AssetFileDescriptor afd = null;

        Log.d("Assets", "playing music");
        if (mediaPlayer == null) {
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setLooping(looping);
            mediaplayer1finished = false;
        }
        if (mediaPlayer2 == null) {
            mediaPlayer2 = new MediaPlayer();
            mediaPlayer2.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer2.setLooping(looping);
            mediaplayer2prepared = false;
        }
        try {

            if (mediaPlayer != null) {
                mediaPlayer.stop();
                mediaPlayer.release();
                mediaPlayer = new MediaPlayer();
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mediaPlayer.setLooping(looping);
                mediaplayer1finished = false;
            }
            if (mediaPlayer2 != null) {
                mediaPlayer2.stop();
                mediaPlayer2.release();
                mediaPlayer2 = new MediaPlayer();
                mediaplayer2prepared = false;
                mediaPlayer2.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mediaPlayer2.setLooping(looping);
            }

            afd = GameMainActivity.assets.openFd(filename);
            mediaPlayer.setDataSource(afd.getFileDescriptor(),
                    afd.getStartOffset(), afd.getLength());
            afd.close();   

            mediaPlayer.setOnPreparedListener(new OnPreparedListener() {    
                @Override
                public void onPrepared(MediaPlayer mp) {
                    if (!mp.isPlaying())
                        mp.start();
                }
            });
            mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer mp) {
                    mediaPlayerIsFinished = true;
                    mp.reset();
                    if(mediaplayer2prepared)
                       mediaplayer2.start();
                    mediaplayer1finished = true;
                }

            });
            mediaPlayer.prepareAsync();
            afd2 = GameMainActivity.assets.openFd(filename2);
            mediaPlayer2.setDataSource(afd2.getFileDescriptor(),
                    afd2.getStartOffset(), afd2.getLength());
            afd2.close();
            mediaPlayer2.setOnPreparedListener(new OnPreparedListener() {    
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mediaPlayerIsFinished = true;
                    mp.reset();
                    mediaplayer2prepared = true;
                    if(mediaplayer1finished && !mp.isPlaying()){
                       mp.start();
                    }
                }

            });
            mediaPlayer2.setOnCompletionListener(new OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer mp) {
                    mediaPlayerIsFinished = true;
                    mp.reset();
                }
            });
            mediaPlayer2.prepareAsync(); 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

要连续启动两个媒体播放器,只需执行Assets.playMusic("music1.ogg",false, "music2.ogg",false);

答案 1 :(得分:1)

You can try something like this. Use a single mediaplayer in a single thread. It is an asynchronous operation so it will go on also if the thread is paused. I think it would work.

private Thread t = null;
private MediaPlayer mediaPlayer;



...
    Button b=findViewById(R.id.yourButtonId);
        b.setOnClickListener(new View.OnClickListener(){
         @Override
         public void onClick(View v){
          //if button had previously clicked stop audio reproduction 
          if(mediaPlayer.isPlaying()) mediaPlayer.stop();
          if(t.isAlive()) t.stop();
          String[] files;
          //Here you have to set your filenames in the array
          ...
          ...
          //Now play that audio
          playMusic(files, false);
         }
    });
...

protected static void playMusic(String[] files, boolean looping){
    AssetFileDescriptor afd = null;
    Log.e("Assets", "Playing music");

    t=new Thread(){
        @Override
        public void run(){
            //Initialize mediaPlayer
            for(String filename:files){
                mediaPlayer=new MediaPlayer();
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mediaPlayer.setLooping(looping);
                afd = GameMainAcivity.assets.openFd(filename);
                mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),afd.getLength());
                afd.close();
                mediaPlayer.prepareAsync();
                mediaPlayer.setOnPreparedListener(new OnPreparedListener(){
                    @Override
                    public void onPrepared(MediaPlayer mp){
                        if(!mp.isPlaying()) mp.start();
                    }
                });
                //while audio is playing wait in this position
                while(mediaPlayer.isPlaying()){
                    this.wait(100);
                }
                //now loop can restart with the other filename that has 
                //to be reproduced
            }
        }
    };
    t.start();
}