MediaPlayer : Audio won't stream from beginning - android

I'm using MediaPlayer in android to stream a few audio files that are added via a ListView. The audio is played when the item is clicked from the ListView.
The streams are quite long (35minutes+) and if the user exits the application before the stream ends. Then when the item is selected again from the ListView after launching, the stream is resumed from the same place where it was left off, whereas, I want it to start from the beginning whenever the item is selected from the ListView.
Here's the code :
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
musicService.player.reset();
musicService.player.release();
musicService.player = new MediaPlayer();
try {
musicService.player.setDataSource(skURL[position]);
} catch (IOException e) {
e.printStackTrace();
}
musicService.player.setAudioStreamType(AudioManager.STREAM_MUSIC);
musicService.player.prepareAsync();
musicService.player.setOnPreparedListener(this);
}
#Override
public void onPrepared(MediaPlayer mp) {
musicService.playSK();
}
//In the MusicService.java
public void playSK(){
player.start();
}
I tried setting the seek position to 0 in the playSK() method thinking that it would solve the problem like
public void playSK(){
player.seekTo(0);
player.start();
}
and it partially did. When the first item of the ListView is selected then the stream always starts from the beginning, but clicking any other item gives the following error :
MediaPlayer : error (-2147483648, 0)
MediaPlayer : start called in state 0
MediaPlayer : error (-38, 0)
MediaPlayer : Error (-2147483648, 0)
MediaPlayer : Error (-38, 0)
Update :
So I decided to dig into why there was a problem caused when trying to seek to the beginning of the track and i found out that the mediaplayer was unable to get the duration due to a protocol exception.
10-01 17:35:06.065 10031-10031/project D/LOG: data source set
10-01 17:35:06.065 10031-10031/project D/LOG: preparing media player
10-01 17:35:06.067 10031-10066/project D/MediaHTTPConnection: filterOutInternalHeaders: key=User-Agent, val= stagefright/1.2 (Linux;Android 6.0.1)
10-01 17:35:06.070 10031-10031/project D/MediaPlayer: setSubtitleAnchor in MediaPlayer
10-01 17:35:06.073 10031-10031/porject D/LOG: media player prepared
10-01 17:35:06.074 10031-10066/project D/MediaHTTPConnection: proxy null port 0
10-01 17:35:06.171 10031-10066/project W/MediaHTTPConnection: readAt 12648448 / 32768 => java.net.ProtocolException
10-01 17:43:43.352 21618-21618/project D/LOG: seeking to start
10-01 17:43:43.352 21618-21618/project W/MediaPlayer: Stream has no duration and is therefore not seekable.
How do I handle this exception and resolve the problem?

try making media player object to null after musicService.player.release();
musicService.player = null;
me too faced this issue the only workaround that works for me is making it null. If you still faced any issue let me know

Related

My app stops unfortunately when the player plays a song and after completion of the song i want to change bt the app get stopped

this is the code where after playing one song it should change top next bt the app get closed.Here on conpletion i want to change the song bt it get stopped
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mpp) {
mp.stop();
mp.reset();
mp.release();
pos =(pos+1)% mysongs.size();
String mediaPath =file.getAbsolutePath()+ "/" + mysongs.get(pos)+".wav";
Log.d("pathh1", mediaPath);
u = Uri.parse(mediaPath);
mp = MediaPlayer.create(getApplicationContext(),u);
// mp = MediaPlayer.create(getApplicationContext(),u);
try {
mp.setDataSource(getApplicationContext(),u);
mp.prepare();
mp.start();
th.start();
} catch (IOException e) {
e.printStackTrace();
}
}
});
ERROR:
05-31 17:24:52.908 9460-9460/php.example.abs.voicerecorder E/MediaPlayer: Should have subtitle controller already set
05-31 17:25:02.798 9460-9460/php.example.abs.voicerecorder D/pathh1: /storage/sdcard/MediaRecorderSample/Recordingg4.wav
05-31 17:25:02.798 9460-9460/php.example.abs.voicerecorder D/MediaPlayer: Couldn't open file on client side, trying server side
05-31 17:25:02.800 9460-9460/php.example.abs.voicerecorder D/AndroidRuntime: Shutting down VM --------- beginning of crash
05-31 17:25:02.801 9460-9460/php.example.abs.voicerecorder E/AndroidRuntime: FATAL EXCEPTION: main
Process: php.example.abs.voicerecorder, PID: 9460
java.lang.IllegalStateException
at android.media.MediaPlayer._setDataSource(Native Method)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1119)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1104)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1083)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1060)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1014)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:957)
at php.example.abs.voicerecorder.Player$2.onCompletion(Player.java:137)
at android.media.MediaPlayer$EventHandler.handleMessage(MediaPlayer.java:2538)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
One of the things going wrong in your code is, that you set the datasource after you created the player with the data source. That´s the wrong way:
mp = MediaPlayer.create(getApplicationContext(),u);
// mp = MediaPlayer.create(getApplicationContext(),u);
try {
mp.setDataSource(getApplicationContext(),u);
mp.prepare();
As stated in the API:
Calling setDataSource.... transfers a MediaPlayer object in the Idle state to the Initialized state. An IllegalStateException is thrown if setDataSource() is called in any other state.
So you have already initialized your MediaPlayer object after releasing it by:
mp = MediaPlayer.create(getApplicationContext(),u);
and right after that you set the data source in the try/catch block:
mp.setDataSource(getApplicationContext(),u);
That does not work because at this time, the MediaPlayer is not in the idle state anymore. The try/catch doesn´t catch the error because it throws an IllegalStateException and you just catch the IOException.
So the only thing you have to do is to delete
mp.setDataSource(getApplicationContext(),u);

Android MediaPlayer not returning from prepareAsync

I'm getting the following back in Logcat starting MediaPlayer with a SPECIFIC URI. Normally every Uri, good or bad, will either play or come back with an error except this particular one.
I/MPS﹕ PrepAsync started
V/MediaPlayer﹕ message received msg=8, ext1=0, ext2=0
V/MediaPlayer﹕ unrecognized message: (8, 0, 0)
V/MediaPlayer﹕ callback application
V/MediaPlayer﹕ back from callback
... and hangs there.
I'm really just looking at how do I capture this conversation in an error handler but if someone knows the actual problem that's even better.
Source code FWIW:
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
}
try {
mediaPlayer.setDataSource(sUrl);
mediaPlayer.prepareAsync();
} catch (Exception e) {
Log.d(TAG, "Exception:"+e;
}
Also, I've tried creating an OnInfoListener, OnError and OnBufferingUpdateListener. These are never called. It's seems that mediaPlayer just goes away during onPrepareAsync.
Here is the URL if anyone is inspired to play with this.
http://54.196.206.122/entercom-koitfmaac-64
I just copy/pasted this into VLC to verify that the link is valid.
UPDATE: After looking at it more, if I wait long enough, eventually I get this:
I/dalvikvm﹕ threadid=3: reacting to signal 3
I/dalvikvm﹕ Wrote stack traces to '/data/anr/traces.txt'
UPDATE: This problem as was pointed out by Shubhang Malviya was that I needed to use URI.parse as:
mMediaPlayer.setDataSource(mContext, Uri.parse("http://54.196.206.122/entercom-koitfmaac-64"));
I thought It would be good If I share my implementation:
Try the following way of initialising your media player
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnCompletionListener(this);
mMediaPlayer.setOnErrorListener(this);
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setOnInfoListener(this);
mMediaPlayer.setOnSeekCompleteListener(this);
mMediaPlayer.setDataSource(mContext, Uri.parse("http://54.196.206.122/entercom-koitfmaac-64"));
mMediaPlayer.prepareAsync();
} catch (IOException e) {
// reset media player
}
Mine onPrepared(MediaPlayer mp) is getting called after only a few seconds and it is playing your Music File.
Also FYI "Couldn't open file on client side, trying server side" is not an error message, but a debug message from the MediaPlayer. Logcat always says this when trying to play a network video stream.

Android Media player throwing error (-38, 0) after doing a reset() while playing files stored on the sd card

I have a list of songs which may be stored locally in the SD card or may be streamed from the network.Tapping on a song starts playing the song.
When the list contains have all songs to be streamed from the network everything is working fine.
But When I have songs which are stored in the sd card then While a song is playing and I tap on another one the _mediaPlayer.reset() throws an error (-38,0)and code enters the onError function where what=-38 extra=0.
However the really confusing part is that when the player has all the locally stored song and the player is paused then tapping on another song works perfectly fine. It only throws the error when a song was being played. So I tried pausing a song if it is playing but it did not help.
PS: I am encrypting the local files and decrypting the file just before playing and storing the unencrypted file with a fixed name(Ex: current.mp3). I also delete the current.mp3 before deencrypting the ile.
I am using a service to play the songs.Below is the code relevant to my problem.
private static class OnPreparedListener_r implements MediaPlayer.OnPreparedListener
{
Context ctx;
public OnPreparedListener_r(Context c) {
ctx = c;
}
public void onPrepared(MediaPlayer mp) {
Utils.acquireWakeLock();
Utils.requestAudioFocus(ctx);
mp.start();
}
//rest of the code
}
//code to play the song when the user taps on it
/*
if(_mediaPlayer.isPlaying()) { //this I tried adding to solve the issue
pause();
}
*/
_mediaPlayer.reset();
if(currentSong.isLocallyStored()){
DeleteCurrFile();
Decrypt(current_song);
_ mediaPlayer.setDataSource("path to the local file ");
}else{
_mediaPlayer.setDataSource("streaming path ");
}
_mediaPlayer.prepareAsync();
//handling the error
private static class OnErrorListener_r implements MediaPlayer.OnErrorListener
{
Context ctx;
public OnErrorListener_r(Context c) {
ctx = c;
}
public boolean onError(MediaPlayer mp, int what, int extra) {
handleMediaError(ctx);
return true;
}
}
I have been trying to figure out the problem for the last 3-4 days and went through all the links but could not find a good explanation of the error which could explain my situation. Any help would be appreciated
Thanks
I get the same error. I found the root reason:
After MediaPlayer.reset,use getDuration and getCurrentPosition methods.
Please refer to:
http://developer.android.com/reference/android/media/MediaPlayer.html
where you can find:
There is a subtle but important difference between a newly constructed MediaPlayer object and the MediaPlayer object after reset() is called.
It is a programming error to invoke methods such as getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioStreamType(int), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(int), prepare() or prepareAsync() in the Idle state for both cases.
If any of these methods is called right after a MediaPlayer object is constructed, the user supplied callback method OnErrorListener.onError() won't be called by the internal player engine and the object state remains unchanged; but if these methods are called right after reset(), the user supplied callback method OnErrorListener.onError() will be invoked by the internal player engine and the object will be transfered to the Error state.
In my code, I use TimerTask to get getCurrentPosition and getDuration.

m3u8 sound lost due to seekTo()

I have the source code of an app that plays .mp4 and I have to make it works with HLS.
The video and the sound are played but I have 2 problems ONLY WITH .m3u8 :
1) When seekTo() is activated (commentaries deleted) the sound is disabled and when I want to quit the player, it makes a long time to do and it makes crash the app.
2) setLooping doesn't work and return Error (-38,0), Attempt to perform seekTo in wrong
state: mPlayer=0x1e0380, mCurrentState=0
Note: those problems are just for .M3U8
Below code of the player :
private void playVideo() {
doCleanUp();
try {
// Create a new media player and set the listeners
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(mFilePath);
mMediaPlayer.setDisplay(mSurfaceHolder);
mMediaPlayer.prepare();
mMediaPlayer.start();
mMediaPlayer.setOnCompletionListener(this);
mMediaPlayer.setOnVideoSizeChangedListener(this);
mMediaPlayer.setOnPreparedListener(this);
//mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//mMediaPlayer.seekTo(mResumePosition);
//mMediaPlayer.setLooping(true);
} catch (Exception e) {
Log.e(LOG_TAG, "error: " + e.getMessage(), e);
showErrorMessage(mErrorPlayingVideo);
// Toast.makeText(this, "Impossible de jouer la vidéo",
// 5000).show();
}
}
Logs when setLooping is activated under setDataSource() :
error (-38, 0)
prepareAsync called in wrong state 0
prepareAsync_l return error =-38
error: null
java.lang.IllegalStateException
at android.media.MediaPlayer.prepare(Native Method)
at fr.niji.broadpeak.activity.BroadpeakDemoPlayer.playVideo(BroadpeakDemoPlayer.java:409)
at fr.niji.broadpeak.activity.BroadpeakDemoPlayer.onRequestFinished(BroadpeakDemoPlayer.java:585)
at fr.niji.lib.dataproxy.service.DataManager.handleResult(DataManager.java:262)
at fr.niji.lib.dataproxy.service.DataManager.onRequestFinished(DataManager.java:292)
at fr.niji.lib.dataproxy.service.ServiceHelper.handleResult(ServiceHelper.java:297)
at fr.niji.lib.dataproxy.service.ServiceHelper$EvalReceiver.onReceiveResult(ServiceHelper.java:119)
at android.os.ResultReceiver$MyRunnable.run(ResultReceiver.java:43)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4126)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
at dalvik.system.NativeStart.main(Native Method)
and below the code :
Attempt to perform seekTo in wrong state: mPlayer=0x1e0380,
mCurrentState=0
error (-38, 0)
Error (-38,0)
Error (-38,0)
Attempt to perform seekTo in wrong state: mPlayer=0x1e0380, mCurrentState=0
Error (-38,0)
Error (-38,0)
Attempt to perform seekTo in wrong state: mPlayer=0x1e0380, mCurrentState=0
Ok I found the problem. When you use seekTo() with a .m3u8 file and the value between the parentheses is set to 0, it doesn't work so I added a condition into playBackVideo() method :
if (mResumePosition > 0) mMediaPlayer.seekTo(mResumePosition);
So mResumePosition will never be set to 0 and play at the beginning of the file. Also, i resolved the setLooping() problem, in
public void onCompletion(final MediaPlayer mediaPlayer)
I added mMediaPlayer.release(); playVideo();
and the looping works very well !
You need to check if it is the LIVE case. If Yes, Looping and seeking might not available.

MediaPlayer: stop called in state 4

I have an activity that has a VideoView that is asynchronously preparing a video:
Uri mUri = "uri to streaming video"
VideoView mVideoView = (VideoView) rootView.findViewById(R.id.videoView);
mVideoView.setOnErrorListener(this);
mVideoView.setOnCompletionListener(this);
mVideoView.setVideoURI(mUri);
mVideoView.setMediaController(null);
mVideoView.setOnPreparedListener(this);
While it is "preparing" I show a ProgressDialog... if I press the back button during this state the following error is printed to ADB and the activity crashes silently with a short wait at a black screen:
E/MediaPlayer( 2204): stop called in state 4
E/MediaPlayer( 2204): error (-38, 0)
W/ActivityManager( 59): Activity pause timeout for HistoryRecord{45080368 com.myapp.VideoPlayerActivity}
What is the best way to stop a VideoView from preparing a video so you can exit an activity?
Note: I don't have access to the actual MediaPlayer object until the callback for the video being prepared is called:
#Override
public void onPrepared(MediaPlayer player)
... which hasn't happened while the MediaPlayer/VideoView is "preparing".
I have not tested it my self but you should be able to reset() the MediaPlayer when you are in preparing state.
Try calling MediaPlayer.prepare() before doing MediaPlayer.stop() when back button is pressed (implement onPause or onStop activity method)

Categories

Resources