I am using Android Studio. So this is the full code. I am trying to start the countdown by clicking the startButton. The plan is that the countdown is going down while I can still click the other button. The other button(incrementButton) increments. I got the increment working but the timer is not working when I click the startButton. Is there something wrong I am doing?
EDIT : Would it also be good to ask on how to cancel the background thread?
I tried using cancel(true). Changed the code
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
TextView seconds;
TextView increment;
int count;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
seconds = (TextView) findViewById(R.id.seconds);
increment = (TextView) findViewById(R.id.increment);
Button incrementButton = (Button) findViewById(R.id.incrementButton);
Button startButton = (Button) findViewById(R.id.startButton);
Button stopButton= (Button) findViewById(R.id.stopButton);
incrementButton.setOnClickListener(this);
startButton.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch(view.getId()){
case R.id.incrementButton:
count++;
increment.setText(Integer.toString(count));
break;
case R.id.startButton:
new timerTask();
break;
case R.id.stopButton:
new timerTask().cancel(true);
break;
}
}
private void updateSeconds(final int count) {
runOnUiThread(new Runnable() {
#Override
public void run() {
seconds.setText(Integer.toString(count));
}
});
}
public class timerTask extends AsyncTask<Void, Void, Void> {
private int i;
private int savedSecond;
public timerTask() {
}
#Override
protected Void doInBackground(Void... voids) {
try {
for(i = 10; i > 0; i--){
savedSecond = i;
updateSeconds(savedSecond);
Thread.sleep(1000); //1000 = 1 seconds
if(isCancelled())
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
}
Call execute method to start AsyncTask as:
case R.id.startButton:
new timerTask().execute();
break;
case R.id.startButton:
timerTask timerTask =new timerTask(); // here you created the timer task.
timerTask.execute() //execute has to be called.
break;
Related
I am new to android studio and want to overcome from this problem.
It gonna help me a lot while creating some future apps like , stopwatch, timer etc etc.
Thanks in advance !!
public class MainActivity extends AppCompatActivity {
private EditText k;
private Button start;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
k=findViewById(R.id.kf);
start=findViewById(R.id.startf);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for(int i=1;i<1000;i++)
{
k.setText(String.valueOf(i) );
}
}
});
}
}
As #f1sh already mentioned in the comments your for loop is executing at such a speed that all you see is the final value. For such cases in android one of the best solutions is to make use of Handler for posting delayed functions without blocking the UI.
So for showing 1 to 999 you can try something like this:
public class MainActivity extends AppCompatActivity {
private EditText k;
private Button start;
int count;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
k=findViewById(R.id.kf);
start=findViewById(R.id.startf);
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
public void run() {
if (count < 1000) {
k.setText(String.valueOf(count));
count++;
handler.postDelayed(this, 1000);
} else {
handler.removeCallbacks(this);
}
}
};
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
count = 1;
handler.postDelayed(runnable, 0);
}
});
}
}
this will keep changing the text in TextView with a 1 second delay, you can change the delay as needed by setting the milliseconds in runnable.
You can even use a countdown timer for this purpose but its more like a workaround and requires you to calculate the correct time etc.
For example displaying 1 to 10 would be something like this:
...
count = 1;
new CountDownTimer(11000, 1000) {
public void onTick(long millisUntilFinished) {
tv.setText(String.valueOf(count));
count++;
}
public void onFinish() {
}
}.start();
here you are displaying the value every 1 second for 11 seconds
This question already has answers here:
Running code in main thread from another thread
(17 answers)
Closed 5 years ago.
I'm trying to dynamically update an android LinearLayout in the main thread.
Unfortunately I'm having a lot of trouble ascertaining anything from the tutorials online. None of them seem to provide a complete picture of how to communicate between threads.
My idea is something like this:
public class MainActivity extends AppCompatActivity {
private LinearLayout layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
layout = new LinearLayout(this);
setContentView(layout);
Updater updater = new Updater();
Thread workerThread = new Thread(updater);
//somehow update layout
The updater class would look something like this:
public class Updater implements Runnable {
private int count = 0;
public Updater() {}
#Override
public void run()
{
for (int i = 0; i < 10; i ++){
try {
count++;
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I know I need a Handler in order to communicate messages between the threads, but I don't know how to set that up.
I would like to avoid anonymous classes, and dynamically create new TextViews whenever Updater has a new message.
create WorkerThreadListener interface:
public interface WorkerThreadListener {
void onUpdate(int counter);
}
Change your Updater class:
public class Updater implements Runnable {
private final WorkerThreadListener mWorkerThreadListener;
private final Handler mHandler;
private int count = 0;
public Updater(final WorkerThreadListener workerThreadListener) {
this.mWorkerThreadListener = workerThreadListener;
this.mHandler = new Handler();
}
#Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
count++;
mHandler.post(new Runnable() {
#Override
public void run() {
mWorkerThreadListener.onUpdate(count);
}
});
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Change MainActivity class:
public class MainActivity extends AppCompatActivity {
private LinearLayout layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
layout = new LinearLayout(this);
setContentView(layout);
Updater updater = new Updater(new WorkerThreadListener() {
#Override
public void onUpdate(int counter) {
//update layout here
}
});
Thread workerThread = new Thread(updater);
workerThread.start();
}
}
Hi please check my below answer hope it helps you.
public class ProgressTestActivity extends Activity {
private ProgressBar progress;
private TextView text;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
progress = (ProgressBar) findViewById(R.id.progressBar1);
text = (TextView) findViewById(R.id.textView1);
}
public void startProgress(View view) {
// do something long
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
final int value = i;
doFakeWork();
progress.post(new Runnable() {
#Override
public void run() {
// here you can add any view or anyof your logic which is related to UI put it into here.
text.setText("Updating");
progress.setProgress(value);
}
});
}
}
};
new Thread(runnable).start();
}
// Simulating something timeconsuming
private void doFakeWork() {
SystemClock.sleep(5000);e.printStackTrace();
}
}
Other ways are also possible.if you have any doubt please comment below post i will explain you in details.
If you just want to use a tick timer and set progress to ui thread . You can use CountDownTimer.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView textView;
private CountDownTimer countDownTimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new);
textView = (TextView) findViewById(R.id.textView);
findViewById(R.id.b2).setOnClickListener(this);
}
public void processData() {
countDownTimer = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
textView.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
textView.setText("done!");
}
}.start();
}
#Override
protected void onStop() {
super.onStop();
if (countDownTimer != null) {
countDownTimer.cancel();
}
}
#Override
public void onClick(View v) {
processData();
}
}
Apart from that to post a callback on UI thread you can use Handler .
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
mainThreadHandler.post(new Runnable() {
#Override
public void run() {
}
});
I'm trying to code a progress bar, that increases depending on a timer (starts at 0 and goes up to a certain time I choose).
When I click on a button, the progress bar decreases (decreases from values[0] - 5).
When the progress bar value is 30, I want to stop the progressbar, so stop asynctask, and restart it so the progress bar value is now 0.
My code doesn't have any error, the problem is that the progressbar doesn't stop and doesn't restart. (I know that because I made a TOAST to print the value of the progress bar, and it never stops)
This is my code in MainActivity
public class MainActivity extends Activity {
ProgressBar progressBar_eau;
TextView txt;
int compteur = 0;
Button btn_arrosoir;
MyTask task_eau;
Boolean restart = true;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_arrosoir = (Button) findViewById(R.id.btn_arrosoir);//my button when you click the progress bar decreases
progressBar_eau = (ProgressBar) findViewById(R.id.barre_eau);
progressBar_eau.setMax(30);
Drawable draw3=getResources().getDrawable(R.drawable.custom_eau);
progressBar_eau.setProgressDrawable(draw3);
progressBar_eau.setProgress(0);
task_eau = new MyTask(progressBar_eau);
task_eau.execute(300);
btn_arrosoir.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//OnCLick Stuff
compteur = compteur - 5;
}
});
}
public void cancelAsynctask(){
if (restart == false){
task_eau.cancel(true);
restartAsynctask();
Toast.makeText(MainActivity.this,
"cancel", Toast.LENGTH_LONG).show();
restart = true;
}
}
public void restartAsynctask(){
task_eau = new MyTask(progressBar_lumiere);
task_eau.execute(300);
Toast.makeText(MainActivity.this,
"restart", Toast.LENGTH_LONG).show();//my emulator shows both message start and restart even though the progress bar doesn't stop
}
public class MyTask extends AsyncTask<Integer, Integer, String> {
ProgressBar progressBar_actuelle;
public MyTask(ProgressBar target) {
progressBar_actuelle = target;
}
#Override
protected String doInBackground(Integer... params) {
while (task_eau.isCancelled() == false){
for (; count <= params[0]; count++) {
try {
Thread.sleep(1000);
publishProgress(count);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(String result) {
}
#Override
protected void onProgressUpdate(Integer... values) {
progressBar_actuelle.setProgress(values[0]+compteur);
if (progressBar_actuelle.getProgress() >= 30){
restart = false;
cancelAsynctask();
}
}
}
}
I think the problem is with the Progressbar declared in AsyncTask.Remove that and directly use the progressbar object created in onCreate method.I also observed that you are not dismissing progressbar at any point in the code. Look into it as well.
I want to add a button in my application that turns off the music but I don't know how to approach it, I have an idea but I'm sure it's far from best so I want to consult with you. The situation is as follows:
public class MainActivity extends Activity implements OnClickListener {
MediaPlayer easysong;
MediaPlayer normalsong;
MediaPlayer hardsong;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.land_main);
mContext = this;
restartButton = (Button)findViewById(R.id.restartButton);
restartButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
easysong = MediaPlayer.create(MainActivity.this, R.raw.arideniro);
normalsong = MediaPlayer.create(MainActivity.this, R.raw.junior);
hardsong = MediaPlayer.create(MainActivity.this, R.raw.ketsathis);
counter = 101;
i = 500 - dif;
new Thread(new Runnable() {
public void run() {
if(i==500){
easysong.start();}
else if(i==375){
normalsong.start();
}else if(i==250){
hardsong.start();
}
while (counter > 0) {
try {
Thread.sleep(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
counter--;
runOnUiThread(new Runnable() {
#Override
public void run() {
scoreText.setText(Integer.toString(counter));
}
});
if(i>150){
i/=1.01;}
else if(i>90-(dif/10)){
i-=1;
}
}if (counter==0) {
mChronometer.stop();
if(easysong.isPlaying()) {
easysong.stop();
easysong.release();
easysong = null;
}else if(normalsong.isPlaying()){
normalsong.stop();
normalsong.release();
normalsong = null;
}else if(hardsong.isPlaying()){
hardsong.stop();
hardsong.release();
hardsong = null;
}
This is the main class of my app where the mediaplayer is used, now I deleted much of the code because it was irrelevant to the mediaplayer and the question, so don't look for the missing brackets and such. And this here is the main menu class where the Switch that will turn on and off the music will be located:
public class MainMenu extends Activity{
private Button easy;
private Button normal;
private Button hard;
private Button scores;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_menu);
easy = (Button) findViewById(R.id.btn_easy);
scores = (Button) findViewById(R.id.btn_highscores);
easy.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dif = 0;
startGame();
}
});
}
public void startGame() {
Intent intent = new Intent(MainMenu.this, MainActivity.class);
startActivity(intent);
}
So my idea is simnple, to add a variable in MainActivity like "int p;" and from the MainMenu class to change it's state between 0 and 1, then I will add around each line that starts music an if(p==1) but is this a good approach ? Also I would like the value of the int to be saved when the app is closed
public class MainActivity extends Activity
{
int min, sec;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
min = 5;
sec = 0;
final TextView timer1 = (TextView) findViewById(R.id.timer1);
timer1.setText(min + ":" + sec);
Thread t = new Thread() {
public void run() {
sec-=1;
if (sec<0) {
min-=1;
sec=59;
}
timer1.setText(min + ":" + sec);
try
{
sleep(1000);
}
catch (InterruptedException e)
{}
}
};
t.start();
}
}
This is a code for a Thread in Java but it doesn't work. Can you help me?
Its a Timer that counts down from 5 Minutes to 0:00.
In your case you are using threads. So you cannot update ui from the thread other than the ui thread. SO you use runOnUithread. I would suggest you to use a countdown timer or a Handler.
1.CountDownTimer
http://developer.android.com/reference/android/os/CountDownTimer.html
Here's a link to another example. Suggest you to check the link for the count down timer.
Countdowntimer in minutes and seconds
Example:
public class MainActivity extends Activity {
Button b;
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textView1);
b= (Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
startTimer(200000);
}
});
}
private void startTimer(long time){
CountDownTimer counter = new CountDownTimer(30000, 1000){
public void onTick(long millisUntilDone){
Log.d("counter_label", "Counter text should be changed");
tv.setText("You have " + millisUntilDone + "ms");
}
public void onFinish() {
tv.setText("DONE!");
}
}.start();
}
}
2.You can use a Handler
Example :
Handler m_handler;
Runnable m_handlerTask ;
int timeleft=100;
m_handler = new Handler();
m_handlerTask = new Runnable()
{
#Override
public void run() {
if(timeleft>=0)
{
// do stuff
Log.i("timeleft",""+timeleft);
timeleft--;
}
else
{
m_handler.removeCallbacks(m_handlerTask); // cancel run
}
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
3.Timer
Timer runs on a different thread. You should update ui on the ui thread. use runOnUiThread
Example :
int timeleft=100;
Timer _t = new Timer();
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
Log.i("timeleft",""+timeleft);
//update ui
}
});
if(timeleft>==0)
{
timeleft--;
}
else
{
_t.cancel();
}
}
}, 1000, 1000 );
You are trying to update the UI Thread from a background Thread with
timer1.setText(
which you can't do. You need to use runOnUiThread(), AsyncTask, CountDownTimer, or something similar.
See this answer for an example of runOnUiThread()
But CountDownTimer is nice for things like this.
Also, when posting a question on SO, statements like "it doesn't work." are very vague and often unhelpful. Please indicate the expected results compared to actual results of your code and logcat if the app is crashing.