I'm creating an audio playback application. I've currently just got two tracks added but eventually I need to add many more... I've currently created two different mediaplayers to run both the tracks, however as the number of tracks will increase using this procedure will lead to problems and lack of performance!
Is there some way I can code this better and more generically?
Here's the java code
public class ChantsFragment extends Fragment {
TextView text1, text2
ImageButton play1, play2, pause1, pause2, repeatoff1, repeatoff2, repeaton1, repeaton2, stop1, stop2;
MediaPlayer mediaPlayer1, mediaPlayer2;
Toast on, off;
public ChantsFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_chants, container, false);
play1 = (ImageButton) view.findViewById(R.id.play1);
play2 = (ImageButton) view.findViewById(R.id.play2);
pause1 = (ImageButton) view.findViewById(R.id.pause1);
pause2 = (ImageButton) view.findViewById(R.id.pause2);
repeatoff1 = (ImageButton) view.findViewById(R.id.repeatoff1);
repeatoff2 = (ImageButton) view.findViewById(R.id.repeatoff2);
repeaton1 = (ImageButton) view.findViewById(R.id.repeaton1);
repeaton2 = (ImageButton) view.findViewById(R.id.repeaton2);
stop1 = (ImageButton) view.findViewById(R.id.stop1);
stop2 = (ImageButton) view.findViewById(R.id.stop2);
mediaPlayer1 = MediaPlayer.create(getActivity(), R.raw.audio1);
mediaPlayer2 = MediaPlayer.create(getActivity(), R.raw.audio2);
on = Toast.makeText(getActivity(), "The chant will repeat itself", Toast.LENGTH_LONG);
off = Toast.makeText(getActivity(), "The chant will no longer repeat itself", Toast.LENGTH_LONG);
//Track 1
text1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mediaPlayer1 != null && mediaPlayer1.isPlaying()) {
text1.setClickable(false);
}
if (mediaPlayer2 != null && mediaPlayer2.isPlaying()) {
mediaPlayer2.stop();
mediaPlayer2.release();
mediaPlayer2 = null;
play2.setVisibility(View.GONE);
pause2.setVisibility(View.GONE);
repeatoff2.setVisibility(View.GONE);
repeaton2.setVisibility(View.GONE);
stop2.setVisibility(View.GONE);
}
if (mediaPlayer1 == null) {
mediaPlayer1 = MediaPlayer.create(getActivity(), R.raw.audio1);
} else {
text1.setClickable(true);
mediaPlayer1.start();
play1.setVisibility(View.GONE);
pause1.setVisibility(View.VISIBLE);
repeatoff1.setVisibility(View.VISIBLE);
stop1.setVisibility(View.VISIBLE);
}
mediaPlayer1.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
play1.setVisibility(View.GONE);
pause1.setVisibility(View.GONE);
repeatoff1.setVisibility(View.GONE);
repeaton1.setVisibility(View.GONE);
stop1.setVisibility(View.GONE);
}
});
}
});
play1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
play1.setVisibility(View.GONE);
pause1.setVisibility(View.VISIBLE);
mediaPlayer1.start();
}
});
pause1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
play1.setVisibility(View.VISIBLE);
pause1.setVisibility(View.GONE);
mediaPlayer1.pause();
}
});
repeatoff1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mediaPlayer1.setLooping(true);
repeatoff1.setVisibility(View.GONE);
repeaton1.setVisibility(View.VISIBLE);
on.show();
off.cancel();
}
});
repeaton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mediaPlayer1.setLooping(false);
repeaton1.setVisibility(View.GONE);
repeatoff1.setVisibility(View.VISIBLE);
off.show();
on.cancel();
}
});
stop1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mediaPlayer1.stop();
mediaPlayer1 = null;
text1.setClickable(true);
play1.setVisibility(View.GONE);
pause1.setVisibility(View.GONE);
repeatoff1.setVisibility(View.GONE);
repeaton1.setVisibility(View.GONE);
stop1.setVisibility(View.GONE);
}
});
//Track 2
text2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mediaPlayer2 != null && mediaPlayer2.isPlaying()) {
text2.setClickable(false);
}
if (mediaPlayer1 != null && mediaPlayer1.isPlaying()) {
mediaPlayer1.stop();
mediaPlayer1.release();
mediaPlayer1 = null;
play1.setVisibility(View.GONE);
pause1.setVisibility(View.GONE);
repeatoff1.setVisibility(View.GONE);
repeaton1.setVisibility(View.GONE);
stop1.setVisibility(View.GONE);
}
if (mediaPlayer2 == null) {
mediaPlayer2 = MediaPlayer.create(getActivity(), R.raw.audio2);
} else {
text2.setClickable(true);
mediaPlayer2.start();
play2.setVisibility(View.GONE);
pause2.setVisibility(View.VISIBLE);
repeatoff2.setVisibility(View.VISIBLE);
stop2.setVisibility(View.VISIBLE);
}
mediaPlayer2.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
play2.setVisibility(View.GONE);
pause2.setVisibility(View.GONE);
repeatoff2.setVisibility(View.GONE);
repeaton2.setVisibility(View.GONE);
stop2.setVisibility(View.GONE);
}
});
}
});
play2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
play2.setVisibility(View.GONE);
pause2.setVisibility(View.VISIBLE);
mediaPlayer2.start();
}
});
pause2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
play2.setVisibility(View.VISIBLE);
pause2.setVisibility(View.GONE);
mediaPlayer2.pause();
}
});
repeatoff2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mediaPlayer2.setLooping(true);
repeatoff2.setVisibility(View.GONE);
repeaton2.setVisibility(View.VISIBLE);
on.show();
off.cancel();
}
});
repeaton2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mediaPlayer2.setLooping(false);
repeaton2.setVisibility(View.GONE);
repeatoff2.setVisibility(View.VISIBLE);
off.show();
on.cancel();
}
});
stop2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mediaPlayer2.stop();
mediaPlayer2 = null;
text2.setClickable(true);
play2.setVisibility(View.GONE);
pause2.setVisibility(View.GONE);
repeatoff2.setVisibility(View.GONE);
repeaton2.setVisibility(View.GONE);
stop2.setVisibility(View.GONE);
}
});
return view;
}
Edit
I've currently zeroed down on adding around 10 tracks to the application. I want playback to stop on the current track (if playing) the moment another track is selected and using media player to do the same would mean checking separately if 9 media players are playing! (Unless of course there's another way to do this which I've completely missed)
Well, for playing multiple audio files at once, SoundPool seems to be your best choice mainly because its much more lightweight and you can control the number of streams. You can create a new SoundPool instance as:
SoundPool soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 100); // 10 = maxStreams, 100 = quality
You can then start loading different sounds into it as:
int soundId1 = soundPool.load(context, R.raw.audio1, 1);
int soundId2 = soundPool.load(context, R.raw.audio2, 1);
...
You can control playback as:
int idBeingPlayed = soundPool.play (soundID, 1, 1, 1, -1, 1); // volume params, returns the streamId
Other controls:
soundPool.pause(streamID);
soundPool.resume(streamID);
For more info, visit the offfical docs. Hope this helps!
Related
I am trying to make a sound wait to play if another sound is currently playing. But, the code I wrote doesn't execute.
public class Transportation extends AppCompatActivity {
private MediaPlayer sound,sound1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.transportation);
sound = MediaPlayer.create(this,R.raw.vatunabus);
final ImageView imageView= (ImageView)findViewById(R.id.vatunabussound);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(sound1.isPlaying()){
sound.stop();
sound.release();
}
else if(sound.isPlaying()){
sound.pause();
}
else {
sound.start();
}
}
});
sound1 = MediaPlayer.create(this,R.raw.varowlsanabus);
final ImageView imageView1 = (ImageView)findViewById(R.id.firstbussound);
imageView1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(sound.isPlaying()){
sound1.stop();
sound1.release();
}
else if(sound1.isPlaying()){
sound1.pause();
}
else {
sound1.start();
}
}
});
}
}
I have two ImageViews with different sounds which plays sound when clicked on one of them. When click on the first ImageView I want the sound to play and before the first ImageView finish playing the sound, if the second ImageView is click, I want to restrict the second ImageView to play a sound because the first ImageView is still playing the sound. In fact, I want to restrict a sound to play when another sound is playing. But, I didn't get the desired result.
public class Transportation extends AppCompatActivity {
private MediaPlayer sound,sound1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.transportation);
sound = MediaPlayer.create(this,R.raw.vatunabus);
final ImageView imageView= (ImageView)findViewById(R.id.vatunabussound);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(sound1.isPlaying()){
sound.stop();
sound.release();
}
else if(sound.isPlaying()){
sound.pause();
imageView.setBackgroundResource(R.mipmap.playicon);
}
else {
sound.start();
imageView.setBackgroundResource(R.mipmap.pauseicon);
}
}
});
sound.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
imageView.setBackgroundResource(R.mipmap.playicon);
}
});
sound1 = MediaPlayer.create(this,R.raw.varowlsanabus);
final ImageView imageView1 = (ImageView)findViewById(R.id.firstbussound);
imageView1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(sound.isPlaying()){
sound1.stop();
sound1.release();
}
else if(sound1.isPlaying()){
sound1.pause();
imageView1.setBackgroundResource(R.mipmap.playicon);
}
else {
sound1.start();
imageView1.setBackgroundResource(R.mipmap.pauseicon);
}
}
});
sound1.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
imageView1.setBackgroundResource(R.mipmap.playicon);
}
});
}
}
Here's an idea, let's create a boolean value to tell us if a sound is currently playing.
private MediaPlayer sound,sound1;
private boolean soundPlaying = false; //new boolean variable
Next, before playing a sound, we'll check to make sure it's still false:
public void onClick(View v) {
//Add a check that exits the function if a sound is playing
//Add this check in both onClick methods
if(soundPlaying){
return;
}
...
}
Also, after sound.start() and sound1.start(), let's set the boolean to true:
soundPlaying = true;
Finally, in both instances of the onCompletion methods, let's reset the boolean to false:
public void onCompletion(MediaPlayer mp) {
soundPlaying = false;
...
}
The final code will look like this:
public class Transportation extends AppCompatActivity {
private MediaPlayer sound,sound1;
private boolean soundPlaying = false; //new boolean variable
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.transportation);
sound = MediaPlayer.create(this,R.raw.vatunabus);
final ImageView imageView= (ImageView)findViewById(R.id.vatunabussound);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Add a check that exits the function if a sound is playing
if(soundPlaying){
return;
}
if(sound1.isPlaying()){
sound.stop();
sound.release();
}
else if(sound.isPlaying()){
sound.pause();
imageView.setBackgroundResource(R.mipmap.playicon);
}
else {
sound.start();
imageView.setBackgroundResource(R.mipmap.pauseicon);
}
}
});
sound.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
soundPlaying = false;
imageView.setBackgroundResource(R.mipmap.playicon);
}
});
sound1 = MediaPlayer.create(this,R.raw.varowlsanabus);
final ImageView imageView1 = (ImageView)findViewById(R.id.firstbussound);
imageView1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Add a check that exits the function if a sound is playing
if(soundPlaying){
return;
}
if(sound.isPlaying()){
sound1.stop();
sound1.release();
}
else if(sound1.isPlaying()){
sound1.pause();
imageView1.setBackgroundResource(R.mipmap.playicon);
}
else {
sound1.start();
imageView1.setBackgroundResource(R.mipmap.pauseicon);
}
}
});
sound1.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
soundPlaying = false;
imageView1.setBackgroundResource(R.mipmap.playicon);
}
});
}
}
I hope this helps. Couldn't try it in live code though, so let me know how it goes.
This is part of the code in my MainActivity.
stopwatch1 is an image button called in MainActivity:
stopwatch1 = (ImageButton)findViewById(R.id.stopwatch1);
I have tried searching for clues on how to use dialog.setOnDismissListener, however, there aren't proper answers to help me with the killing of the audio after deliberate or accidental exit of the dialog. Any help would be appreciated.
stopwatch1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Dialog mmDialog1 = new Dialog(context);
mmDialog1.setContentView(R.layout.countdowntimer);
mmDialog1.setTitle("Stop-watch");
Button ddButton1 = (Button) mmDialog1.findViewById(R.id.countdown_exit);
final Button ddButton2 = (Button) mmDialog1.findViewById(R.id.countdown_start);
final TextView timeview = (TextView) mmDialog1.findViewById(R.id.timeview);
ddButton2.setTag(1);
ddButton2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
final int status = (Integer) v.getTag();
if (status == 1) {
ddButton2.setText("Stop");
countDownTimer = new CountDownTimer(60000, 1000) {
public void onTick(long millisUntilFinished) {
int time = (int) (millisUntilFinished/1000);
timeview.setText(Integer.toString(time));
}
#Override
public void onFinish() {
timeview.setText("60");
ddButton2.setText("Start");
MediaPlayer stop = MediaPlayer.create(context, R.raw.stop);
stop.start();
}
}.start();
v.setTag(0);
} else {
ddButton2.setText("Start");
timeview.setText("60");
countDownTimer.cancel();
v.setTag(1);
}
}
});
ddButton1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mmDialog1.dismiss();
}
});
mmDialog1.show();
}
});
My suggestion would be to implement an interface. When the dialog closes, have the callback shut off the media player.
A quick example is this.
interface
public interface DialogClosed {
void shutDownMediaPlayer();
}
then implement the interface in the calling activity
activity
public class MainActivity extends Activity implements DialogClosed {
....
#Override
public void shutDownMediaPlayer() {
//shut down media player here
}
}
Also, you may add a boolean to check if the dialog is showing like this
boolean isShowing = mDialog.isShowing();
and then you can just shut off the media player at any point if this is false.
So I've used some pointers from Jawascript and also edited my code a little, now it works:
stopwatch1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Dialog mmDialog1 = new Dialog(context);
mmDialog1.setContentView(R.layout.countdowntimer);
mmDialog1.setTitle("Stop-watch");
Button ddButton1 = (Button) mmDialog1.findViewById(R.id.countdown_exit);
final Button ddButton2 = (Button) mmDialog1.findViewById(R.id.countdown_start);
final TextView timeview = (TextView) mmDialog1.findViewById(R.id.timeview);
final MediaPlayer stop = MediaPlayer.create(context, R.raw.stop);
ddButton2.setTag(1);
mmDialog1.setCancelable(false);
if (mmDialog1.isShowing() == false) {
stop.stop();
}
ddButton2.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
final int status = (Integer) v.getTag();
if (status == 1) {
ddButton2.setText("Stop");
countDownTimer = new CountDownTimer(60000, 1000) {
public void onTick(long millisUntilFinished) {
int time = (int) (millisUntilFinished/1000);
timeview.setText(Integer.toString(time));
}
#Override
public void onFinish() {
timeview.setText("60");
ddButton2.setText("Start");
try {
stop.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
stop.start();
}
}.start();
v.setTag(0);
} else {
ddButton2.setText("Start");
timeview.setText("60");
countDownTimer.cancel();
v.setTag(1);
stop.stop();
}
}
});
ddButton1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mmDialog1.dismiss();
}
});
mmDialog1.show();
}
});
I am making an app in which there are many images and audio. All I want to do is apply a loop for these images and audio so that when an image gets displayed the audio will get played, i.e. image1=audio1, image2=audio2. There are next and previous buttons in my app. Next will display the next image and audio, previous will display previous one. Should I use a for loop? or switch case? I have tried this code. But when the images and audio array comes to an end I want to start all over again. Please help.
public class MainActivity extends Activity {
int i=1;
MediaPlayer mediaplayer;
int image = 0;
int sound ;
int [] sounds;
int [] audio;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sounds = new int [] {
R.raw.audio_one, R.raw.audio_two, R.raw.audio_three, R.raw.audio_four
};
mediaplayer = MediaPlayer.create(this, sounds[0]);
mediaplayer.start();
final int [] images = {
R.drawable.num1, R.drawable.num2, R.drawable.num3, R.drawable.num4
};
ImageButton next = (ImageButton)findViewById(R.id.imageButton1);
ImageButton prev = (ImageButton)findViewById(R.id.imageButton2);
final ImageView img1 = (ImageView)findViewById(R.id.imageView2);
final ImageView img2 = (ImageView)findViewById(R.id.imageView3);
next.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(image==3){
}
else {
image++;
}
i=image;
audio(i);
mediaplayer.start();
img1.setImageResource(images[image]);
}
});
prev.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (image<=0){
img1.setImageResource(R.drawable.num1);
}
else
{
image--;
}
i=image;
audio(i);
mediaplayer.start();
img1.setImageResource(images[image]);
}
});
}
public void audio(int a)
{
mediaplayer = MediaPlayer.create(this, sounds[a]);
return;
}
}
use the following code...
next.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(image== images.lenght()-1){
image=0;
}
else {
image++;
}
i=image;
audio(i);
mediaplayer.start();
img1.setImageResource(images[image]);
}
});
prev.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (image==0){
img1.setImageResource(R.drawable.num1);
}
else
{
image--;
}
i=image;
audio(i);
mediaplayer.start();
img1.setImageResource(images[image]);
}
});
}
I need a button that will start when pressed and stop when pressed again. Otherwise I have overlapping sounds. Can any of you assist me with the code please? Below is what I currently have and can't get the button to stop when clicked again so currently it is just playing and stops when the sound is done causing sounds to overlap. Getting one to stop when another is pressed would also be ideal but I don't have a clue how to easily incorporate this.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_boardone);
Button one = (Button) findViewById(R.id.button1);
one.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer mp = MediaPlayer.create(BoardoneActivity.this, R.raw.mouse_laughter);
mp.start();
}
});
Button two = (Button) findViewById(R.id.button2);
two.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer mp = MediaPlayer.create(BoardoneActivity.this, R.raw.evil_laugh);
mp.start();
}
});
Dont use two objects of Media Player. Bleow is the snippet of methods from my project. If any error let me know.
private MediaPlayerManager mRecordingPlayer = null;
private void initAudioPlayer(){
if(mRecordingPlayer == null){
mRecordingPlayer = new MediaPlayerManager();
}
}
private void playMusic(int position){
initAudioPlayer();
mRecordingPlayer.resetPlayer();
mRecordingPlayer.setupPlayback("your reasource");
mRecordingPlayer.startPlaying();
}
private void stopPlaying(){
initAudioPlayer();
if(mRecordingPlayer.isPlaying()){
mRecordingPlayer.pausePlaying();
}
}
#Override
public void onPause() {
clearAudioPlayer();
super.onPause();
}
private void clearAudioPlayer(){
if(mRecordingPlayer != null ){
mRecordingPlayer.resetPlayer();
}
}
#Override
public void onClick(View view) {
boolean on = ((ToggleButton) view).isChecked();
if(on){
playMusic("play music");
((ToggleButton) view).setChecked(true);
}else{
stopPlaying();
}
}
Try it with below code.
mPlayPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if (mp.isPlaying()) {
if (mp != null) {
mp.pause();
mPlayPause.setText("Play");
}
} else {
if (mp != null) {
mp.start();
mPlayPause.setText("Pause");
}
}
}
});