Consider an application, it will count down from 60 to 0 at intervals of 1 second.
public class MainActivity extends AppCompatActivity {
int time;
TextView timeDisplay;
private Handler handler new Handler();
#Override
protected void onCreate(Bundle savedinstanceState) {
super.onCreate(savedinstanceState);
setContentView(R.layout.activity_main);
time = 60;
timeDisplay (TextView) findViewByid(R.id.timeDisplay);
handler.removeCallbacks(updateTimer);
handler.postDelayed(updateTimer, 1000);
}
private Runnable updateTimer = new Runnable(){
public void run(){
// somthing here
}
};
}
I try to implement a count down timer like this but I am very new to android studio and java and did not really know how to implement this. Hence any comment will be very useful. Thank you.
Did you tried CountDownTimer? You could read more information here
CountDownTimer
Related
I tried this code (seen below) and it says "Cannot resolve symbol 'customHandler'", I am a beginner so I don't know yet how to fix this problem.
It would be awesome, if you could explain me how to fix it.
I am thankfull for every help :D
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//------------------
//------------------
android.os.Handler customHandler = new android.os.Handler();
customHandler.postDelayed(updateTimerThread, 0);
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
//write here whatever you want to repeat
customHandler.postDelayed(this, 1000);
}
};
I am trying to make a method run from the begining once every minute.
customHandler is a local variable in your method onCreate, so method run() cannot see it.
Make customHandler a member variable of your class to fix.
//Member variable
android.os.Handler customHandler;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Assign value
customHandler = new android.os.Handler();
customHandler.postDelayed(updateTimerThread, 0);
}
private Runnable updateTimerThread = new Runnable() {
public void run()
{
//USE the value
customHandler.postDelayed(this, 1000);
}
};
Your customHandler object is not visible from your updateTimerThread.
Try to change the visibility of this variable by moving it outside of your method.
Here is an exemple:
android.os.Handler customHandler;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//------------------
//------------------
customHandler = new android.os.Handler();
customHandler.postDelayed(updateTimerThread, 0);
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
//write here whatever you want to repeat
customHandler.postDelayed(this, 1000);
}
};
But using a Timer and a TimerTask may be a better solution than recursively calling postDelay on your handler.
It's makes cleaner code and it assure you that it will be runned at a specific frequency (for example every minutes) whereas your solution only allows to fix the delay between the end of a run and the beginning of the next one (if it take 30s to run and delay is 1 minute, it will run every 1.5mn)
// declare your timer
Timer basicTimer;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//------------------
//------------------
// create a Timer
basicTimer = new Timer();
// create the periodic task, here it's an anonymous class
TimerTask updateTimerThread = new TimerTask() {
public void run() {
//write here whatever you want to repeat
// no need to call postDelayed
}
};
// schedule the task to run every minutes
basicTimer.scheduleAtFixedRate(updateTimerThread, 0, 60*1000); // 1minutes = 60000 ms
}
Can you tell me where is the problem on this line: timerText.setText(seconds);.
public class ShowTimer extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.timer_test_xml);
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask() {
int seconds;
TextView timerText = (TextView) findViewById(R.id.TimerTestId);
#Override
public void run() {
seconds++;
timerText.setText(seconds);
}
}, 0, 1000);
}}
I think what you want to do is display seconds in the text view. However, the TextView.setText(int) function does not do this (Im not actually sure what it does). What you want to do is timerText.setText(""+seconds); to convert the parameter into a string and change the function call to a different overloaded function.
seconds is an int, whereas I think you want to be passing as character sequence, or a reference to one via a resource id, as per the documentation.
Though this doesn't answer the OP's original question, there are alternative (and - if you agree with the recommendations from the Android docs - better) ways to do this described in this thread.
As with Richard's suggestion, your other problem is updating the TextView on the non-UI thread, so consider using a Handler.
Example
public class ShowTimer extends Activity {
private Handler mHandler;
private TextView timerText = null;
private int seconds;
private Runnable timerRunnable = new Runnable() {
#Override
public void run() {
timerText.setText(String.valueOf(seconds++));
mHandler.postDelayed(timerRunnable, 1000);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timer_test_xml);
mHandler = new Handler();
timerText = (TextView) findViewById(R.id.TimerTestId);
timerRunnable.run();
}
}
Ok - I know there has got to be a simple solution to this but for the life of me I can't figure it out.
Programming a very basic android activity to simply iterate through 0-99. I have a textview that I want to display the count. What happens is that it simply stays blank until the end and then shows the ending count (99).
Not sure if a textview is the right way to display or what the answer is. Any help is greatly appreciated. Thanks in advance
Try using code like this in onCreate (where number is defined as a field):
textView.post(new Runnable() {
#Override
public void run() {
number++;
textView.setText("counting: " + number);
if (number < 100) {
textView.postDelayed(this, 50);
}
}
});
Edit: code was edited as View classes have post and postDelayed, which propagates call to Handler instance they have internally.
You need to read a bit about Handler class.
Warning: this code leaks Activity for the time of approximatelly 5 seconds and should not be used directly in production code. You need to remove Runnable from the message queue at the appropriate time (maybe in onDestroy, but it depends on your needs).
View.removeCallbacks for anti-memory-leak.
My guess is that your onCreate() has code like this:
for (int i=0;i<100;i++) {
tv.setText(String.valueOf(i));
Thread.sleep(100); // or something to delay for a bit
}
That will give you the output that you are describing.
As with many GUI frameworks, Android's UI is event-driven. Calling setText() does not update the screen. Rather, it puts a message on a queue, asking for the screen to be updated. That queue is processed by the main application thread... the same thread that is calling onCreate() in the first place. Hence, what you are doing is queuing up 100 setText() calls, none of which will be processed until your loop is complete. Applying the 100 of them takes very little time, giving the visual result of only seeing the last change.
User a timer scheduled at a fixed rate. Increment a counter every second. Set the text on the UI thread. cancel the timer when required.
public class MainActivity extends Activity {
TextView _tv;
Timer _t;
int _count=0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
_tv = (TextView) findViewById( R.id.textView1 );
_t = new Timer();
_tv.setText(""+_count);
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
_count++;
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
_tv.setText(""+_count);
if(_count==99)
{
_t.cancel();
}
}
});
}
}, 1000, 1000 );
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
_t.cancel();
}
}
Use a countdown timer, in below code, onTick() will get called every second, here you can display/update your number each second.
set interval according to your need. Its in mili seconds.
public class TimerActivity extends Activity {
private final long startTime = 100 * 1000;
private final long interval = 1 * 1000;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
countDownTimer = new MyCountDownTimer(startTime, interval);
countDownTimer.start();
public class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
#Override
public void onFinish() {
text.setText("Time's up!");
}
#Override
public void onTick(long millisUntilFinished) {
text.setText(100 - millisUntilFinished/1000);
}
}
}
I am currently learning how to develop applications for Android mobile devices.
I wrote a test application to display numbers 0-9 on the device screen. I created a simple function to delay the number change.
However, upon running the application, only the final number is displayed. There is also a delay before this final number shows. I'm assuming that the length of the pause is my defined delay multiplied by the number of digits to be shown.
How do I create an app that changes the numbers with a delay?
public class AndroidProjectActivity extends Activity {
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Main();
}
void Delay(int Seconds){
long Time = 0;
Time = System.currentTimeMillis();
while(System.currentTimeMillis() < Time+(Seconds*1000));
}
void Main() {
String ConvertedInt;
TextView tv = new TextView(this);
setContentView(tv);
for(int NewInt = 0; NewInt!= 9; NewInt++){
ConvertedInt = Character.toString((char)(NewInt+48));
tv.setText(ConvertedInt);
Delay(5);
}
}
One way of doing this is to create a runnable that updates your view. This will still update on the UI thread, but wait in the background. There might be mistakes in the below code, but it should run with minor tweaks..
Blocking in any of the system calls into your activity is not good, since you're blocking the UI thread. Your app will be force closed, with an Application Not Responding message. Here is another good example.
public class AndroidProjectActivity extends Activity {
private Handler mHandler;
private TextView mTextView;
private Runnable mCountUpdater = new Runnable() {
private int mCount = 0;
run() {
if(mCount > 9)
return;
mTextView.setText(String.valueOF(mCount+48));
mCount++;
// Reschedule ourselves.
mHandler.postDelayed(this, 5000);
}
}
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// Cleaner to load a view from a layout..
TextView tv = new TextView(this);
setContentView(tv);
mTextView = tv;
// Create handler on UI thread.
mHandler = new Handler();
mHandler.post(mCountUpdater);
}
}
Try creating a thread, which sleeps for certain interval of time, and then increment the value by 1 till 9. And use Handler to update the UI.
You can also use AsyncTask
The call to main() i blocking the UI so it can not display nay numbers until the call is finished.
I have the following code that responds to a button click, changes the view and then after 5 seconds switches the view back:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menu);
Button test = (Button)findViewById(R.id.browseLocation);
test.setOnClickListener(testListener);
}
private TimerTask revert = new TimerTask(){
#Override
public void run() {
setContentView(R.layout.menu);
}
};
private OnClickListener testListener = new OnClickListener() {
public void onClick(View v) {
setContentView(R.layout.test);
Timer tim = new Timer();
tim.schedule(revert, 5000);
}
};
However this code does not work. The run method of the timetask is hit but setContentView fails. I assume it has something to do with scope inside the timetask.
How can I achieve the desired result?
Try yourActivityName.this.setContentView(). Do you know if revert is being called at all (i.e. using Logging)?
Found on another post that setContentView cannot be called from a non-UI thread.
Can achieve the desired affect using runOnUiThread, but not recommended.