我需要帮助在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
:所有三位玩家都在说他们正在玩,但只能听到一个... !
为什么要改变? 为什么它一旦停止工作就会起作用?
注意:
.mp3
个文件压缩为.acc
个文件(从320kbps
到144kbps
)Xamarin Studio
C#
下工作,但对于clarety purpouse,我会坚持使用小Java
个代码段。编辑1
根据这个Play two mp3 song at the same time我的解决方案应该正常工作,对吧?
答案 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();
}
}
}