Streaming Audio from A URL in Android using MediaPlayer? - android

I've been trying to stream mp3's over http using Android's built in MediaPlayer class. The documentation would suggest to me that this should be as easy as :
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(URL_OF_FILE);
mp.prepare();
mp.start();
However I am getting the following repeatedly. I have tried different URLs as well. Please don't tell me that streaming doesn't work on mp3's.
E/PlayerDriver( 31): Command PLAYER_SET_DATA_SOURCE completed with an error or info PVMFErrNotSupported
W/PlayerDriver( 31): PVMFInfoErrorHandlingComplete
E/MediaPlayer( 198): error (1, -4)
E/MediaPlayer( 198): start called in state 0
E/MediaPlayer( 198): error (-38, 0)
E/MediaPlayer( 198): Error (1,-4)
E/MediaPlayer( 198): Error (-38,0)
Any help much appreciated, thanks
S

simple Media Player with streaming example.For xml part you need one button with id button1 and two images in your drawable folder with name button_pause and button_play and please don't forget to add the internet permission in your manifest.
public class MainActivity extends Activity {
private Button btn;
/**
* help to toggle between play and pause.
*/
private boolean playPause;
private MediaPlayer mediaPlayer;
/**
* remain false till media is not completed, inside OnCompletionListener make it true.
*/
private boolean intialStage = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button1);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
btn.setOnClickListener(pausePlay);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
private OnClickListener pausePlay = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
if (!playPause) {
btn.setBackgroundResource(R.drawable.button_pause);
if (intialStage)
new Player()
.execute("http://www.virginmegastore.me/Library/Music/CD_001214/Tracks/Track1.mp3");
else {
if (!mediaPlayer.isPlaying())
mediaPlayer.start();
}
playPause = true;
} else {
btn.setBackgroundResource(R.drawable.button_play);
if (mediaPlayer.isPlaying())
mediaPlayer.pause();
playPause = false;
}
}
};
/**
* preparing mediaplayer will take sometime to buffer the content so prepare it inside the background thread and starting it on UI thread.
* #author piyush
*
*/
class Player extends AsyncTask<String, Void, Boolean> {
private ProgressDialog progress;
#Override
protected Boolean doInBackground(String... params) {
// TODO Auto-generated method stub
Boolean prepared;
try {
mediaPlayer.setDataSource(params[0]);
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
intialStage = true;
playPause=false;
btn.setBackgroundResource(R.drawable.button_play);
mediaPlayer.stop();
mediaPlayer.reset();
}
});
mediaPlayer.prepare();
prepared = true;
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
Log.d("IllegarArgument", e.getMessage());
prepared = false;
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
prepared = false;
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
prepared = false;
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
prepared = false;
e.printStackTrace();
}
return prepared;
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
if (progress.isShowing()) {
progress.cancel();
}
Log.d("Prepared", "//" + result);
mediaPlayer.start();
intialStage = false;
}
public Player() {
progress = new ProgressDialog(MainActivity.this);
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
this.progress.setMessage("Buffering...");
this.progress.show();
}
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
if (mediaPlayer != null) {
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
}

Android MediaPlayer doesn't support streaming of MP3 natively until 2.2. In older versions of the OS it appears to only stream 3GP natively. You can try the pocketjourney code, although it's old (there's a new version here) and I had trouble making it sticky — it would stutter whenever it refilled the buffer.
The NPR News app for Android is open source and uses a local proxy server to handle MP3 streaming in versions of the OS before 2.2. You can see the relevant code in lines 199-216 (r94) here: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/PlaybackService.java?r=7cf2352b5c3c0fbcdc18a5a8c67d836577e7e8e3
And this is the StreamProxy class: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java?r=e4984187f45c39a54ea6c88f71197762dbe10e72
The NPR app is also still getting the "error (-38, 0)" sometimes while streaming. This may be a threading issue or a network change issue. Check the issue tracker for updates.

I guess that you are trying to play an .pls directly or something similar.
try this out:
1: the code
mediaPlayer = MediaPlayer.create(this, Uri.parse("http://vprbbc.streamguys.net:80/vprbbc24.mp3"));
mediaPlayer.start();
2: the .pls file
This URL is from BBC just as an example. It was an .pls file that on linux i downloaded with
wget http://foo.bar/file.pls
and then i opened with vim (use your favorite editor ;) and i've seen the real URLs inside this file. Unfortunately not all of the .pls are plain text like that.
I've read that 1.6 would not support streaming mp3 over http, but, i've just tested the obove code with android 1.6 and 2.2 and didn't have any issue.
good luck!

Use
mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaplayer.prepareAsync();
mediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaplayer.start();
}
});

I've had the same error as you have and it turned out that there was nothing wrong with the code. The problem was that the webserver was sending the wrong Content-Type header.
Try wireshark or something similar to see what content-type the webserver is sending.

Looking my projects:
https://github.com/master255/ImmortalPlayer http/FTP support, One thread to read, send and save to cache data. Most simplest way and most fastest work. Complex logic - best way!
https://github.com/master255/VideoViewCache Simple Videoview with cache. Two threads for play and save data. Bad logic, but if you need then use this.

No call mp.start with an OnPreparedListener to avoid the zero state i the log..

Related

how to stream a online radio without any stuck over streaming?

how to stream a online radio without any buffering after the player is played. It should buffered for few sec for continue playing the radio,but it get stuck for few sec and playing.
my Aync task:
class Player extends AsyncTask {
private ProgressDialog progress;
#Override
protected Boolean doInBackground(String... params) {
// TODO Auto-generated method stub
Boolean prepared;
try {
mediaPlayer.setDataSource(params[0]);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
intialStage = true;
playPause = false;
control.setBackgroundResource(R.drawable.play);
mediaPlayer.stop();
mediaPlayer.reset();
}
});
mediaPlayer.prepare();
prepared = true;
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
Log.d("IllegarArgument", e.getMessage());
prepared = false;
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
prepared = false;
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
prepared = false;
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
prepared = false;
e.printStackTrace();
}
return prepared;
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
if (progress.isShowing()) {
progress.cancel();
}
Log.d("Prepared", "//" + result);
mediaPlayer.start();
media.stop();
intialStage = false;
}
public Player() {
progress = new ProgressDialog(MainActivity.this);
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
this.progress.setMessage("Buffering...");
media.start();
}
}
public void mute1(View v){
speaker.setVisibility(View.VISIBLE);
mute.setVisibility(View.INVISIBLE);
mediaPlayer.setVolume(0,0);
media.setVolume(0,0);
seekbar.setClickable(false);
seekbar.setFocusable(false);
seekbar.setEnabled(false);
}
public void speaker1(View v){
speaker.setVisibility(View.INVISIBLE);
mute.setVisibility(View.VISIBLE);
mediaPlayer.setVolume(1,1);
media.setVolume(1,1);
seekbar.setClickable(true);
seekbar.setFocusable(true);
seekbar.setEnabled(true);
}
how to get my player prepare for the online radio without any streaming after player is started.
Please Help me..
my source is:
if (playPause) {
control.setBackgroundResource(R.drawable.play);
mediaPlayer.stop();
new Player().cancel(true);
media.stop();
media.reset();
mediaPlayer.reset();
if (mediaPlayer.isPlaying())
mediaPlayer.stop();
mediaPlayer.reset();
media.stop();
playPause = false;
} else {
control.setBackgroundResource(R.drawable.pause);
if (intialStage) {
new Player()
.execute("http://streaming.shoutcast.com/MUKILFMRADIO");
} else {
if (!mediaPlayer.isPlaying())
mediaPlayer.start();
}
}
playPause = true;
}
};
I would suggest to use Exoplayer than media player.ExoPlayer is an application level media player for Android. It provides an alternative to Android’s MediaPlayer API for playing audio and video both locally and over the Internet. ExoPlayer supports features not currently supported by Android’s MediaPlayer API, including DASH and SmoothStreaming adaptive playbacks. Unlike the MediaPlayer API, ExoPlayer is easy to customize and extend, and can be updated through Play Store application updates. This links give you better idea about Exoplayer.
https://developer.android.com/guide/topics/media/exoplayer.html
https://github.com/google/ExoPlayer

How to continue radio streaming in mediaPlayer after screen Orientation changes?

I am using a simple code to stream a radio from url like this:
player = new MediaPlayer();
try {
player.setDataSource("XYZ.com/streaming link");
player.prepare();
player.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
player.start();
ma.MyProgressdis();
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
But when screen Orientation changes the media player stops for a while and start streaming again. I have tried using onConfigurationChanged method but I am confused about what could I do to continue the streaming without pausing .

Android Media Player: Start called in state 4 error(-38,0)

This is the code am using to fetch a file name(.mp3) dynamically from some other class as am having many mp3 files in my assets folder:
playAudioButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
FileName audio=new FileName();
String audioName=audio.getAudioName(count).toString();
if(audioName=="NO Audio")
{
Toast.makeText(getApplicationContext(), "No Audio for this page", Toast.LENGTH_SHORT).show();
}
else
{
try {
afd=getAssets().openFd(audioName + ".mp3");
mp = new MediaPlayer();
mp.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
mp.prepareAsync();
mp.start();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
Log Cat :
03-20 11:21:28.726: E/SpannableStringBuilder(4418): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
03-20 11:21:28.726: E/SpannableStringBuilder(4418): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
03-20 11:22:24.968: D/libEGL(4579): loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
03-20 11:22:24.976: D/libEGL(4579): loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
03-20 11:22:24.984: D/libEGL(4579): loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
03-20 11:22:25.070: D/OpenGLRenderer(4579): Enabling debug mode 0
03-20 11:22:38.773: E/MediaPlayer(4579): start called in state 4
03-20 11:22:38.773: E/MediaPlayer(4579): error (-38, 0)
03-20 11:22:38.773: E/MediaPlayer(4579): Error (-38,0)
Points to be noted:
1. I have checked similar threads on stack overflow the answer is using prepareAsync()
2. I have used prepareAsync()
Thanks in advance.
You can also use below onPrepared() method to call start method so that start() is called after MediaPlayer is prepared.
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.start();
}
});
Instead of using this preparedSync/prepare method of MediaPlayer you can just pass the file path converting into URI to the MediaPlayer.create()
MediaPlayer mediaPlayer = MediaPlayer.create(context, URI.parse("file://"+filePath));
this will prepare it and start playing itself
Or another way is use onPrepareListener() of MediaPlayer and then from this on prepared start playing
state 4 means Mediaplayer is in preparing state
and we call other actions like
Mediaplayer.start()
Mediaplayer.stop()
Mediaplayer.pause()
or any other thing .
As per your code it is Mediaplayer.start();
you need to write onprepare method
MediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.start();
}
});
Once Onprepared() method called you can do further process
just remove
mp.start()
after
mp.prepareAsync();
And you will good to go
public class BackgroundSound extends AsyncTask<String, Void, Void> {
MediaPlayer mediaPlayerChatAudio;
#Override
protected Void doInBackground(String... params) {
String model = params[0];
final Uri uri = Uri.parse(model);
LogEm.e("EM", "::::::::::URI::::::::::" + model);
if (uri == null || uri == Uri.EMPTY) return null;
if (mediaPlayerChatAudio != null) mediaPlayerChatAudio.stop();
try {
mediaPlayerChatAudio = MediaPlayer.create(TextActivity.this, uri);
mediaPlayerChatAudio.setAudioStreamType(AudioManager.STREAM_MUSIC);
} catch (Exception e) {
// do nothing.
}
if (mediaPlayerChatAudio == null) return null;
mediaPlayerChatAudio.setVolume(1.0f, 1.0f);
mediaPlayerChatAudio.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mediaPlayerChatAudio.reset();
mediaPlayerChatAudio.release();
mediaPlayerChatAudio = null;
}
});
mediaPlayerChatAudio.start();
return null;
}
}
If the above solutions doesn't work for anyone facing the same problem.
Make sure you call mediaPlayer.reset() before changing dataSource for the mediaPlayer object

Android: Playing multiple audio tracks

I am developing in Android and have been trying to create an Async task that plays audio files in order depending on a set of boolean values (if i1 is true, then it plays i1, and then when i1 is done, if i2 is true it plays that and so on). My first attempt is not crashing the app, but is also not playing the audio file.
class SessionMusicTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
try {
while(playing == true){
if(i1 == true && done == true){
done = false;
player.setDataSource(i1Loc);
player.prepare();
player.start();
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
done = true;
}
});
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
Is this the best approach to the problem? Any idea why the file isn't playing?
Thanks for any help in advance.
Update:
I just put a finish() in the onPostExecute() and the activity ends almost immediately, leading me to believe the task is not even starting to play the audio file?
Make sure you are releasing the MediaPlayer class when a song is done playing otherwise you could see some strange behavior:
mp.release();
Write following outside from :: doInBackground(Void... params) {
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
done = true;
}
});

is it possible to display video information from an rtsp stream in an android app UI

I have managed to get a working video player that can stream rtsp links, however im not sure how to display the videos current time position in the UI, i have used the getDuration and getCurrentPosition calls, stored this information in a string and tried to display it in the UI but it doesnt seem to work
**in main.xml:**
TextView android:id="#+id/player"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="1px"
android:text="#string/cpos"
/>
**in strings.xml:**
string name="cpos">"" /string>
**in Player.java**
private void playVideo(String url) {
try {
media.setEnabled(false);
if (player == null) {
player = new MediaPlayer();
player.setScreenOnWhilePlaying(true);
} else {
player.stop();
player.reset();
}
player.setDataSource(url);
player.getCurrentPosition();
player.setDisplay(holder);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnPreparedListener(this);
player.prepareAsync();
player.setOnBufferingUpdateListener(this);
player.setOnCompletionListener(this);
} catch (Throwable t) {
Log.e(TAG, "Exception in media prep", t);
goBlooey(t);
try {
try {
player.prepare();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.v(TAG, "Duration: ===> " + player.getDuration());
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private Runnable onEverySecond = new Runnable() {
public void run() {
if (lastActionTime > 0
&& SystemClock.elapsedRealtime() - lastActionTime > 3000) {
clearPanels(false);
}
if (player != null) {
timeline.setProgress(player.getCurrentPosition());
//stores getCurrentPosition as a string
cpos = String.valueOf(player.getCurrentPosition());
System.out.print(cpos);
}
if (player != null) {
timeline.setProgress(player.getDuration());
//stores getDuration as a string
cdur = String.valueOf(player.getDuration());
System.out.print(cdur);
}
if (!isPaused) {
surface.postDelayed(onEverySecond, 1000);
}
}
};
Your code snippet looks significantly like my vidtry sample. getCurrentPosition() and getDuration() works for HTTP streaming, such as for use in updating the progress bar.
I have not tried vidtry with an RTSP video stream, mostly because I don't know of any.
Check the SDP response from the server to ensure that it is sending the duration in the response (live streams don't have a recognizable time and that may cause the client to not provide this information.)
E.g. a live feed will look like:
a=range:npt=0-
Whereas a VoD clip should look like:
a=range:npt=0-399.1680
If getCurrentPosition() doesn't work, but you know the Duration (either getDuration() works or you have an alternate way of getting this information; you could calculate it by watching the buffering events and tracking this your self. Your approach is the more desirable approach than this one.
If I got you right, you want to show in a TextView elapsed time e.g. hh:mm:ss?
If so, I'll give you a little walkthrough on how to do that.
private TextView mElapsedTimeText;
private VideoView mVideoView;
private Thread mThread;
#Override
public void onCreate(Bundle savedInstanceState) {
/* here goes your code */
// let's assume that your IDs are elapsedId and videoId
mElapsedTimeText = (TextView) findViewById(R.id.elapsedId);
mVideoView = (VideoView) findViewById(R.id.videoId);
mThread = new Thread() {
#Override
public void run() {
mElapsedTime.setText(getNiceString());
mVideoView.postDelayed(mThread, 1000);
}
}
/* here goes your code */
}
public String getNiceString() {
String result = "";
int position = mVideoView.getCurrentPosition();
/* here goes your code */
//result is hh:mm:ss formatted string
return result;
}
#Override
public void onPrepared(MediaPlayer mp) {
/* here goes your code */
// you have to trigger the process somewhere
mVideoView.postDelayed(mThread, 1000);
/* here goes your code */
}
And one more thing I forgot to mention. In order to make this work your activity class has to implement the OnPreparedListener interface.
I hope you or someone else will find this post useful.
Best regards,
Igor

Categories

Resources