I am streaming a live .mp3 from an online source. The problem is that between prepareAsync() and onPrepared(), almost 1 minute passes. That means that prepareAsync is taking upwards of 1 minute to prepare before playback can start. The code is below:
void start1(String a){
mp.setDataSource(a);
mp.setOnPreparedListener(this);
mp.prepareAsync();
running=true;
}catch(Exception e){
noerror=false;
}
}
#Override
public void onPrepared(MediaPlayer mp1){
Log.d("in here2","okay");
//mp.start();
Log.d("in here2","okay");
}
This is happening in emulator. Is there something wrong with the code?
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 am making a voice recording android app. The problem is that when I want to pause and continue the record it does not work and the app crashes. This is code :
buttonPause.setOnClickListener(new View.OnClickListener() {
#TargetApi(Build.VERSION_CODES.N)
#Override
public void onClick(View view) {
try {
recording=false;
mediaRecorder.pause();
recording=false;
buttonRecord.setBackgroundResource(R.drawable.record);
Toast.makeText(getActivity(), "Recording pause",
Toast.LENGTH_LONG).show();
}catch (Exception e){
}
and this appears on log
enter image description here
Please add the log of the Error, or it's impossible to help you.
The MediaRecorder can be paused ("pause()") and resumed ("resume()"). The only case when Pause() throws an Exception is when it is called before a "start()" or after a "stop()".
I want to be able to trigger an event when a user connects or disconnects a USB device. I have the following code:
public static boolean isConnected(Context context) {
Intent intent = context.registerReceiver(null, new IntentFilter("android.hardware.usb.action.USB_STATE"));
return intent.getExtras().getBoolean("connected");
}
The above is from another StackOverflow question.
How can I go about the problem I'm facing? I don't think it would be practical to check every x second if the state has changed. So, I checked online for an event listener about USB_CONNECTION, but I can't seem to find any. Actually, I did find a few but they were confusing and quite old. (A year or two ago.)
TRIED CODE
while(notFinished) {
if (!isConnected(this)) {
pause();
} else if (!mediaPlayer.isPlaying() && isConnected(this)) {
play();
} else {
Log.e("[ERROR]: ", "An error has occured at startSong!");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
^^^ Clearly not efficient, but it does work (somewhat). So, that's why I came over here to know if there was a listener for USB_CONNECTION_STATUS. I think this would be a lot faster.
You can use BroadcastReceiver for receiving connected and disconnected actions:
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getExtras().getBoolean("connected")) {
//start doing something for state - connected
} else {
//start doing something for state - disconnected
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction("android.hardware.usb.action.USB_STATE");
registerReceiver(receiver, filter);
This BroadcastReceiver will receive actions every time wen usb connected or disconnected.
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();
}
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.