Progress Bar while media player is preparing - android

I am trying to figure out how to have a progress bar that says "Loading. Please Wait..." while my media player prepares a streaming file. What occurs now is that it displays after the song is prepared. how can i fix this?
mediaPlayerLoadingBar =ProgressDialog.show(PlaylistActivity.this, "", "Loading. Please wait...", true);
/*dubstep stream*/
try {
dubstepMediaPlayer.setDataSource(dubstepPlaylistString[0]);
dubstepMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
dubstepMediaPlayer.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException 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();
}
dubstepMediaPlayer.start();
if(dubstepMediaPlayer.isPlaying()){
mediaPlayerLoadingBar.dismiss();
}`
EDIT:
This is the code I have now:
`switch(pSelection){
case 1:
new AsyncTask<Void, Void, Void>(){
#Override
protected void onPreExecute(){
mediaPlayerLoadingBar =ProgressDialog.show(PlaylistActivity.this, "", "Loading. Please wait...", true);
try {
dubstepMediaPlayer.setDataSource(dubstepPlaylistString[0]);
} 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();
}
dubstepMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
//mediaPlayerLoadingBar =ProgressDialog.show(PlaylistActivity.this, "", "Loading. Please wait...", true);
return null;
}
protected void onPostExecute(Void result){
//mediaPlayerLoadingBar =ProgressDialog.show(PlaylistActivity.this, "", "Loading. Please wait...", true)
dubstepMediaPlayer.prepareAsync();
dubstepMediaPlayer.start();
mediaPlayerLoadingBar.dismiss();
}
}.execute();`

If someone Still facing this problem here is the code below
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
if(translation.equals("NIV"))
{
if(AudioPlaying==false)
{
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(Main.this);
mediaController = new MediaController(Main.this);
}
else
mediaController.show();
}
else
Toast.makeText(getBaseContext(), "عفوا, جاري تحميل ملفات الصوت الخاصة بترجمة الفانديك ", Toast.LENGTH_LONG).show();
pd = new ProgressDialog(Main.this);
pd.setTitle("Processing...");
pd.setMessage("Please wait.");
pd.setCancelable(false);
pd.setIndeterminate(true);
pd.show();
}
#Override
protected Void doInBackground(Void... arg0) {
try {
//Do something...
//Thread.sleep(5000);
try
{
mediaPlayer.setDataSource(AudioUrlPath);
mediaPlayer.prepare();
mediaPlayer.start();
AudioPlaying=true;
}
catch (IOException e) {
Log.e("AudioFileError", "Could not open file " + AudioUrlPath + " for playback.", e);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
if (pd!=null) {
pd.dismiss();
//b.setEnabled(true);
}
}
};
task.execute((Void[])null);

The issue lies in that you are not doing anything asynchronously here, and you should be. You should use an AsyncTask to do your work.
Take a look at 'the 4 steps', as detailed here:
The 4 steps
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute(), invoked on the UI thread immediately after the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
EDIT:
You can create an anonymous inner class to do your bidding, which may be similar to how you are creating your onClick handler. In your onClick do something like this:
//pseudo-code...
onClick(View v, ...) {
new AsyncTask<Generic1, Generic2, Generic3>() {
protected void onPreExecute() {
// do pre execute stuff...
}
protected Generic3 doInBackground(Generic1... params) {
// do background stuff...
}
protected void onPostExecute(Generic3 result) {
// do post execute stuff...
}
}.execute();
}
Don't forget to keep an eye on your generics here!

Here is the activity class.Here i am showing the way only.
package com.android.mediaactivity;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
public class MediaActivity extends Activity
{
public LinearLayout mainLayout;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mainLayout=(LinearLayout)findViewById(R.id.mainlinear);
MediaPlayer media=new MediaPlayer(this);
media.startPlayer();
}
}
Here is mediaplayerclass.
package com.android.mediaactivity;
import java.io.IOException;
import android.media.MediaPlayer.OnPreparedListener;
public class MediaPlayer implements OnPreparedListener {
MediaActivity mediaActivity;
android.media.MediaPlayer mediaPlayer;
public MediaPlayer(MediaActivity mediaActivity) {
this.mediaActivity = mediaActivity;
}
public void startPlayer() {
mediaPlayer = new android.media.MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.reset();
try {
mediaPlayer.setDataSource("");
mediaPlayer.prepareAsync();
toggleProgress(true);
} 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(); } } public void onPrepared(android.media.MediaPlayer mp) { toggleProgress(false); mediaPlayer.start(); }
public void toggleProgress(final boolean show) {
mediaActivity.runOnUiThread(new Runnable() {
public void run() {
if (show) mediaActivity.mainLayout.setVisibility(mediaActivity.mainLayout.VISIBLE);
else mediaActivity.mainLayout.setVisibility(mediaActivity.mainLayout.INVISIBLE);
}
});
}
}
}
}
And here is the main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:id="#+id/mainlinear"
android:visibility="invisible">
<ProgressBar android:id="#+id/ProgressBar01"
android:layout_width="wrap_content" android:layout_height="wrap_content"></ProgressBar>
</LinearLayout>

When you say prepare on the underlying mediaplayer object, internally it really does some preparation like - setting up the extractor for the file, setting up the audio decoder to decode the encoded audio file and setting up the audio sink to play the raw audio data that was decoded from the decoder. Now all this will take time, it is not instantaneous.
So in your original code, you check if the mediaplayer isPlaying and then dismiss it but the problem is at that point of time the mediaplayer is not playing the audio yet and thus your dismiss is never called so it always visible.
What you need to do is implement the listener MediaPlayer.OnPreparedListener and when the method onPrepared is called in your application call the dismiss mediaPlayerLoadingBar.dismiss(); in that method.

Here is my solution :
The prepareAsync function used to prepare the audio and it is a non blocking operation (it is not blocking the main thread of the app).
Then I used the callback setOnPreparedListener to get notified when the
prepareAsync return, and the audio is ready
public void playAudio(String audioFile){
//init the progress dialog
final ProgressDialog progressDialog = new ProgressDialog(SubjectActivity.this);
try {
progressDialog.setCancelable(false);
progressDialog.setMessage(" Waiting to Prepare ...");
progressDialog.show();
// pass the url file to the media player
mediaplayer.setDataSource(audioFile);
mediaplayer.prepareAsync();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException 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();
}
//the callback gets called when prepareAsync audio file become ready,
mediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaplayer.start();
// cancel the dialog
progressDialog.cancel();
}
});
}

Finally found out:
Guys very Imp point:
After setting url
try {
mediaPlayer.setDataSource(url);
} catch (IOException e) {
e.printStackTrace();
}
I have added prepare_sync() and added handler cause it was crashing for big files
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mediaPlayer.prepareAsync();
ProgressDialog progressDialog = ProgressDialog.show(Player.this,
"Loading Title", "Loading Message");
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (progressDialog != null && progressDialog.isShowing()){
progressDialog.dismiss();
}
}
});
// might take long! (for buffering, etc)
mediaPlayer.start();
}
},500);
This code will add progressbar too.
Points:
set url
prepareasync
OnPreparedlistener
Progressbar
mp.start-done
This is my way of doing btw I have heard there is alternative Exoplayer have a look at that too !

Related

Change pause button of audio player on oncomplete listener in android

I'm loading audio sounds into a listview, I play them.When the audio playing is done, i want to change that specific sound's pause button to play button again.
here is my code to play sounds
soundChild.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
player.setDataSource(url);
// file.close();
player.prepare();
player.setLooping(false);
// player.start();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException 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();
}
if (player.isPlaying()) {
if (player != null) {
player.pause();
// Changing button image to play button
soundChild.setImageResource(R.drawable.playbutton);
}
} else {
// Resume song
if (player != null) {
player.start();
// Changing button image to pause button
soundChild.setImageResource(R.drawable.pausebutton);
}
}
}
});
player.setOnCompletionListener(new OnCompletionListener() {
#Override public void onCompletion(MediaPlayer mp) { // TODO
// Auto-generated method stub player.release(); player=null;
Toast.makeText(_context, "complete", Toast.LENGTH_LONG).show();
soundChild.setImageResource(R.drawable.playbutton);
player.reset();
} });
But on complete listner the imageview of player button is never changed back to play imageview again. I doin't know where i'm doing wrong, because if onComplete is being called then imageview background should also change.please help.
Usually You have to call requestLayout before:
soundChild.requestLayout();
soundChild.setImageResource(R.drawable.playbutton);
and then after changing the image
soundChild.invalidate();
What else could You try? If it doesn´t work, You can also try:
soundChild.setImageDrawable(context.getResources().getDrawable(R.drawable.playbutton));
Because, like described in the API for setImageResource:
This does Bitmap reading and decoding on the UI thread, which can
cause a latency hiccup
Also, what it is possible, You have to call it in on ui thread:
runOnUiThread(new Runnable() {
#Override
public void run() {
soundChild.setImageResource(R.drawable.playbutton);
}
});
and call this in onCompletion.

Progress dialog not showing up while media controller loading the sound file

I'm using a media controller and media player to load a sound file from a server. I want to display a progress dialog box while the it is loading the sound file. The problem is actually the progress car shows but not as soon as I presses the button but just before the media controller shows up it shows and hides immediately . The media controller is working fine.
ImageButton soundLoader = (ImageButton)getActivity().findViewById(R.id.lifeObjectSound);
soundLoader.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
progress = ProgressDialog.show(getActivity(), "dialog title",
"dialog message", true);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(currentFragment);
mediaController = new MediaController(getActivity());
try {
mediaPlayer.setDataSource("https://dl.dropboxusercontent.com/u/108022472/5041046.mp3");
mediaPlayer.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException 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();
}
mediaPlayer.start();
}
});
I'm stopping the progress dialog as follows:
#Override
public void onPrepared(MediaPlayer mp) {
Log.d("media status", "onPrepared");
mediaController.setMediaPlayer(this);
mediaController.setAnchorView(getView());
handler.post(new Runnable() {
public void run() {
mediaController.setEnabled(true);
mediaController.show(0);
progress.dismiss();
}
});
}
use following line
progress = ProgressDialog.show(getActivity(), "dialog title",
"dialog message", true);

Change audio being played with delay android

I am trying to run audios one after another with a time gap of 5 seconds. However I dont really see that happening. My third audio in the list is played and others are skipped. This means while debugging only music3 is being played and others are not. I would love alternate methods of doing this. Moreover I used prepare method just like that. Makes no difference while running though.
for(int j=0;j<3;j++)
{
if(j==0)
{
xnp = MediaPlayer.create(this,R.raw.ticktock);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
try {
xnp.prepare();
xnp.start();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 5000);
xnp.stop();
}
if(j==1)
{
xnp = MediaPlayer.create(this,R.raw.music2);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
try {
xnp.prepare();
xnp.start();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 5000);
xnp.stop();
}
else if (j==2)
{
xnp = MediaPlayer.create(this,R.raw.music3);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
try {
xnp.prepare();
xnp.start();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 5000);
xnp.stop();
intenter();
}
}
Your current implementation does not work because the media playback is not done on the main thread, so you are immediately playing all 3 media resources, so only the third one is heard.
I think you might want to call MediaPlayer#setOnCompletionListener on your MediaPlayer object. In the completion listener, you can then postDelayed onto your Handler to queue up the next resource to play.

Why animation is not displaying front while streaming in android

I am doing an radio streaming app. I am trying to display some loading bar frame by frame animation before my stream begins. but the animations starts after playing the stream only. How could i show my anim before stream loads. Here is my code snippet. Help is appreciated...
bhajan_play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ConnectivityManager conMan = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo Info = conMan.getActiveNetworkInfo();
if (Info == null) {
Toast.makeText(BhajanStream.this, "POOR SIGNALS ",
Toast.LENGTH_LONG).show();
// startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
}
else {
loadanim.setBackgroundResource(R.drawable.loader_1);
loadanim.setBackgroundResource(R.anim.loadanim);
loadanimation = (AnimationDrawable) loadanim
.getBackground();
loadanimation.isVisible();
effectanim.setBackgroundResource(R.drawable.effect_1);
effectanim.setBackgroundResource(R.anim.musiceffect);
effectanimation = (AnimationDrawable) effectanim
.getBackground();
bhajan_play.setBackgroundResource(R.drawable.bhajan_start);
bhajan_play.setVisibility(View.GONE);
bhajan_stop.setVisibility(View.VISIBLE);
loadanim.setVisibility(View.VISIBLE);
effectanim.setVisibility(View.VISIBLE);
}
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(rs_bhajan_uri);
} 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();
}
try {
mediaPlayer.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mediaPlayer.start();
}
});
}
protected void onPreExecute() {
// UI work allowed here
loadanimation.start();
}
You should call prepareAsync() rather than just prepare().
From the MediaPlayer documentation:
For streams, you should call prepareAsync(), which returns
immediately, rather than blocking until enough data has been buffered.
(Calling prepare will block your Ui Thread until the data is prepared, meaning that updating your views has to wait until the preparation is done)
Example implementation:
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});

Using a thread with media player

I'm trying to get this to work the way I want and it just won't I think I had it at some point but I was trying to fix something else and changed a few things and messed it up. Basically I'm this button is a play button. It is supposed to run media player through another thread so that it reacts and buffers faster. Issue is after it plays through to the end and I click play it is ended and keeps running the onCompletion. When I would like it to start over and play from the beginning again.
public void onClick(View v) {
if(playClick%2==0){
song1.setBackgroundResource(R.drawable.button_pause);
try{
if(playClick==0){
playThread();
if(lastPlayedExists){
lastPlayed.release();
}
}
mp.start();
mpExists = true;
playClick++;
lastPlayed = mp;
lastPlayedExists=true;
mp.setOnCompletionListener(new OnCompletionListener(){
#Override
public void onCompletion(MediaPlayer media) {
mp.reset();
song1.setBackgroundResource(R.drawable.button_play);
}
});
}catch (NullPointerException e){
}
}
else if (playClick%2==1){
song1.setBackgroundResource(R.drawable.button_play);
mp.pause();
playClick++;
}
}
}
});
And this is the thread for media player
private void playThread(){
try{
new Thread(new Runnable() {
public void run() {
try {
mp.setDataSource(song);
} 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();
}
try {
mp.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}catch(IllegalStateException e){
}
}
I have tried it with the onCompletion having mp.reset(), mp.stop(), and mp.release() along with trying lastPlayed.release() all in different tests. As well as none of them being there and it just being the button change and the progress bar reset. If you know how to fix this and make it replay as it should I would greatly appreciate it. Or if you know how to make the thread stop and restart some how so that I can just make it recall and do the thread over again that would work too (atm when that has been tried it crashes because the thread has already been started). Thanks and I appreciate any input.
mp.setOnCompletionListener(new OnCompletionListener(){
#Override
public void onCompletion(MediaPlayer media) {
playClick=2;
song1.setBackgroundResource(R.drawable.button_play);
}
});

Categories

Resources