I'm creating a simple app that will stream the internet radio station. So when the user clicks the play button I want to show a progress bar (loading circle) until the stream is being played.
I have two Runnables, one to show the progress bar, other to load audio stream and play. This is a progress bar Runnable:
private Runnable showProgressBar = new Runnable() {
#Override
public void run() {
progBar.setVisibility(View.VISIBLE);
}
};
Than on button click:
buttonPlay.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Handler show_progress_h = new Handler();
show_progress_h.post(showProgressBar);
Handler play_h = new Handler();
play_h.post(startPlayingThread);
}
});
But... the progress bar loads much to late. It loads when the radio is almost loaded, so you only see it for a blink. Is it possible to show it immediately after the button was clicked? I have no idea what is slowing it down. Should I use something else instead of Handler?
Oh and btw... I also tried both with no handlers, but the response is the same.
The problem is you are posting long running task on UI thread immidiatly after showing progressbar:
buttonPlay.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Handler show_progress_h = new Handler();
show_progress_h.post(showProgressBar);
Handler play_h = new Handler();
play_h.post(startPlayingThread);//<< issue is here
}
});
Instead do something similar to this:
buttonPlay.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Handler show_progress_h = new Handler();
show_progress_h.post(showProgressBar);
new AsyncTask<Void, Void, Void>(){
#Override
protected void doInBackground(Void v){
// perform long runningtask here that you are performing in
//startPlayingThread
}
}.execute();
}
});
For more detail check this tutorial: http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html#concurrency_asynchtask
You can use new Thread(your_runnable).start() as an alternative, and try debugging it.
Related
i have an app that contains a dialog
i want to close this dialog after x second, when user haven't any interact with app, like volume seekbar popup(that's open when the volume button clicked, and closed after 2 second of inactivity).
what is the simplest way to implement this?
thank you
You could for example use a Handler and call its .removeCallbacks() and .postDelayed() method everytime the user interacts with the dialog.
Upon an interaction, the .removeCallbacks() method will cancel the execution of .postDelayed(), and right after that, u start a new Runnable with .postDelayed()
Inside this Runnable, you could close the dialog.
// a dialog
final Dialog dialog = new Dialog(getApplicationContext());
// the code inside run() will be executed if .postDelayed() reaches its delay time
final Runnable runnable = new Runnable() {
#Override
public void run() {
dialog.dismiss(); // hide dialog
}
};
Button interaction = (Button) findViewById(R.id.bottom);
final Handler h = new Handler();
// pressing the button is an "interaction" for example
interaction.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
h.removeCallbacks(runnable); // cancel the running action (the hiding process)
h.postDelayed(runnable, 5000); // start a new hiding process that will trigger after 5 seconds
}
});
For tracking user interaction, you could use:
#Override
public void onUserInteraction(){
h.removeCallbacks(runnable); // cancel the running action (the hiding process)
h.postDelayed(runnable, 5000); // start a new hiding process that will trigger after 5 seconds
}
Which is available in your activity.
I like to do this with AsyncTask:
class ProgressDialogTask extends AsyncTask<Integer, Void, Void> {
public static final int WAIT_LENGTH = 2000;
private ProgressDialog dialog;
public ProgressDialogTask(Activity activity) {
dialog = new ProgressDialog(activity);
}
#Override
protected void onPreExecute() {
dialog.setMessage("Loading");
}
#Override
protected Void doInBackground(final Integer... i) {
long start = System.currentTimeMillis();
while(!isCancelled()&&System.currentTimeMillis()-start< WAIT_LENGTH){}
return null;
}
#Override
protected void onPostExecute(final Void v) {
if(dialog.isShowing()) {
dialog.dismiss();
}
}
}
Then trigger it from your Activity on click:
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ProgressDialogTask task = new ProgressDialogTask(this);
task.execute(0);
}
});
If you need better precision you can also use System.nanoTime()
I am also new at android, but I recommend creating a timer, and when lets say the timer t is greater than or equal to 2, then you do something. It would look kind of like this
if (t >= 2.0){
//Do whatever you want it to do
}
This may not work for your purposes, but it's just something that may require less lines of code in the end. (as I always say, less code is more code) I know that timers are basically easy to make, but I have never used one in an app. I wouldn't specifically know how to make the timer, but I'm sure you can find a tutorial on youtube.
This is the question that came up when I was looking up things regarding timing out. I have implemented an answer which uses AsyncTask, Handler, and Runnable. I am providing my answer here as a potential template for future answer searchers.
private class DownloadTask extends AsyncTask<Void, CharSequence, Void> {
//timeout timer set here for 2 seconds
public static final int timerEnd = 2000;
private Handler timeHandler = new Handler();
#Override
protected void onPreExecute() {
ProgressDialog dProgress = new ProgressDialog(/*Context*/);
dProgress.setMessage("Connecting...");
dProgress.setCancelable(false);
dProgress.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//Dismissing dProgress
dialog.dismiss();
//Removing any Runnables
timeHandler.removeCallbacks(handleTimeout);
//cancelling the AsyncTask
cancel(true);
//Displaying a confirmation dialog
AlertDialog.Builder builder = new AlertDialog.Builder(/*Context*/);
builder.setMessage("Download cancelled.");
builder.setCancelable(false);
builder.setPositiveButton("OK", null);
builder.show();
} //End onClick()
}); //End new OnClickListener()
dProgress.show();
} //End onPreExecute()
#Override
protected Void doInBackground(Void... params) {
//Do code stuff here
//Somewhere, where you need, call this line to start the timer.
timeHandler.postDelayed(handleTimeout, timerEnd);
//when you need, call onProgressUpdate() to reset the timer and
//output an updated message on dProgress.
//...
//When you're done, remove the timer runnable.
timeHandler.removeCallbacks(handleTimeout);
return null;
} //End doInBackground()
#Override
protected void onProgressUpdate(CharSequence... values) {
//Update dProgress's text
dProgress.setMessage(values[0]);
//Reset the timer (remove and re-add)
timeHandler.removeCallbacks(handleTimeout);
timeHandler.postDelayed(handleTimeout, timerEnd);
} //End onProgressUpdate()
private Runnable handleTimeout = new Runnable() {
public void run() {
//Dismiss dProgress and bring up the timeout dialog
dProgress.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(/*Context*/);
builder.setMessage("Download timed out.");
builder.setCancelable(false);
builder.setPositiveButton("OK", null);
builder.show();
}
}; //End Runnable()
} //End DownloadTask class
To those somewhat new to using AsyncTask, you must make a DownloadTask object and call .execute().
For example:
DownloadTask dTaskObject = new DownloadTask();
dTaskObject.execute();
I actually also took this code further than what you see by having all my doInBackground() code be done via a function, so I actually had to call onProgressUpdate() and other functions using the DownloadTask object.
So I have an activity which runs a simple snakes and ladders game, and I want to allow the player to click a button and move, which would subsequently be followed by the computer moving. My problem is, that once the player moves, the computer immediately makes its move.
Instead I want the activity to wait before the computer makes its move. I've looked around a lot and found that waiting involves using a thread, but I have failed to implement it without my app crashing
My attempt at declaring a thread:
final Runnable runnable = new Runnable() {
#Override
public void run()
{
while (true)
{
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
};
Thread thread= new Thread(runnable);
My onClick() method for the button:
Button rollButton = (Button) (findViewById(R.id.rollButton));
rollButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//executes only if current player is a human
if(GAME_BOARD.getCurrentPlayer().isHuman()) {
GAME_BOARD.rollDie(); // rolls the die
showDie(GAME_BOARD); // displays die on screen
GAME_BOARD.move(); // moves the player and sets next player as current player
playerTurn.setText(GAME_BOARD.getCurrentPlayer().getName() +"'s turn");// sets TextView to display who's player's turn it is
thread.start();
if(!GAME_BOARD.getCurrentPlayer().isHuman()) {
GAME_BOARD.rollDie();
showDie(GAME_BOARD);
GAME_BOARD.move();
playerTurn.setText(GAME_BOARD.getCurrentPlayer().getName() +"'s turn");
}
}
}
});
So again, my question is, how do I make it so that before the second if statement executes, the activity waits, say 4 seconds?
you can use an Handler.postDeleayed. You have to provide a Runnable to execut and the delay period in milliseconds. The Runnable will be executed on the UI Thread
You can use Handle to post your task defined in runnable after some delay
use this
Inside Activity define
Handler hand = new Handler();
and define your task in runnable like this
Runnable run = new Runnable() {
#Override
public void run() {
**your Task here.......**
}
};
In on click event
btnStartShow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
hand.postDelayed(run,3000); // For delay three seconds
}
});
also remove all pending messages by calling following sentence at appropriate place
hand.removeCallbacksAndMessages(null);
Use a CountDownTimer:
CountDownTimer timer = new CountDownTimer(4000, 1000) {
#Override
public void onFinish() {
*function containing the second statement*
}
#Override
public void onTick(long millisLeft) {
// not ticking
}
};
and in the onClick method in the click listener use:
timer.start();
Try the following,
rollButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Runnable runnable = new Runnable() {
#Override
public void run() {
// whatever you would like to implement when or after clicking rollButton
}
};
rollButton.postDelayed(runnable, 5000); //Delay for 5 seconds to show the result
}
I am working on a Testing Project for me , just so I could learn more , so now I need to update the text of a TextView constantly every 250 milliseconds through a for(;;) loop , it happens after a Button click ... My problem is that whenever I press that button my app freezes (Yes my button is totally working , verified through previous testings) , I am using a handler to the Main thread doesn't get affected while the Runnable is up ... Here is my code of the Button and Handler ...
final Handler handler = new Handler();
B3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
handler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
for(;;){
String a = Shells.sendSingleCommand("free");//Here I send a command "free" and it returns its output
text.setText(a);//text is my TextView which is used through my experimentations ...
synchronized(this){
try{
wait(250);
}catch(Exception e){
}
}
}
}
});
}
});
If you need anymore info ask please :)
use handler.postDelayed for updating textview constantly every 250 milliseconds instead of using for loop to avoid freeze current Activity as :
Handler handler=new Handler();
B3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
handler.post(runnable);
}
});
Runnable runnable=new Runnable(){
#Override
public void run() {
String a = Shells.sendSingleCommand("free");
text.setText(a);
handler.postDelayed(runnable, 250);
}
};
Android doesnt allow you to do long tasks in the main thread. If you need to do something like this I recommend moving the for loop and depdendent code into a separate thread..
I am trying to play an mp3 file (with an onClickListener) and stop after 2 seconds. I tried the code below but it is not working. Could anyone please help?
final MediaPlayer mpsound = MediaPlayer.create(this, R.raw.media_player_sound);
ImageView sound = (ImageView) findViewById(R.id.button);
sound.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mpsound.start();{
sleep(2000);
mpsound.stop();
}
}
});
Why are you calling stop() on mpfrog if you are playing audio with mpsound? You need to call the stop() function on the mpsound MediaPlayer. Also, you might want to add the #Override annotation to your onClick() method.
for the override...
sound.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mpsound.start();{
sleep(2000);
mpsound.stop();
}
}
});
for a timer.....
Handler handler = new Handler(){
#Override
public void handleMessage(Message msg){
mpsound.stop();
}
};
//Task for timer to execute when time expires
class SleepTask extends TimerTask {
#Override
public void run(){
handler.sendEmptyMessage(0);
}
}
//then in some other function...
Timer timer = new Timer("timer",true);
timer.schedule(new SleepTask(),2000);
You have to wait 2 seconds in different thread, for this case use your own created thread and wait there and stop player, or you can use CountDownTimer - very simple solution.
You can find same question aggregated here and here
In eclipse you can use autocomplete (ctrl + space by default) to fill automatically all inmplemented methods and #Overrides will already be there.
I want to show other image in ImageView within 3 second, after that rollover old image. The code:
OnClickListener oc = new OnClickListener() {
#Override
public void onClick(View v) {
ImageView iv = (ImageView)v;
iv.setImageResource(img2_id);
SystemClock.sleep(3000);
iv.setImageResource(img1_id);
}
}
myImageView.setOnClickListener(oc);
But it doesn't work? So, am I doing something wrong?
You are blocking the UI thread. Thus during the sleep command, the screen won't refresh. What you need is to schedule a non-blocking delayed call to a function which changes image resource. Here is a modified code that would do such a thing:
Handler mHandler = new Handler(); /*handler declared in your Activity thread, I assume*/
OnClickListener oc = new OnClickListener() {
#Override
public void onClick(View v) {
ImageView iv = (ImageView)v;
iv.setImageResource(img2_id);
mHandler.postDelayed(new Runnable(){
public void Run(){
iv.setImageResource(img1_id);
}
},3000);
}
}
myImageView.setOnClickListener(oc);