Timed event handlers in Android - android

I'm having an awful time trying to get a simple Android app to work properly. I've very little experience in Java, having come from C, and I'm trying to start small with a simple clock app that will update the display every second. Here's my Java code:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String currentdatetime =
DateFormat.getDateTimeInstance().format(new Date());
final TextView textview = new TextView(this);
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
String currentdatetime =
DateFormat.getDateTimeInstance().format(new Date());
textview.setText(currentdatetime);
}
};
textview.setGravity(Gravity.CENTER);
textview.setTextSize(20);
textview.setText(currentdatetime);
setContentView(textview);
handler.postDelayed(runnable, 1000);
runnable.run();
}
I'm running this in Debian Linux with the Google-provided ADT bundle, and have followed all the suggestions Eclipse gives for fixing these problems, to no avail. The program compiles fine and displays exactly as I'd expect it to, except that it does not update at all. I've scoured Google as best I can and have followed many different ways of doing this, but I've not been successful.
What I'd expect this program to do is, on creation, set "currentdatetime" to the current date and time, stick it in a TextView, and then change the TextView to the main view. I'd expect it to then hit handler.postDelayed and do this again every thousand milliseconds. Clearly, though, that's not what's happening.
I'm afraid I'm completely lost. Can anyone point me in the right direction?

Well, appears that I was on rather the wrong track. I've got the code working now, rather more neatly, with the following:
protected void onCreate(Bundle savedInstanceState) {
final Handler handler = new Handler();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textview = new TextView(this);
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
String currentDateTimeString =
DateFormat.getDateTimeInstance().format(new Date());
textview.setGravity(Gravity.CENTER);
textview.setTextSize(60);
textview.setText(currentDateTimeString);
setContentView(textview);
}
});
}
},1000,1000);
}
So thanks to anyone who was getting ready to answer.

Related

I cant make myHandler run

What I want to do is just a basic implementation of handler example. I have a TextView on the mainActivity, and once the page loads the handler is supposed to run and show the user value coming from SystemClock.uptimeMillis. But ıt doesn't work more than once. How can I make this code run?
public class MainActivity extends Activity {
long uptoMS=0L;
TextView tv;
Handler handler=new Handler();
long swaptime=0L;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findViewById(R.id.textView1);
uptoMS=SystemClock.uptimeMillis();
tv.setText(String.valueOf(uptoMS));
handler.post(runner);
}
private Runnable runner=new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
swaptime+=uptoMS;
tv.setTag(String.valueOf(swaptime));
handler.post(this);
}
};
}
See this below example
scheduler(){
TimerTask tasknew = new TimerSchedulePeriod();
Timer timer = new Timer();
// scheduling the task at interval
timer.schedule(tasknew,100, 100);
}
// this method performs the task
public void run() {
System.out.println("timer working");
}
timer = new Timer();
refreshTask = new TimerTask() {
#Override
public void run() {
swaptime+=uptoMS;
tv.setTag(String.valueOf(swaptime));
handler.post(this);
}
};
timer.schedule(refreshTask,
100, 100);
Well, there some problems with your code.
Firstly, you use setTag() instead of setText(), so the value will never update.
tv.setTag(String.valueOf(swaptime));
Secondly, you get uptoMS once in onCreate(), and then you use it in every "handler loop". I don't know what you try to achive but it's unlike that you want this.
Thirdly, you instantly repost your Runnable, so the main thread's message queue will be busy. You should give some break instead of instant reposting. For example you can wait 100 ms between the updates, so the TextView will be updated 10 times in every second.
handler.postDelayed(this, 100);
And finally, however others suggest you using Timer, just ignore them. Handler is the Android way to achieve tasks like this.

Updating UI on button click after a certain time

I have a TextView. I want to update its text (append a "1") after 1 second of a button click.
public class HaikuDisplay extends Activity {
Method m;
Timer t;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
t = new Timer();
m = HaikuDisplay.class.getMethod("change");
}
//Event handler of the button
public void onRefresh(View view)
{
//To have the reference of this inside the TimerTask
final HaikuDisplay hd = this;
TimerTask task1 = new TimerTask(){
public void run(){
/*
* I tried to update the text here but since this is not the UI thread, it does not allow to do so.
*/
//Calls change() method
m.invoke(hd, (Object[])null);
}
};
t.schedule(task1, 1000);
}
public void change()
{
//Appends a "1" to the TextView
TextView t = (TextView)findViewById(R.id.textView1);
t.setText(t.getText() + "1");
}
//Event handler of another button which updates the text directly by appending "2".
//This works fine unless I click the first button.
public void onRefresh1(View view)
{
TextView t = (TextView)findViewById(R.id.textView1);
t.setText(t.getText() + "2");
}
}
Consider all Exceptions be handled.
On first click, m.invoke gives InvocationTargetException. But it calls the method change() on successive invokes without any Exceptions(verified by logging). But it does not update the text. Where am I wrong?
Also, I see in the debugger that it creates a new Thread every time I click the button. That is fine. But why isn't it removing the previous Threads though their execution has been completed?
Do something like this
public void onRefresh1(View v) {
// You can have this in a field not to find it every time
final EditText t = (EditText) findViewById(R.id.textView1);
t.postDelayed(new Runnable() {
#Override
public void run() {
t.append("1");
}
}, 1000);
}
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// Update UI
}
}, 1000);
implement this on button click
UPDATE:
There are some other answers. dtmilano suggested another solution which is almost same to mine except he is calling the postDelayed method of View class and In my answer I used postDelayed method of handler class.
from the api reference of android the postDelayed method of Handler says
The runnable will be run on the thread to which this handler is
attached.
and the postDelayed method of View says
The runnable will be run on the user interface thread.
This is the only difference between these two solution. in my answer instead of creating new Handler every time you can use any other handler instance. Then the runnable will be run on that thread where that specific handler is declared. And if the postDelayed of EditText is used the the runnable method will be run on the user Interface Thread.
Now the performance issue, both has the same performance (If anybody can prove me wrong with reference I will be happy)
That's looking awful convoluted - have you considered using CountDownTimer instead?
new CountDownTimer(1000, 1000) {
public void onTick(long millisUntilFinished) {
// no-op
}
public void onFinish() {
change();
}
}.start();
This should call change (and hence change the text) on the UI thread, avoiding reflection and threading errors.
Hi Use the following code for that. Hope this will help you .
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
// your code here
}
},
1000
);
Have a look of this question also.
display data after every 10 seconds in Android
You can try with this also.
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
public void run() {
doStuff();
/*
* Now register it for running next time
*/
handler.postDelayed(this, 1000);
}
};
**EDIT 3**
Try with this once you are need to enable once (i mean if you put your code in yourmethod()== this will get automatically call 1 seconds once.
private Timer timer;
TimerTask refresher;
// Initialization code in onCreate or similar:
timer = new Timer();
refresher = new TimerTask() {
public void run() {
yourmethod();
};
};
// first event immediately, following after 1 seconds each
timer.scheduleAtFixedRate(refresher, 0,100);

How do I set up a Timer.scheduleAtFixedRate() that actually works?

I am using Eclipse for Android. I am trying to make a simple repeating Timer that has a short delay.
It will start after a TextView timerTV is clicked. This code is in the onCreate method:
timerTV = (TextView) findViewById(R.id.timerTV);
timerTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Timer gameTimer = new Timer();
TimerTask doThis;
int delay = 5000; // delay for 5 sec.
int period = 1000; // repeat every sec.
doThis = new TimerTask() {
public void run() {
Toast.makeText(getApplicationContext(), "timer is running", Toast.LENGTH_SHORT).show();
}
};
gameTimer.scheduleAtFixedRate(doThis, delay, period);
Everytime I try to run it, a "Class File Editor" pops up with the error:
"Source not found"
The JAR file C:\Program Files\Android\android-sdk\platforms\android-8\android.jar has no source attachment.
You can attach the source by clicking Attach Source below:
[Attach Source...]
When I click this, Eclipse asks me to select the location folder containing 'android.jar'
I tried to do this, but cannot navigate all the way to the folder it is located in anyway.
I presume the issue is in my code somewhere.
I have been searching for hours, even copied and pasted code many times.
Using an actual Timer (java.util.Timer) in conjunction with runOnUiThread() is one way to solve this issue, and below is an example of how to implement it.
public class myActivity extends Activity {
private Timer myTimer;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, 1000);
}
private void TimerMethod()
{
//This method is called directly by the timer
//and runs in the same thread as the timer.
//We call the method that will work with the UI
//through the runOnUiThread method.
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
//This method runs in the same thread as the UI.
//Do something to the UI thread here
}
};
}
SOURCE: http://steve.odyfamily.com/?p=12
Try using Project -> Clean then right click your project and find Fix Project Properties. Check your Build Path. It could be any one of these things. Restart eclipse, make sure your Android Manifest is targeting the correct API, 8 I assume?

Log in and delay second activity until results are posted

All! I am pretty new to Developing Android. I have run into many issues already and solved most of them myself, and some by searching here and on other sites. The problem I currently face now, I can't seem to find a solution for. It is close to what others on here have asked, but I can't find anything for my problem.
I am working on the beginning stages of my first big app, in which a user signs in to the fist page and is then allowed access to the rest of the app and features with. I am using basic examples right now of a simple log in app and it works fine, but when I try to delay the first activity from calling the second one until the results are posted, either it posts and doesn't call the second activity, or it doesn't post the results and moves on anyways. I am also currently trying to bundle the results and display them in the second activity. I Will change that later though, I just need to see if it will work right.
Here is my code:(not sure if I'm doing this right. It's my first time!)
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Login button clicked
ok = (Button)findViewById(R.id.btn_login);
ok.setOnClickListener(this);
result = (TextView)findViewById(R.id.lbl_result);
final Handler handler1 = new Handler();
handler1.postDelayed(new Runnable() {
#Override
public void run() {
ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final Bundle b = new Bundle();
EditText txt1 = (EditText)findViewById(R.id.editText1);
EditText txt2 = (EditText)findViewById(R.id.lbl_result);
b.putString("ID", txt1.getText().toString());
b.putString("PW", txt2.getText().toString());
final Handler handler2 = new Handler();
handler2.postDelayed(new Runnable() {
#Override
public void run() {
final Intent myIntent = new Intent(TempActivity.this, TempActivity2.class);
myIntent.putExtras(b);
startActivity(myIntent);
}
}, 3000);
}
});
}
}, 4000);
}
Am I just going about this the wrong way? Any help is greatly appreciated! I hate being a noob! Let me know if anymore information is needed!
Ohhhh... i dont know.. if it is actually right.. but as far as i understand your code... you are using
handler1.postDelayed(new Runnable() {
and in its runnable
public void run() {
ok.setOnClickListener(new View.OnClickListener() {
here.. you are setting onClickListener.. and it will happen after 4 seconds.. because of this line..
}, 4000);
so if you click before 4 seconds.. i think onclicklistener is not being set... so give some time.. like 4 seconds after the application starts
.. and then try clicking... i think then it should work..

android assign a drawable dynamicaly to a imageview

I have an array of drawables, that I would like to change by my own timer to a imageview.
(i tried the other option with xml and setBackgroundResource, but does not work for me as I have hundret of pics and always got memory problem as it looks android assign already the whole memory for all pics at once. (just in this demo i shorted it to 4 images)
Ok, so first i make my array
private static int[] draws = {
R.drawable.frankiearmevor_0001,
R.drawable.frankiearmevor_0002,
R.drawable.frankiearmevor_0003,
R.drawable.frankiearmevor_0002
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imgView = (ImageView) findViewById(R.id.fredi);
// create timer
Timer updateProgressTimer = new Timer();
updateProgressTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
myloop();
}
}, 0, 150);
}
int mycounter;
public void myloop()
{
mycounter++;
if (mycounter > 4) mycounter = 1;
imgView.setImageResource(draws[mycounter-1]);
String hallo; hallo = "now: "+mycounter;
Log.d("1",hallo);
}
when I assign only a fixed image: imgView.setImageResource(draws[2]);
it shows that fine and I see also my thread is logged fine, but when I exchange the
fixed resource draws[2] into a dynamic draws[mycounter-1] .. i just get a black screen, no error, nothing.
what to do, so i will show the images :)
thx
chris
EDIT: 22. August:
I tried now with the comment I got, it compiles fine, but somehow there is an error i guess.. it crash:
imgView = (ImageView) findViewById(R.id.fredi);
Timer updateProgressTimer = new Timer();
updateProgressTimer.scheduleAtFixedRate(new TimerTask()
{
#Override
public void run()
{
//myloop();
imgView.post (new Runnable()
{
public void run()
{
mycounter++;
if (mycounter > 10) mycounter = 1;
imgView.setImageResource(draws[1]);
//imgView.invalidate();
String hallo; hallo = "now: "+mycounter;
Log.d("1",hallo);
}
});
}
}, 0, 150);
The ImageView update should happen on the UI Thread...
Refer this answer. The TimerTask runs on a different thread, so you've to use the imgView.post() to update the UI Component.
Are you sure you need to update the Component every 150ms? That's very expensive.
Good Luck.

Categories

Resources