I am using the mediaplayer feature on Android. I basically have songs in the raw folder and I would just like to change to a new track but it fails. One music file plays and then I press a button after or during the music playing to skip to a random track but it fails.
Current code
mediaplayer.stop();
try {
mediaplayer.prepareAysn();
mediaPlayer.selectTrack(randomtrack_num - 1);
}
catch(Exception e){}
mediaplayer.start();
The error that I receive:
MediaPlayer: start called in state 64
MediaPlayer: error (-38, 0)
MediaPlayer: Error (-38,0)
I tried this without mediaplayer.stop() and still included mediaplayer.start() at the end and it would just replay the same track again.
Am I missing something?
Please let me know.
2nd Approach
After reading the document I realized this can only be done in the prepared state which I assume in my second approach it should work but it is not.
mediaPlayer.stop();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener(){
#Override
public void onPrepared(MediaPlayer mp) {
try{
mp.selectTrack(randomtrack_num - 1);
}catch(Exception e){}
mp.start();
}
});
mediaPlayer.prepareAsync();
I get this error:/MediaPlayer: Should have subtitle controller already set
Basically the same track plays again and it does not go to the selected track.
You are calling mediaplayer.start() in wrong state. Firstly read this documentation:
https://developer.android.com/reference/android/media/MediaPlayer.html
You will have a better idea of correct implementation.
EDITED:
String[] url ; // initiliaze your URL array here
MediaPlayer myMediaPlayer = new MediaPlayer();
myMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
myMediaPlayer.setDataSource(url[0]);
myMediaPlayer.prepareAsync(); // might take long! (for buffering, etc)
} catch (IOException e) {
Toast.makeText(this, "mp3 not found", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
//mp3 will be started after completion of preparing...
myMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer player) {
player.start();
}
});
Playing different track after completions
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp)
{
myMediaPlayer.reset();
/* load the new source */
myMediaPlayer.setDataSource(url[position]);//select the path according to your need
/* Prepare the mediaplayer */
myMediaPlayer.prepareAsync();
}
Related
I have read numerous different responses on this matter but I just wanted to clarify one thing about the onCompletionListener method for MediaPlayer. I have a configuration that is currently working and playing a song after it completes the first one, but after the second one ends it will not play another song from the array. It will also not display the metadata for the new track either. My guess is that the onCompletionListener only runs once and doesn't transfer to the newly created MediaPlayer instance. More Specifically the answer I'm looking for is can the onCompleteListener run more than once? Or is it a non looping function?
Video demonstrating the issue: https://youtu.be/WXDtCktTh3M
Here is what I have for my listener block:
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
if (chosenPath == null) {
seekBar.setProgress(0);
mediaPlayer.seekTo(0);
} else {
songOrderCounter += 1;
System.out.println("SONG_ITERATOR_COUNT: " + songOrderCounter);
try {
/*handler.removeCallbacks(moveSeekBarThread);
songUpdateTimeHandler.removeCallbacks(updateSongTime);*/
Log.d("PATH_WORKING", allMusicFiles[songOrderCounter].toString());
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(allMusicFiles[songOrderCounter].toString());
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
metaRetriever();
seekBar.setProgress(0);
seekBar.setMax(mediaPlayer.getDuration());
trackTime();
}
});
mediaPlayer.prepareAsync();
metaRetriever(); /* Moved inside onPrepared*/
} catch (Exception e) {
System.out.println("NEXT_SONG_FAILED: " + e);
}
}
}
});
UPDATE
The reason this is not working is because I have created a new MediaPlayer Instance in the onCompletion() function so the listener will not associate with the newly created MediaPlayer instance. Therefore it will not listen for the completion of the newly created MediaPlayer. I removed the new MediaPlayer section of code from the setOnCompleteListener() function and now there are issues with the runnable threads that are keeping track of seekbar and time progress causing it to crash when it reaches the end of the file
D/PATH_WORKING: /storage/emulated/0/Music/01 Control.mp3
I/System.out: NEXT_SONG_FAILED: java.lang.IllegalStateException
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.macyg.androidmediaplayer, PID: 12784
java.lang.IllegalStateException
at android.media.MediaPlayer.getCurrentPosition(Native Method)
at com.example.macyg.androidmediaplayer.MainActivity$12.run(MainActivity.java:596)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
And the Runnable causing the crash:
private Runnable moveSeekBarThread = new Runnable() {
public void run() {
if(mediaPlayer.getCurrentPosition() <= mediaPlayer.getDuration()) {
int mediaPos_new = mediaPlayer.getCurrentPosition();
int mediaMax_new = mediaPlayer.getDuration();
seekBar.setMax(mediaMax_new);
seekBar.setProgress(mediaPos_new);
handler.postDelayed(this, 100); //Looping the thread after 0.3 second
// seconds
}else{}
}
};
I have tried to play many audio (mp3) files through MediaPlayer's setAudioStreamType(AudioManager.STREAM_VOICE_CALL); but mp.start(); does not play nor does it throw an exception.
The setup works with SoundPool but it is limited to like 5 seconds, some files playing upto 8 seconds.
I am attaching the part of code here:
String s = absolutepath.get(position);
Uri u = Uri.parse(s);
playing = (MediaPlayer) MediaPlayer.create(MainActivity.this, u);
playing.setOnPreparedListener(this);
onPrepared includes this:
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
spProgress.cancel();
mp.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
try {
mp.start();
} catch (IllegalStateException e) {
Toast.makeText(this, "exception", Toast.LENGTH_SHORT).show();
}
}
I have tried this without the try/catch and even without listener. The only time it plays is when I don't use the stream type STREAM_VOICE_CALL.
The same files can be played with SoundPool:
SoundPool sp = new SoundPool(1, AudioManager.STREAM_VOICE_CALL, 0);
sp.load(s, 1);
sp.setOnLoadCompleteListener(this);
Listener:
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
// TODO Auto-generated method stub
if (status == 0) {
spProgress.cancel();
sp.play(sampleId, 1, 1, 1, 0, 1);
} else {
Toast.makeText(this, "failed to load", Toast.LENGTH_SHORT).show();
}
}
I actually had the same problem, and Google's Guide is very bad here - it's indeed a bit tricky, but simple to explain:
As you need to change the STREAM, and then prepare() your MediaPlayer again, you'll get it working by doing this:
Resources res = getResources();
AssetFileDescriptor afd = res.openRawResourceFd(R.raw.tts_a);
mp = new MediaPlayer();
//mp.reset();
mp.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
mp.setLooping(false);
try {
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mp.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mp.start();
The actual trick is to NOT use the MediaPlayer.create, as it's calling the prepare itself! Therefore you're not able to set the Stream. By setting the File with AssetFileDescriptor, you can set the Stream and call your prepare() afterwards!
i am using the MediaPlayer class to loop music from youtube. So far no problem, but the MediaPlayer downloads the video every playback again from youtube, which causes a lot of traffic. Is there a way to let the video in the buffer of the MediaPlayer?
I'm using the following code:
try {
MediaPlayer mp = new MediaPlayer();
mp.setDataSource("http://r6---sn-4g57knsy.googlevideo.com/videoplayback?itag=18&key=yt5&ip=123.45.67.89&ipbits=0&ratebypass=yes&ms=au&source=youtube&sver=3&mt=1383664037&id=3fa390e8443132e0&expire=1383690428&sparams=gcr%2Cid%2Cip%2Cipbits%2Citag%2Cratebypass%2Csource%2Cupn%2Cexpire&fexp=935610%2C932206%2C916807%2C941242%2C916623%2C924616%2C907231%2C907240&mv=m&gcr=de&upn=9y98yq_WFEc&signature=98E548B5E368061D425FED483828E6D5AF1BBC2B.8AB359B7BA604F108D85578BC704844308E9B6EB");
mp.setLooping(true);
mp.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
mp.prepare();
} catch (Exception e) {
e.printStackTrace();
}
Thanks.
Short answer: no.
Long answer: write a simple proxy server to run on the device and cache it yourself. It's not incredibly hard, but it requires some thought to pull off seemlessly.
I'm a Beginner in android programming and I want to programming mp3 app to call some mp3 files from URL, so when I show "Media Player" in android developer I put the URL in the setDataSource and it's work fine, but the problem is the Activity take a lot of time to display it and in the sometimes app will be crashed. This is the part of my code :
file_url = Mp3_Linkes[num];
//Set Source
try {
mp.setDataSource(file_url);
} catch (Exception e) {
Toast.makeText(this, "Source Error !!", Toast.LENGTH_LONG).show();
}
//Prepare
try {
mp.prepare();
}catch(Exception e)
{
Toast.makeText(this, "Prepare Error !!", Toast.LENGTH_LONG).show();
}
//Start
mp.start();
Your activity is blocking because you are calling prepare on your Main Thread (UI thread)
Instead You can use prepareAsynch and OnPreparedListener to start specially when loading from remote source:
code :
try {
mp.setDataSource(file_url);
mp.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer player) {
player.start();
}
});
mp.prepareAsync();
I am trying to make music play in my app and have a song play after the first one has finished but i get some errors that i cannot resolve any help?
public class Music {
int count;
String[] titles = new String[] { "title1.mp3", "title2.mp3", "title3.mp3", "title4.mp3" };
public void GameMusic(){
count = 0;
MediaPlayer mp = MediaPlayer.create(this, R.raw.title1);
mp.start();
}
void onCompletion(MediaPlayer mp){
mp.stop();
if (count == titles.length -1) {
count = 0;
}
mp.setDataSource(titles[count]);
count++;
mp.prepare();
mp.start();
}
}
The errors are on:
MediaPlayer mp = MediaPlayer.create(this, R.raw.music);
(The method create(Context, int) in the type MediaPlayer is not applicable for the arguments (Music, int)
mp.setDataSource(titles[count]);
(Unhandled exception type IOException)
mp.prepare();
(Unhandled exception type IOException)
Any help would be appreciated.
Well the errors might be a little cryptic but they are self-explanatory.
You need to pass a Context to GameMusic() and use it to initialize MediaPlayer:
public void GameMusic(Context context){
count = 0;
MediaPlayer mp = MediaPlayer.create(context, R.raw.title1);
mp.start();
}
this only works if the class (in this case Music) extends Context, so you need to provide a Context another way.
And in onCompletion() use a try-catch block to handle the IOException:
try {
mp.setDataSource(titles[count]);
count++;
mp.prepare();
mp.start();
}
catch(IOException e) {
// Do something when MediaPlayer fails
}
Your Music Class is just a class and not an activity and hence the this passes an object and not a context. If this is your only music player class then you need it to extend Activity else you need to pass a context to it.
public void GameMusic(Context context){
count = 0;
MediaPlayer mp = MediaPlayer.create(context, R.raw.title1);
mp.start();
}
And for the other two exceptions, it states that the exceptions are unhandled. so you need to use a Try-Catch block the handle the uncaught IOException.
That should solve all the errors that you are getting now.
when setting the datasource to Mediaplayer try to use absolutepath of the music file
if it is stored in sd-card means ..try this
String ExternalStorageDirectoryPath = Environment.getExternalStorageDirectory()
.getAbsolutePath();
mp.setDataSource(ExternalStorageDirectoryPath +"/"+titles[count]);
after calling the
mp.prepare();
implement the onpreparedlistner ,after get the notification for this then start the mediaplayer
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
and handle the all kind of exception, so that u can easily track the issues.