使用更优雅的代码一个接一个地播放 mp3 文件,几乎没有延迟



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

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() )是相同的。两者都是不同的媒体播放器,为了简单起见,我只在帖子中写了一个副本

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();
        }
    }

要立即播放,您需要设置两个媒体播放器并通过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);

你可以尝试这样的事情。在单个线程中使用单个媒体播放器。这是一个异步操作,因此如果线程暂停,它也将继续。我认为它会起作用。

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();
}

最新更新