I am currently working with FFmpegMediaPlayer in order to make a basic music player given a url. I got the basic functionality to work. On error, I show an error message, else I play the songs.
The problem I am facing is, once the player starts, and I turn off my wifi and phone data, it stops the sound. Once I turn my wifi or phone data back one, I would like the player to continue but it simply stops. I have to stop and play again for it to continue.
Is there a way to have the FFmpegMediaPlayer continue streaming?
This is what I have to initialize the player:
mMediaPlayer = new FFmpegMediaPlayer();
mMediaPlayer.setOnErrorListener(this);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setOnSeekCompleteListener(this);
try {
Uri uri = Uri.parse(radio_url);
mMediaPlayer.setDataSource(mMainActivity, uri);
mMediaPlayer.prepareAsync();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Then I have a function to handle when Play/Stop button is clicked:
#Override
public void onPlayButtonClicked(Button button) {
if (radioInitialized) {
mAnalytics.onStopButtonClicked();
mMainLayout.loading(false);
mMediaPlayer.pause();
button.setBackground(mMainActivity.getResources().getDrawable(R.drawable.play_button));
radioInitialized = false;
} else {
mAnalytics.onPlayButtonClicked();
mMainLayout.loading(true);
initRadio();
button.setBackground(mMainActivity.getResources().getDrawable(R.drawable.stop_button));
radioInitialized = true;
}
}
Again, the basic functionality works, but I would like for it to continue streaming after wifi is turned back on.
Found a solution.
My main goal was to create a media player like a radio.
I tried MediaPlayer and it works but it tends to stop frequently.
I then tried vitamio and FFmpegMediaPlayer. Vitamio was confusing and FFmpegMediaPlayer doesn't support on streaming error.
I currently got it working with Google's Exo Player. There is a very nice tutorial here: https://codelabs.developers.google.com/codelabs/exoplayer-intro/index.html?index=..%2F..%2Findex#0
Related
I am working on application that contacts with media server. So, I have an array that fills with media's URLs. Media type is mp3.
I have a ListView that each row indicates one of array's cell. When clicked event received to each row, It should run setDataSource, prepare and start MediaPlayer. When first time, I clicked on one row, All things are okay and media streams successfully. But when I clicked another while last media is playing, error (1,-114) occurs.
Based on MediaPlayer, I know setDataSource should be run in Idle state of MediaPlayer, So, before setting data source, I invoke reset to move to Idle state.
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(getMusicUrl());
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.prepareAsync();
I implement OnErrorListener, The error details is as follows:
What: 1 MEDIA_ERROR_UNKNOWN
Extra: -114 (I haven't found any docs about this error)
Can any one help me to solve this problem?
Could you try calling mediaPlayer.release() when you decide to switch to other song.
I am experiencing an odd issue with a video streaming application I am working on. The actual streaming of video/audio is working fine on all of my test devices. However, on seemingly any device 4.0+, when using an RTSP URL, prepare() returns instantly (this causes an issue providing proper feedback to the users while a video is loading and interferes with a few other systems I have in place).
Below is the block of code where I initialize and setup my MediaPlayer, but keep a few things in mind:
My initPlayer method is called from an AsyncTask.
The video does eventually play correctly, but prepare returning instantly creates a lack of feedback to the user during a video load.
No errors of any kind occur during the entire process
start() is called on the MediaPlayer via the onPrepared method in my OnPreparedListener, which obviously becomes an issue when prepare() returns before it is actually ready to be played.
HTTP streams seem to work fine, and on every test device below 4.0 the issue does not occur.
I have been trying to fix this for a ridiculous amount of time, and haven't been able to find anyone else who has ran into this problem. Any ideas would be greatly appreciated.
public void initPlayer() {
//We first need to make sure the MediaPlayer isn't null
if(mMediaPlayer==null){
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnPreparedListener(mediaPlayerPreparedListener);
mMediaPlayer.setOnCompletionListener(mediaPlayerCompletionListener);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
//If a video/stream has been chosen while another is already playing
else if(mMediaPlayer.isPlaying()){
mMediaPlayer.reset();
}
//Video is not in full screen mode
second = false;
try {
mMediaPlayer.setDataSource(videoString);
holder = mPreview.getHolder();
mMediaPlayer.setDisplay(holder);
mMediaPlayer.prepare();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//onPreparedListener
private OnPreparedListener mediaPlayerPreparedListener = new OnPreparedListener(){
public void onPrepared(MediaPlayer mp) {
mp.start();
vidPb.setVisibility(View.INVISIBLE);
}
};
Use mp.prepareAsync() as it is better for streaming media. Using prepare() blocks until MediaPlayer is ready for playback or an IllegalStateException occurs. Also, in android 4 (ICS), blocking on any UI thread is even more strict and may cause an ANR (Activity not responding) dialog to appear.
One final thought, try to avoid using e.printStackTrace(); in android apps.
Instead, use the Log.e("TAG_STRING", e.getMessage(), e); to print errors to the android logging system that you can access from logcat.
All in all, it should looks something like this:
try {
mMediaPlayer.setDataSource(videoString);
holder = mPreview.getHolder();
mMediaPlayer.setDisplay(holder);
mMediaPlayer.prepareAsync();
} catch (IllegalArgumentException e) {
Log.e("TAG_STRING", e.getMessage(), e);
} catch (SecurityException e) {
Log.e("TAG_STRING", e.getMessage(), e);
} catch (IllegalStateException e) {
Log.e("TAG_STRING", e.getMessage(), e);
} catch (IOException e) {
Log.e("TAG_STRING", e.getMessage(), e);
}
my app is playing some audio files, but if the user hits the play button twice, it will play then it will play again (something like that).
I would like the next action to happen JUST when the first execution of the audio file is over.
How can I do that?
Here is my code:
MediaPlayer mMediaPlayer = new MediaPlayer();
try {
mMediaPlayer.setDataSource((endMidia));
mMediaPlayer.prepare();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
mMediaPlayer.start();
Any help is appreciatted!
You can make check with MediaPlayer.isPlaying().
There are listeners on MediaPlayer events like OnCompletionListener
http://developer.android.com/reference/android/media/MediaPlayer.html#setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener)
and others
check if condition as shown in below code
MediaPlayer mMediaPlayer = new MediaPlayer();
try {
mMediaPlayer.setDataSource((endMidia));
mMediaPlayer.prepare();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
if(!mMediaPlayer.isPlaying()){
mMediaPlayer.start();
}
I have mp4 and wmv movie files and need to play only sound not video screen. How to do it?? Could I get sound track from movie file??
I know if I hide the SurfaceView from screen, I can only hear sound.. but I have tried a lot but.. it is impossible.
If you have any solution to extract sound track from movie file, please let me know..
Thanks in advance.
If you are using the mediaplayer API in your app then don't call the API public void setDisplay (SurfaceHolder sh). This will ensure that only the audio is played out even if the video content is present..
More info in android doc here
Use following code, Optimize following code as per your requirement. It play video from youtube.
try {
final MediaPlayer m = new MediaPlayer();
Thread t = new Thread(new Runnable() {
public void run() {
try {
m.setDataSource("rtsp://v8.cache3.c.youtube.com/CjgLENy73wIaLwlQP1m32SiSYxMYJCAkFEIJbXYtZ29vZ2xlSARSB3JlbGF0ZWRggqG7w9aS2-1MDA==/0/0/0/video.3gp");
m.prepare();
m.start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
} catch (Exception e) {
e.printStackTrace();
}
I am using a MediaPlayer instance in order to stream audio files from an Internet location. The audio player is in a separate activity. The user can select from a list of audio files and come to this activity to play the audio.
Now the user might go back to the previous activity (with the list) and select another audio file. In this case, I want to stop any other audio that is playing and start playing the new audio which was selected.
Is there any way I can know whether an audio file is playing without having to hold on to the MediaPlayer object?
Thanks.
Edit
I did find out how to know whether an audio is playing.
We can do it by using an object of AudioManager and calling isAudioPlaying(). This will return a true if any audio is playing.
Now the other question, how do I stop an audio currently playing? I do not have an instance of the MediaPlayer object which was created to start the audio (coz the user has already left the activity once and has come back with a new object of the activity and thus a new instance of the MediaPlayer)
You'll need to call stop() on the MediaPlayer instance. To make this work in your application, you'll either need to:
Call stop() within the audio playing activity (in onDestroy()), for example
Create a Service to play audio, and communicate with it from both activities
Using a Service will allow your code to continue running outside of the Activity life-cycle, and is the only way to persist a MediaPlayer object like you need to in this case.
Alternatively, you may be able to create a custom subclass of Application and store the MediaPlayer there, but using a Service is considered better practice.
I found way to check whether audio stream (AudioManager.STREAM_RING, AudioManager.STREAM_NOTIFICATION and etc.) is currently busy using reflection:
/**
* Unhide android api: check is stream is active now (AudioManager.STREAM_RING, AudioManager.STREAM_NOTIFICATION...),
* uses reflection
* #param audioStream
* #return
*/
public static boolean isStreamActive(int audioStream) {
Class<?> audioSystemClazz = null;
Boolean res = false;
try {
audioSystemClazz = Class.forName("android.media.AudioSystem");
if (null != audioSystemClazz) {
// isStreamActive
Method method = audioSystemClazz.getDeclaredMethod("isStreamActive", new Class<?>[] { int.class,
int.class });
if (null != method) {
res = (Boolean) method.invoke(null, audioStream, 0);
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return res;
}
Here's some handy code to sleep until audio is done playing:
AudioManager manager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
while(manager.isMusicActive())
{
Log.d("music", "music is active");
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
Log.e("music", "interrupted waiting for music to stop");
}
Log.d("music", "done playing music");
}
#lostintransit "Would it be better to use a service, a static variable or a singleton class? What would be the better design option?"
I think a service is what you want. The built-in media player and Pandora's app both use a service to ensure the music isn't tied to the Activity lifecycle.
If I'm understanding why you'd use a singleton or static I don't think it will accomplish what you want. The singleton/static will only be enforced within a single process in Linux. If you launch your Activity, then close it, then launch it again, they will run in different processes.
Try this...
if (mp1 != null && mp1.isPlaying()) {
mp1.stop();
}
Where mp1 is the MediaPlayer