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.
I have an Android app that streams an MP3 file and plays this file in player,
but the problem is mediaPlayer.prepare(); takes a long time buffering and the app freezes
so I tried to use prepareAsync();, but with this function I can't make the player play the next file.
It just plays a single file online; if I need to play another file I have to close and restart the activity when play ends. This is my code:
public void playMp3(String _link)
{
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
if(!mediaPlayer.isPlaying()){
mediaPlayer.start();
Progressbar.setVisibility(View.INVISIBLE);
play.setVisibility(View.GONE);
stop.setVisibility(View.VISIBLE);
songProgressBar.setProgress(0);
songProgressBar.setMax(100);
}
updateProgressBar();
}
});
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mediaPlayer.reset();
songProgressBar.setProgress(0);
songProgressBar.setSecondaryProgress(0);
play.setVisibility(View.VISIBLE);
stop.setVisibility(View.GONE);
link = "http://server11.mp3quran.net/hawashi/002.mp3";
playMp3(link);
}
});
mediaPlayer.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// Toast.makeText(getApplicationContext(), "n" + percent, Toast.LENGTH_LONG).show();
songProgressBar.setSecondaryProgress(percent);
if(percent==100)
{
Progressbar.setVisibility(View.INVISIBLE);
}else if(percent > songProgressBar.getProgress())
{
Progressbar.setVisibility(View.INVISIBLE);
}else
{
Progressbar.setVisibility(View.VISIBLE);
}
}
});
mediaPlayer.reset();
Progressbar.setVisibility(View.VISIBLE);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(_link);
//mediaPlayer.prepare(); // might take long! (for buffering, etc) //##
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();
}}
Actually I don't know where is error in your code but I will explain how I did that in my app
public void playMp3(String _link){
mediaPlayer.reset();
Progressbar.setVisibility(View.VISIBLE);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(_link);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnPreparedListener(this);
//mediaPlayer.prepare(); // might take long! (for buffering, etc) //##
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();
}
}
Then implements OnCompletionListener, OnPreparedListener and OnBufferingUpdateListener in your class
public class PlayerActivity extends Activity implements OnCompletionListener, OnPreparedListener, OnBufferingUpdateListener{
.
.
.
and implements all methodes
public void onPrepared(MediaPlayer mediaplayer) {
if(!mediaPlayer.isPlaying()){
mediaPlayer.start();
Progressbar.setVisibility(View.INVISIBLE);
play.setVisibility(View.GONE);
stop.setVisibility(View.VISIBLE);
songProgressBar.setProgress(0);
songProgressBar.setMax(100);
}
updateProgressBar();
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
//mediaPlayer.reset();
songProgressBar.setProgress(0);
songProgressBar.setSecondaryProgress(0);
play.setVisibility(View.VISIBLE);
stop.setVisibility(View.GONE);
link = "http://server11.mp3quran.net/hawashi/002.mp3";
playMp3(link);
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
songProgressBar.setSecondaryProgress(percent);
if(percent==100)
{
Progressbar.setVisibility(View.INVISIBLE);
}else if(percent > songProgressBar.getProgress())
{
Progressbar.setVisibility(View.INVISIBLE);
}else
{
Progressbar.setVisibility(View.VISIBLE);
}
}
I wish this helped you.
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();
}
});
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);
}
});
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 !