同时使用MediaPlayer播放多首歌曲:只有一首真正在播放

时间:2014-10-15 09:49:54

标签: android multithreading audio xamarin android-mediaplayer

我需要帮助在Android中同时播放多个音轨。

我应该使用Android.Media.MediaPlayer在同一时间播放三个音轨

昨天我设法让它工作:

MediaPlayer track1 = MediaPlayer.create(this, R.raw.track1);
MediaPlayer track2 = MediaPlayer.create(this, R.raw.track2);
MediaPlayer track3 = MediaPlayer.create(this, R.raw.track3);

正如您所看到的,我在MediaPlaye这里有三个实例

因为我被要求,我需要在后台主题中播放这些MediaPlayer

以下是我开始MediaPlayers的部分:

//let's suppose this code snippet is in a run() method inside a Thread (which is the case)
track1.start();
track2.start();
track3.start();

如果我昨天说,那是因为第二天,它没有按预期工作。

事实上,启动MediaPlayer似乎停止了之前播放的MediaPlayer

我在调试器模式下进行了测试:显然,track2.start()停止了track1的MediaPlayer,并遵循相同的模式,track3.start()停止了第2个MediaPlayer。

所以最后,只播放了track3 ,我无法听到任何以前的曲目,无论音量设置是什么,而我可以清楚地听到所有这些曲目:它应该创造某种氛围。

当然,更改曲目的开始顺序不会改变任何内容:只会听到最后一首曲目。

如果我说"听到"这是因为在调试器模式下,检查属性MediaPlayer.isPlaying正在返回 true 所有三位玩家都在说他们正在玩,但只能听到一个... !

为什么要改变? 为什么它一旦停止工作就会起作用?

注意:

  • 音频文件具有相同的持续时间,大约约15分钟
  • 音频文件被.mp3个文件压缩为.acc个文件(从320kbps144kbps
  • 我在Xamarin Studio C#下工作,但对于clarety purpouse,我会坚持使用小Java个代码段。

编辑1

根据这个Play two mp3 song at the same time我的解决方案应该正常工作,对吧?

5 个答案:

答案 0 :(得分:8)

我使用CyclicBarrier实例和内部类实现实现了您正在寻找的东西。

示例:

public enum MP_COMMAND {
    START,
    STOP,
    PAUSE
}

/**
 * Uses threads to execute synced commands for the current video media player and 
 * background music player in tandem.
 */
public void syncedCommand(MediaPlayer player1, MediaPlayer player2, MP_COMMAND command) {
    final CyclicBarrier commandBarrier = new CyclicBarrier(2);
    new Thread(new SyncedCommandService(commandBarrier, player1, command)).start();
    new Thread(new SyncedCommandService(commandBarrier, player2, command)).start();
}

/**
 * Inner class that starts a given media player synchronously
 * with other threads utilizing SyncedStartService
 */
private class SyncedCommandService implements Runnable {
    private final CyclicBarrier              mCommandBarrier;
    private       MediaPlayerTest.MP_COMMAND mCommand;
    private       MediaPlayer                mMediaPlayer;

    public SyncedCommandService(CyclicBarrier barrier, MediaPlayer player, MediaPlayerTest.MP_COMMAND command) {
        mCommandBarrier = barrier;
        mMediaPlayer = player;
        mCommand = command;
    }

    @Override public void run() {
        try {
            mCommandBarrier.await();
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }

        switch (mCommand) {
            case START:
                mMediaPlayer.start();
                break;

            case STOP:
                mMediaPlayer.stop();
                break;

            case PAUSE:
                mMediaPlayer.pause();
                break;

            default:
                break;
        }
    }
}

你会像这样使用它:

syncedCommand(mCurrentVideoPlayer, mBackgroundMusic, MP_COMMAND.START);

如果您要求它可以用于任何数量的媒体播放器,您可以轻松实现它 - 我的要求只需要两个。

我意识到这个问题已经过时了,但是这个页面是我在寻找解决方案时发现自己的地方,所以我希望这可以帮助任何人在未来坚持这个问题。

答案 1 :(得分:2)

嗯,我相信我发现了我能说出的“临时解决方案”。

MediaPlayer track1 = MediaPlayer.create(this, R.raw.track1);
track1.start();
MediaPlayer track2 = MediaPlayer.create(this, R.raw.track2);
track2.start();
MediaPlayer track3 = MediaPlayer.create(this, R.raw.track3);
track3.start();

问题在于create()方法在播放歌曲时会产生明显的差距。

所以这不是它。

过了一会儿,我尝试了以下几点:

MediaPlayer track1 = MediaPlayer.create(this, R.raw.track1);
track1.start();
track1.pause();
MediaPlayer track2 = MediaPlayer.create(this, R.raw.track2);
track2.start();
track2.pause();
MediaPlayer track3 = MediaPlayer.create(this, R.raw.track3);
track3.start();
track3.pause();

// resuming...
track1.start(); 
track2.start();
track3.start();

那就是,歌曲更加同步。我仍然可以听到一个很小的差距,但它更好。 我发现这个解决方案既丑陋又丑陋。

除非有人有其他想法,否则我会坚持使用该解决方案。

答案 2 :(得分:1)

正如Andrey Nikishaev已在评论中写道,似乎有些设备在同时使用多个MediaPlayers时遇到问题。虽然只有一个在我的Nexus 5上播放,但它在我的Moto G4上工作(但在播放期间仍然有短暂休息)。两者都运行Android 6.0.1。

我建议使用ExoPlayer代替此用例。它对我来说很好,至少在我的两个设备上。

答案 3 :(得分:0)

我在ogg文件音频中转换了我的mp3(使用Audacity),我可以使用2个Mediaplayer istances并听混音。

我没试过,有可能超过3个。

答案 4 :(得分:0)

嗨尝试下面的代码,它将起作用,歌曲不会停止你只需要从微调器中选择歌曲并单击开始按钮,然后从微调器中选择下一首歌曲并单击开始它将起作用。

public class MainActivity extends AppCompatActivity {

    Spinner sp;
    Button bstart;
    MediaPlayer mp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sp=(Spinner)findViewById(R.id.sp);
        String [] mys={"demo","democheap","demorehana"};
        ArrayAdapter<String> data=new ArrayAdapter<String>(this,R.layout.support_simple_spinner_dropdown_item,mys);
        sp.setAdapter(data);

    }

    public void code(View v)
    {
        if(sp.getSelectedItem().toString().equals("demo"))
        {
            mp=MediaPlayer.create(this,R.raw.demo);
        }
        else if(sp.getSelectedItem().toString().equals("democheap"))
        {
            mp=MediaPlayer.create(this,R.raw.democheap);
        }
        else if(sp.getSelectedItem().toString().equals("demorehana"))
        {
            mp=MediaPlayer.create(this,R.raw.demorehana);
        }

        if(v.getId()==R.id.bstart)
        {
            mp.start();
        }
    }
}
相关问题