I generate midi files on the go. I want to play these files continuously.
I initialise a mediaplayer and start song1.mid. Then I use the following code to play song2.mid
// set on completion listener music file
mediaPlayer
.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
String filePath2 = null;
File file = null;
FileInputStream inputStream = null;
//set the filePath
try {
filePath2 = getCacheDir() + "/optimuse" + song + ".mid";
file = new File(filePath2);
if (file.exists()) {
inputStream = new FileInputStream(file);
if (inputStream.getFD().valid()) {
System.out.println("Valid!");
}
}
} catch (Exception e1) {
e1.printStackTrace();
System.exit(-1);
}
//set Mediaplayer's datasource
if (file.exists()) {
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(inputStream.getFD());
inputStream.close();
} catch (Exception e1) {
e1.printStackTrace();
System.exit(-1);
}
try {
mediaPlayer.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//if the player is not running
if (!mediaPlayer.isPlaying()) {
//start the player
mediaPlayer.start();
Toast.makeText(MainActivity.this,
"mediaPlayer.start()", Toast.LENGTH_LONG)
.show();
}
}
});
}
});
The problem is that the mediaplayer stops after song2. But I want song3 to start. I can increment the global variable, ok. But the onCompletionListener does not seem to work when the second song finishes.
I guess I should initialise MediaPlayer mp to have an onCompletionListener too? Not sure what the best approach is.
Or should I do something like:
new class MediaPlayer implements OnCompletionListener(){
#Override
song++;
//code to start the mediaplayer
}
Thank you for putting me in the right direction. I am also a little bit concerned with efficiency, when I keep starting up new mediaplayers...
Basically, what I want to do is play song1.mid, song2.mid,... continuously, but the files are generated during the program.
EDIT
Thanks to the wonderful help of #Gan. I know have the following working code:
// set on completion listener music file
mediaPlayer
.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
String filePath2 = null;
File file = null;
FileInputStream inputStream = null;
//set the filePath
try {
filePath2 = getCacheDir() + "/optimuse" + song + ".mid";
file = new File(filePath2);
if (file.exists()) {
inputStream = new FileInputStream(file);
if (inputStream.getFD().valid()) {
System.out.println("Valid!");
}
}
} catch (Exception e1) {
e1.printStackTrace();
System.exit(-1);
}
//set Mediaplayer's datasource
if (file.exists()) {
try {
mp.stop();
mp.reset();
mp.setDataSource(inputStream.getFD());
inputStream.close();
} catch (Exception e1) {
e1.printStackTrace();
System.exit(-1);
}
try {
mp.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//if the player is not running
if (!mp.isPlaying()) {
//start the player
mp.start();
Toast.makeText(MainActivity.this,
"mp.start()", Toast.LENGTH_LONG)
.show();
}
}
});
}
});
store the source locations in an array and in the onCompletionListener cycle through the source. something like this (use the same media player instance)
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp)
{
if(currentPosition<sourceArray.size())
{
mediaPlayer.reset();
/* load the new source */
mediaPlayer.setDataSource(sourceArray[position]);
/* Prepare the mediaplayer */
mediaPlayer.prepare();
/* start */
mediaPlayer.start();
}
else
{
/* release mediaplayer */
mediaPlayer.release();
}
}
Related
i have many Imageviews to play sound when clicked and i managed to play it.
but the problem that when i want to click on another image which supposed to play another sound, it stops the sound but i can't resume if it was clicked on the same play button.
Here is the code I've managed to get it to work so far:
audio1 = (ImageView) popupView.findViewById(R.id.lesson1_audio_gramar_1);
assert audio1 != null;
audio1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mMediaPlayer == null) {
mMediaPlayer = MediaPlayer.create(Lesson1Activity.this, R.raw.lesson1);
}
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
audio1.setImageResource(R.drawable.ic_play_circle_filled_black_48dp);
try {
mMediaPlayer.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
mMediaPlayer.start();
audio1.setImageResource(R.drawable.ic_pause_circle_filled_black_48dp);
mMediaPlayer.setOnCompletionListener(mCompletionListener);
}
}
});
audio2 = (ImageView) popupView.findViewById(R.id.lesson1_audio_gramar_2);
assert audio2 != null;
audio2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mMediaPlayer == null) {
mMediaPlayer = MediaPlayer.create(Lesson1Activity.this, R.raw.lesson2);
}
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
audio2.setImageResource(R.drawable.ic_play_circle_filled_black_48dp);
try {
mMediaPlayer.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
mMediaPlayer.start();
audio2.setImageResource(R.drawable.ic_pause_circle_filled_black_48dp);
mMediaPlayer.setOnCompletionListener(mCompletionListener);
}
}
});
To play another track, follow this simple steps:
if (mediaPlayer != null) {
if(mediaPlayer.isPlaying()){
mediaPlayer.stop();
mediaPlayer.reset()
mediaPlayer.setDataSource(new music to play);
mediaPlayer.prepare();
}
}
Then call mediaPlayer.start() in the onPrepared() method
I have written a mediaPlayer Application and in that mediaplayer.setOnCompletionListener is called before the completion of song and it goes on for every song...It's keep on going to next song until it reaches the last song in playList... Please Help
Here is my code:
tracksListViewForSpeakers.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
Track track = playlistContents.get(position);
String filepath = track.getFilePath();
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(filepath);
mediaPlayer.start();
// mediaPlayer.setVolume(0, 0);
} catch (IOException e) {
e.printStackTrace();
for(int i=0;i<4;i++)
System.out.println("MediaPlayer Exception");
}
}
});
Completion Listener
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
onNextClicked(mp);
}
});
OnNextClickedMethod
public void onNextClicked(MediaPlayer mp){
int val = myModel.getCurrentPlayingIndex();
val=val+1;
Track track = currentPlayList.get(val);
String filepath = track.getFilePath();
if (mp.isPlaying()) {
mp.stop();
}
mp.reset();
try {
mp.setDataSource(filepath);
mp.start();
// mediaPlayer.setVolume(0, 0);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Use This To Play Next Song On Completion
#Override
public void onCompletion(MediaPlayer arg0) {
if (isRepeat) {
// repeat is on play same song again
playSong(currentSongIndex);
} else if (isShuffle) {
// shuffle is on - play a random song
Random rand = new Random();
currentSongIndex = rand.nextInt((songsList.size() - 1) - 0 + 1) + 0;
playSong(currentSongIndex);
} else {
// no repeat or shuffle ON - play next song
if (currentSongIndex < (songsList.size() - 1)) {
playSong(currentSongIndex + 1);
currentSongIndex = currentSongIndex + 1;
} else {
// play first song
playSong(0);
currentSongIndex = 0;
}
}
}
Then playsong method is like this
public void playSong(int songIndex){
// Play song
try {
mp.reset();
mp.setDataSource(songsList.get(songIndex).get("songPath"));
mp.prepare();
mp.start();
// Displaying Song title
String songTitle = songsList.get(songIndex).get("songTitle");
songTitleLabel.setText(songTitle);
// Changing Button Image to pause image
btnPlay.setImageResource(R.drawable.btn_pause);
// set Progress bar values
songProgressBar.setProgress(0);
songProgressBar.setMax(100);
// Updating progress bar
updateProgressBar();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
or u can see this tutorial and implement this
http://www.androidhive.info/2012/03/android-building-audio-player-tutorial/
try like this
//set path
mediaPlayer.setDataSource("yourFilePath");
mediaPlayer.setOnPrepareListener(new OnPrepareListener(MediaPlayer mediaPlayer) {
mediaPlayer.start();
});
mediaPlayer.prepareAsync();
don't call start() without prepareAsync();
Hope it will solve your problem..
So I'm trying to take multiple pictures at regular time intervals, however I get a "takePicture Failed" Exception after the first picture is previewed on the surfaceView.
Here's my takePictures() method which is called when a button is pressed:
public void takePictures() {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
camera = Camera.open();
if (camera != null) {
try {
camera.setPreviewDisplay(surfaceView.getHolder());
camera.startPreview();
camera.takePicture(null, null, new CustomPictureCallbcak(this, cacheDir, imageView, 3, 5000));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
else {
Toast.makeText(this, "No camera found.", Toast.LENGTH_SHORT).show();
}
}
And here's the onPictureTaken() method of CustomPictureCallback :
#Override
public void onPictureTaken(byte[] data, Camera camera) {
//get date info for file name
SimpleDateFormat sdf = new SimpleDateFormat("ddmmyyyyhhmmss");
String date = sdf.format(new Date());
String fileDir = createImageFileName(date);
//write the image to cache
writeImageToCache(fileDir, data);
//display file name in a toast notification
Toast.makeText(c, fileDir, Toast.LENGTH_SHORT).show();
//show picture on imageview
imageView.setImageBitmap(BitmapFactory.decodeByteArray(data, 0, data.length));
//retake images
this.camera = camera;
while (numOfImagesAlreadyTaken <= numOfImages) {
Thread thread = new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
numOfImagesAlreadyTaken++;
CustomPictureCallbcak.this.camera.stopPreview();
sleep(delay);
CustomPictureCallbcak.this.camera.takePicture(null, null, CustomPictureCallbcak.this);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
Toast.makeText(c, "Total images taken: " + numOfImagesAlreadyTaken, Toast.LENGTH_SHORT).show();
//release camera
camera.release();
camera = null;
}
As Aleksander Lidtke suggested, I created a single thread inside my takePictures() method and put a while loop inside it:
public void takePictures(final int numOfPictures, final int delay) {
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Thread thread = new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
while (numOfPicturesAlreadyTaken <= numOfPictures) {
try {
camera = Camera.open();
camera.setPreviewDisplay(surfaceView.getHolder());
camera.startPreview();
camera.takePicture(null, null, new CustomPictureCallbcak(MainActivity.this, cacheDir, imageView));
numOfPicturesAlreadyTaken++;
sleep(delay);
}
catch (Exception e) {
e.printStackTrace();
Log.d("TEST", e.getMessage());
}
}
}
};
thread.start();
}
else {
Toast.makeText(this, "No camera found.", Toast.LENGTH_SHORT).show();
}
}
In one of my activity, there is a button to play music using mediaPlayer. Also it has an option to play the music in background or stop when the activity is finished.
I use this code for that.
#Override
protected void onStop() {
super.onStop();
SharedPreferences perfs = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
if (!perfs.getBoolean("bg_play", true)) {
mediaPlayer.stop();
mediaPlayer.release();
}
}
That works perfectly. Now the problem is when the user is back on the activity and press the play button, it starts a new mediaPlayer and play the new music. I want to stop the previous music running in background when new music is started.
Here is my code
private void myMediaPlayer() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
else {
mediaPlayer.stop();
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(Environment.getExternalStorageDirectory()+"file.mp3");
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
mediaPlayer.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.start();
}
}
And the MediaPlayer declaration
MediaPlayer mediaPlayer=new MediaPlayer();
before onCreate
I'm a beginner to programing so I might be wrong. .. Wouldn't making the mefiaPlayer variable static work? But I think the problem is that when you go back to the activity, the activity is being rebuilt.
I published an app recently, and users are reporting crashes because my program included the method setNextMediaPlayer(). I now realize that this only works for API 16+, and my app supports API 8+. I was wondering if there is an alternate way of achieving the same effect.
My app has some text to speech, and what I was doing was creating an ArrayList of MediaPlayers that each had a short sound file, and then playing them one after an other. If I remove this method from the code, the audio becomes too choppy to understand.
I was thinking about using the SoundPool class, but there is no OnCompleteListener, so I'm not sure how I would do it.
So basically my question is: Is there a way to transition seamlessly between audio files without using the setNextMediaPlayer() method?
Thanks very much for your time!
EDIT
I added this code that I found
private class CompatMediaPlayer extends MediaPlayer implements OnCompletionListener {
private boolean mCompatMode = true;
private MediaPlayer mNextPlayer;
private OnCompletionListener mCompletion;
public CompatMediaPlayer() {
try {
MediaPlayer.class.getMethod("setNextMediaPlayer", MediaPlayer.class);
mCompatMode = false;
} catch (NoSuchMethodException e) {
mCompatMode = true;
super.setOnCompletionListener(this);
}
}
public void setNextMediaPlayer(MediaPlayer next) {
if (mCompatMode) {
mNextPlayer = next;
} else {
super.setNextMediaPlayer(next);
}
}
#Override
public void setOnCompletionListener(OnCompletionListener listener) {
if (mCompatMode) {
mCompletion = listener;
} else {
super.setOnCompletionListener(listener);
}
}
#Override
public void onCompletion(MediaPlayer mp) {
if (mNextPlayer != null) {
// as it turns out, starting a new MediaPlayer on the completion
// of a previous player ends up slightly overlapping the two
// playbacks, so slightly delaying the start of the next player
// gives a better user experience
SystemClock.sleep(50);
mNextPlayer.start();
}
mCompletion.onCompletion(this);
}
}
But now how do I add the audio files? I tried this:
// assigns a file to each media player
mediaplayers = new ArrayList<CompatMediaPlayer>();
for (int i = 0; i < files.size(); i++) {
mediaplayers.add((CompatMediaPlayer) CompatMediaPlayer.create(this, files.get(i)));
}
but am getting a class cast exception because MediaPlayer cannot be casted to CompatMediaPlayer.
Create Compat player that will work with onCompletionListener to start the next player like:
public void onCompletion(MediaPlayer mp) {
if (mCompatMode && mNextPlayer != null) {
mNextPlayer.prepare();
mNextPlayer.start();
}
}
Somewhere in your constructor check if there is method (or check SDK version) named "setNextMediaPlayer"
mCompatMode = Build.VERSION.SDK_INT < 16;
Define method like this one:
public void setNextMediaPlayer(MediaPlayer next) {
if (mCompatMode) {
mNextPlayer = next;
} else {
super.setNextMediaPlayer(next);
}
}
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
mediaPlayer = new MediaPlayer();
try {
AssetFileDescriptor descriptor = context.getAssets().openFd("play1.mp3");
mediaPlayer.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
descriptor.close();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.start();
MediaPlayer md = new MediaPlayer();
try {
AssetFileDescriptor descriptor = context.getAssets().openFd("play2.mp3");
md.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
descriptor.close();
md.setAudioStreamType(AudioManager.STREAM_MUSIC);
md.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.setNextMediaPlayer(md);
MediaPlayer md1 = new MediaPlayer();
try {
AssetFileDescriptor descriptor = context.getAssets().openFd("play3.mp3");
md1.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
descriptor.close();
md1.setAudioStreamType(AudioManager.STREAM_MUSIC);
md1.prepare();
} catch (IOException e) {
e.printStackTrace();
} md.setNextMediaPlayer(md1);