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.
Related
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);
So i am trying to get a mediaplayer to work, but on first install the music doesnt start playing (i think it's because of permissions needed for the visualizer). But everytime afterwards it plays just fine.
code:
mPlayer = MediaPlayer.create(this, R.raw.bik);
mPlayer.setLooping(true);
mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
Log cat:
11-23 17:18:29.979 28329-28329/com.waro.blockevader E/MediaPlayer: Error (-38,0)
11-23 17:18:29.979 28329-28329/com.waro.blockevader E/MediaPlayer: Error (-38,0)
11-23 17:18:29.979 28329-28329/com.waro.blockevader E/MediaPlayer: Error (1,-1010)
11-23 17:18:29.979 28329-28329/com.waro.blockevader E/MediaPlayer: Error (-38,0)
11-23 17:18:29.979 28329-28329/com.waro.blockevader V/MediaPlayer[Native]: isPlaying: 0
11-23 17:18:29.979 28329-28329/com.waro.blockevader E/MediaPlayer: Error (-38,0)
The file format is .mp4
Thanks for the help.
Edit:
What i meant by everytime after;
Everytime after i gave permissions and RESTARTED the app, the music starts playing just fine and no errors are given.
Permissions:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
You are getting two different errors. The first one
E/MediaPlayer: Error (-38,0)
means that you try to call the MediaPlayer without preparing it first.
The second error
E/MediaPlayer: Error (1,-1010)
means that the media is unsupported. You can see the error codes here and here
I fixed it by changing a part in the onResumse(),
As expected it was indeed the permission causing havoc,
i had:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
if (!mPlayer.isPlaying() && !mpCreated) {
initTunnelPlayerWorkaround();
init();
} else {
mPlayer.start();
mVisualizerView.link(mPlayer);
}
} else {
cleanUp();
mPlayer.start();
Log.i("boop","biep");
}
And finally discovered by that log it was going into the else, meaning it was calling the cleanUp(); method
And in the cleanUp() method i had:
private void cleanUp() {
if (mPlayer != null) {
mVisualizerView.release();
if(!mPlayer.isPlaying()) {
mPlayer.pause();
}
}
}
The 2nd if was causing havoc (duh) and i fixed it by changing it to:
private void cleanUp() {
if (mPlayer != null) {
mVisualizerView.release();
if(mPlayer.isPlaying()) {
mPlayer.pause();
}
}
I know this is a weird and specific answer, but maybe someone else who had the same struggle can find out why he or she was having problems.
Have a great day all and thanks for trying to help
~Waro (dh19, couldnt use waro sadly)
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
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.
I am writing an Android alarm application that uses a Service in order to play the alarm tone. Currently, I am able to get the audio to play, but it plays in a form that can be muted by turning down the device's volume. Thus, I am trying to add a call to setAudioStreamType(AudioManager.STREAM_ALARM); to prevent this.
I have the following for my onStartCommand() function for the service:
MediaPlayer mMP;
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
try
{
mMP = MediaPlayer.create(this, R.raw.alarm);
mMP.setAudioStreamType(AudioManager.STREAM_ALARM);
mMP.setLooping(true);
//mMP.prepare(); commented out since prepare() is called in create
}
catch (Exception e)
{
e.printStackTrace();
}
if (mMP != null) mMP.start();
return START_STICKY;
}
My problem is that with the call to setAudioStreamType(), the MediaPlayer never plays the audio. If I comment that line out, the audio plays.
With the line in, I get the following runtime error(s):
04-10 19:32:03.115: E/MediaPlayer(3411): setAudioStream called in state 8
04-10 19:32:03.115: E/MediaPlayer(3411): error (-38, 0)
04-10 19:32:03.115: E/MediaPlayer(3411): start called in state 0
04-10 19:32:03.115: E/MediaPlayer(3411): error (-38, 0)
04-10 19:32:03.115: E/MediaPlayer(3411): Error (-38,0)
04-10 19:32:03.115: E/MediaPlayer(3411): Error (-38,0)
Some research (I can't find the link now) told me that setAudioStreamType() can't be called after prepare() has been called, and that create() implicitly calls prepare().
In any regard, how am I supposed to setAudioStreamType() without such an error?
You can either call mp.reset() and then set the stream type, data source, and then prepare. Alternately just use the default constructor and handle the initialization yourself.
EDIT:
Resources res = getResources();
AssetFileDescriptor afd = res.openRawResourceFd(R.raw.alarm);
mp.reset();
mp.setAudioStreamType(AudioManager.STREAM_ALARM);
mp.setLooping(true);
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mp.prepare();
mp.start();
Accepted answer was throwing an IllegalStateException. This is working
MediaPlayer mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(
this,
getCustomToneUri()
);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}