In my listView I am displaying some media content from an API. The API does not contain any information about the media duration so I thought I'd make a helper class to deal with this.
public static String getPodDuration(String url){
utils = new Utilities();
try{
mep = getInstance();
mep.reset();
mep.setDataSource(url);
mep.prepareAsync();
mep.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
duration = mep.getDuration();
Log.i("duration", String.valueOf(duration));
}
});
} catch(IllegalArgumentException e){
} catch(IllegalStateException e){
} catch(IOException e){
}
return String.valueOf(utils.milliSecondsToTimer(duration));
}
The getInstance() is as follows:
static MediaPlayer mep = null;
public static MediaPlayer getInstance(){
if(mep == null){
mep = new MediaPlayer();
}
return mep;
}
So with the help of such methods, in main class I pass on the URL of the media file. But for some reason its only giving me 0:00 value. utils.milliSecondsToTimer(duration) method works fine though.
I get the following error:
error (1, -107)
Can someone help implement this ? I do not have to play this media, I simply need to get its duration.
Edited Response:
The error error (1, -107) is coming from the player engine i.e. NuPlayer engine where the player is trying to connect to the URL. The error code -107 is corresponding to ENOTCONN (reference: errno). Please check the connection of the URL which you have given to the player.
P.S: Can you please try with a file based input?
OLD Response:
The error prepareAsync called in state 8 is indicating that the MediaPlayer is in PREPARED state and hence, it's an error to invoke a prepareAsync in this state. I feel your issue may be due to reset being invoked as part of the implementation. Please refer to this link here which explains the differences between newly created and reset player, especially the paragraph below the state diagram.
I would recommend you to modify your get instance implementation to include a release and remove the reset as below.I feel this should solve your problem.
public static String getPodDuration(String url){
utils = new Utilities();
try{
mp = getInstance();
mp.setDataSource(url);
mp.prepareAsync();
........
static MediaPlayer mp = null;
public static MediaPlayer getInstance(){
if(mp != null){
mp.release();
}
mp = new MediaPlayer();
return mp;
}
You are expecting synchronous output from an asynchronous operation. The prepared callback will not have happened by the time the getPodDuration method returns, so duration will be whatever it was before it entered the method.
Also, you only need to set the prepared listener once. Set it in the same place you create the MediaPlayer. Personally, I'm not a fan of the singleton pattern in this case, but it should still work. Your duration member will need to be static along with the MediaPlayer.
Related
I am able to play an mp3 file using android's MediaPlayer object. But I would like to play between a range of milliseconds for example between 30000 ms to 40000 ms ( 10 seconds only ). How can I achieve this?
Currently the following code is what I have,
private MediaPlayer mPlayer;
public void play() {
try {
mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.mp3_file);
if (mPlayer != null) {
int currentPosition = mPlayer.getCurrentPosition();
if (currentPosition + 30000 <= mPlayer.getDuration()) {
mPlayer.seekTo(currentPosition + 30000);
} else {
mPlayer.seekTo(mPlayer.getDuration());
}
mPlayer.start();
}
}
catch(Exception e) {
}
}
Any help is greatly appreciated. Thank you!
You can use the method:
public int getCurrentPosition ()
to obtain the current time in milSeconds maybe inside a Handler that runs every 1000 milSeconds and tests to see:
if(mPlayer.getCurrentPosition() >= (mPlayer.getDuration + 40000));
Dont forget to release the media file when you're done using it:
public void release();
mPlayer.release();
Releases resources associated with this MediaPlayer object. It is
considered good practice to call this method when you're done using
the MediaPlayer. In particular, whenever an Activity of an application
is paused (its onPause() method is called), or stopped (its onStop()
method is called), this method should be invoked to release the
MediaPlayer object, unless the application has a special need to keep
the object around. In addition to unnecessary resources (such as
memory and instances of codecs) being held, failure to call this
method immediately if a MediaPlayer object is no longer needed may
also lead to continuous battery consumption for mobile devices, and
playback failure for other applications if no multiple instances of
the same codec are supported on a device. Even if multiple instances
of the same codec are supported, some performance degradation may be
expected when unnecessary multiple instances are used at the same
time.
The best approach is to use a Handler to time the stopping of the playback. Start the player and then use the Handler's postDelayed to schedule the execution of a Runnable that will stop the player. You should also start the player only after the initial seek completes. Something like this:
public class PlayWord extends Activity implements MediaPlayer.OnSeekCompleteListener {
Handler mHandler;
MediaPlayer mPlayer;
int mStartTime = 6889;
int mEndTime = 7254;
final Runnable mStopAction = new Runnable() {
#Override
public void run() {
mPlayer.stop();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final TextView tv = new TextView(this);
tv.setText("Playing...");
setContentView(tv);
mHandler = new Handler();
mPlayer = MediaPlayer.create(this, R.raw.nicholas);
mPlayer.setOnSeekCompleteListener(this);
mPlayer.seekTo(mStartTime);
}
#Override
public void onDestroy() {
mPlayer.release();
}
#Override
public void onSeekComplete (MediaPlayer mp) {
mPlayer.start();
mHandler.postDelayed(mStopAction, mEndTime - mStartTime);
}
}
Note also that the MediaPlayer.create method you are using returns a MediaPlayer that has already been prepared and prepare should not be called again like you are doing in your code.on the screen. I also added a call to release() when the activity exits.
Also, if you want to update the UI when the seek completes, be aware that this method is usually called from a non-UI thread. You will have to use the handler to post any UI-related actions.
I'm copied this from: Android: How to stop media (mp3) in playing when specific milliseconds come?
I am having some trouble using the android MediaPlayer in a non activity class, always a context error. Here is the bugged line:
MediaPlayer Shoot = MediaPlayer.create(this, R.raw.shot);
Now I know I cant use "this" in a service, but all the other stuff I tried kept giving bugs.
any suggestions?
You are too luck because in the last two days I have develop an app that uses MediaPlayer inside a background Service ;)
You can simply retrieve an instance of your MediaPlayer using the next line:
MediaPlayer mediaPlayer = new MediaPlayer();
Then you can set all listener and play song that you want.
Edit 22th april 2012
To set listeners (an example):
mediaPlayer.setOnErrorListener(new OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO notify error to user or play next song
return true;
}
});
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
// TODO Notify to user the completion of song or play next song
}
});
To start and play song you have to do something like this:
try{
mediaPlayer.setDataSource(mSongUrl);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.prepare();
} catch (Exception e) {
e.printStackTrace();
}
// Starting media player
mediaPlayer.start();
Why don't you just pass the context reference to the constructor of your non activity class.
and then from there save it and pass it to where it is needed.
Make sure your context reference no longer remain live after its use. Else it will gonna cause memory issue.
I'm currently trying to write a simple audio player that streams a URL until the user quits. Nothing fancy really, but I'm trying to use the onInfo method of MediaPlayer to wait for the metadata update flag. I have the following code for creating the media player object.
/**
* Creates a new media player and attempts to prepare it.
*/
private void createPlayer(){
Log.v(TAG, "Now in createPlayer()");
if(mPlayer==null){
Log.i(TAG, "No existing media player found, creating.");
mPlayer=new MediaPlayer();
mPlayer.setOnErrorListener(this);
mPlayer.setOnInfoListener(new OnInfoListener() {
public boolean onInfo(MediaPlayer mp, int what, int extra) {
Log.w(TAG,"---Got some info!---");
return false;
}
});
mPlayer.setOnPreparedListener(this);
mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
} else {
Log.i(TAG, "Found an existing media player. Doing nothing.");
}
try{
mPlayer.setDataSource(mStreamUri);
mPlayer.prepareAsync();
Log.i(TAG, "Just sent the media player a prepareAsync()");
}catch(Exception e){
Log.e(TAG,"Caught exception while trying to set up media player.");
}
}
I have yet to see onError fire, but I also have yet to actually get any errors because of the simplicity of my app, but of course onPrepare works fine. I've tried implementing it with the class, as well as an inline method like the above code but nothing happens.
Change your code with this and try again -
mPlayer.prepare();
You cannot return false in onInfoListener. The android developer says if it returns false, the infoListener seems as if it was not set.
I have problems with my app because multimedia sound is heard when the app is in background
I have defined my Media player like this;
private void playLocalAudio(int R1)throws Exception
{
MediaPlayer mediaPlayer = MediaPlayer.create(this,R1);
mediaPlayer.start();
}
For calling PlayLocalAudio I do:
try{
playLocalAudio(R.raw.fartw1);
}
catch (Exception e) {
e.printStackTrace();
}
}});
But I am not able to call correctly MediaPlayer.Stop()
I am trying:
public void onPause()
{
super.onPause();
mediaplayer.stop();
}
But it doesn't work. Could you help me?
I'm guessing that your code has a class variable mediaPlayer that's not visible in your example. In that case you have variable shadowing, because you're instantiating a new mediaPlayer in playLocalAudio and that instance is not visible inside the pause method. So stop is never called. Remove the MediaPlayer class name from the declaration in playLocalAudio.
Hey,
I'm using MediaPlayer to play a regular ShoutCast stream. The code is straightforward with prepareAsync() and a handler to start the playback. While it works flawlessly with some streams like DI.FM or ETN.FM (http://u10.di.fm:80/di_progressive), with others (http://mp3.wpsu.org:8000/) it won't go past the prepare state. No other listeners are called either.
//Uri streamUri = Uri.parse("http://u10.di.fm:80/di_progressive"); /* works */
Uri streamUri = Uri.parse("http://mp3.wpsu.org:8000/"); /* stuck on prepare state */
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(this.getBaseContext(), streamUri);
mediaPlayer.prepareAsync();
Any feedback is appreciated!
I think that there are some compatibility problems with the server end.
This is rather strange since the emulator handles it ok in my case - just not on my Froyo Galaxy S, even though it is the same API version.
It could be a codec issue, http streaming issue, I do not know.
But all the servers that fail tend to be old ones, with "Copyright 1998 - 2004" at the bottom... Not exactly recent or up to date you would think.
One potential workaround (which I have not tried yet) would be to use the StreamProxy, which would also make your code compatible with 2.1 and possibly earlier versions too. At the cost of extra work, extra code, and without doubt extra bugs...
In case you are not aware of it, there is another player bug report for 2.2 which may be relevant too:
Basic streaming audio works in 2.1 but not in 2.2
I'm facing an issue when MP "hangs" at preparing state too long (stream) and i'm trying to stop it using reset(). This causes MP to hang and thus my whole app freezes. Seems like there is no way to stop MP at preparing state. Im thinking on use prepare() wrapped in thread instead of prepareAsync(). Then i'll be able to kill that thread. As for now i did it in following way:
private void actionCancel(){
try {
mp.setDataSource(new String());
} catch (Exception e) {
e.printStackTrace();
android.util.Log.d(TAG,"actionCancel(): mp.setDataSource() exception");
mp.reset();
}
}
and it works 4me.
Additionally i have a following counter:
#Override
public void onBufferingUpdate(final MediaPlayer mp, final int percent) {
if (!mp.isPlaying()){
// android.util.Log.d(TAG,"onBufferingUpdate(): onBufferingUpdateCount = "+onBufferingUpdateCount);
if (onBufferingUpdateCount>MAX_BUFFERING_UPDATES_AT_PREPARING_STATE)
restartMP();
onBufferingUpdateCount++;
return;
}
}
i'd discover this listener always triggers at preparing state. So if it triggers more than 10 times and MP is still not playing i'm just restarting it:
private void restartMP(){
if (mp!=null)
if (mpState==MediaPlayerState.Preparing)
actionCancel();
else
mp.reset();
else
mp = new MediaPlayer();
mpState = MediaPlayerState.Idle;
onBufferingUpdateCount=0;
//isRequestCancelled=false;
requestTrackInfoStartedAt=0;
requestPlay();
}
note MediaPlayerState is my custom enum which has "Preparing" value. Also mpState is a class property/field which holds current MediaPlayerState state. Before starting prepareAsync() im setting mpState to MediaPlayerState.Preparing after it completes im setting it to MediaPlayerState.Started or other corresponding value.