android, failing to use timer - android

I would like to change the background image of a frame layout per second. For this task I use timer and timertask classes but it does not seem to work as the initial background never changes and the pyhsical device that I test the following code terminates abnormally.
FrameLayout fl;
List<Integer> myList;
int i = 0;
TimerTask myTimerTask = new TimerTask()
{
public void run()
{
fl.setBackgroundResource(myList.get(i));
i++;
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myList = new ArrayList<Integer>();
myList.add(R.drawable.square1);
myList.add(R.drawable.square2);
myList.add(R.drawable.square3);
myList.add(R.drawable.square4);
myList.add(R.drawable.square5);
myList.add(R.drawable.square6);
myList.add(R.drawable.square7);
myList.add(R.drawable.square8);
myList.add(R.drawable.square9);
myList.add(R.drawable.square10);
myList.add(R.drawable.square11);
myList.add(R.drawable.square12);
fl = (FrameLayout)findViewById(R.id.frameLayout1);
long delay = 1000;
long period = 1000;
Timer t = new Timer();
t.schedule(myTimerTask,delay,period);
}
Where do I fail ? ^^
Thanks in advance for your time.

You should call invalidate() after setting the new background resource.

You can't access a view from a non UI thread like a timer. You need to have a handler to update the view and get the timer to send messages to it. And you need to stop i from going out of bounds, like:
TimerTask myTimerTask = new TimerTask() {
public void run() {
Message m = Message.obtain();
m.what = i;
myUpdateHandler.sendMessage(m);
i++;
if (i >= myList.size())
i = 0;
}
};
.
Handler myUpdateHandler = new Handler() {
/** Gets called on every message that is received */
#Override
public void handleMessage(Message msg) {
fl.setBackgroundResource(myList.get(msg.what));
}
};
.

Well, you got several problems on your code.
From your code it doesn't clear where the "fi" is initialized, is it before the timer callback is called? after?
What is the purpose of the int "i"? Shouldn't it be a class member?
You must stop the timer on the onDestroy of the Activity, otherwise you might get some undesired behavior when accessing the frame layout.
Anyway, try running the the following from the onCreate:
final FrameLayout fl = (FrameLayout)findViewById(R.id.frameLayout1); // You must have final here
final List<Integer> myList = <get it from where you need to>
int i = 0; // What is the purpose of this int? it passed by value to the callback - are you sure it is needed?
TimerTask myTimerTask = new TimerTask()
{
public void run()
{
fl.setBackgroundResource(myList.get(i));
i++; // Shouldn't it be a class member?
}
};

Related

The correct way to start animation as soon as fragment loads

I got a fragment in which there's an animation of a count down clock. I want to start the animation as soon as the fragment loads without any intervention from the user.
What I do now is calling the following method in onCreateView:
private void startCountDownAnimation()
{
final int totalSeconds = secondsToStart + minutesToStart * 60;
mRingProgressBar.setTotalSeconds(totalSeconds);
HandlerThread handlerThread = new HandlerThread("countdown");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable()
{
#Override
public void run()
{
timer.scheduleAtFixedRate(new TimerTask()
{
//int secondsPassed = 0;
int secondsLeft = totalSeconds;
#Override
public void run()
{
if(secondsLeft == 0)
{
//fragment transaction
timer.cancel();
}
//final int currentProgress = Math.round(((float) secondsPassed)/((float) totalSeconds)*100f);
getActivity().runOnUiThread(new Runnable()
{
#Override
public void run()
{
mRingProgressBar.setSeconds(secondsLeft);
secondsLeft--;
//secondsPassed++;
}
});
}
}, 0, 1000);
}
});
}
This seems to work including when the app goes to the background.
I just want to know if what I'm doing is the correct way to handle the animation:
1) Is onCreate the correct place to call this method?
2) Can I have some issues of the app going to the background or if the screen blackens after a while?
3)Anything else I should change?
You should not use a Timer inside an Handler as the Timer is already asynchronous. The Timer is known to generate memory leaks so I'd suggest to use a CountDownTimer instead.
You should probably create the timer in onCreate and start it in onResume and stop it in onPause. Then you update the view in the onTick but you probably need to check if the view is available or not (view != null)

I am looking to exit a handler and go back to activity code when it has done its job

I have been trying to figure out how to make a countdown timer using 'handler()' and i still don't know how to make it so the app will execute the line "Finished" when the countdown hits 0.
I am after whatever line of code is required for me to enter in the 'UpdateGUI()' to exit the runnable and go back to the main activity to display "Finished".
I have not been coding very long, so maybe it is an obvious answer, but I can't find it on any threads on this page...
Some help would be much appreciated :-)
Thank you
public class MainActivity extends AppCompatActivity {
int i = 10;
TextView tv;
final Handler myHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button but = (Button) findViewById(R.id.button);
but.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
tv = (TextView) findViewById(R.id.textView);
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
UpdateGUI();
}
}, 0, 1000);
tv = (TextView) findViewById(R.id.textView);
tv.setText("Finished");
}
});
}
private void UpdateGUI() {
if (i == 0) {
//this is where i need to enter the code!!
}
else
i--;
myHandler.post(myRunnable);
}
final Runnable myRunnable = new Runnable() {
public void run() {
tv.setText(String.valueOf(i));
}
};
}
If I understand you correctly in case you need to run your runnable after some period of time use Handler method postDelayed(runnable, timeOutInMillis)
UPDATE: example of handler timer
int timesRun;
Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
runTimer();
i++;
}
};
// call it in button callback
public void runTimer(){
// update your timer here
if (i != 10) // if 10 seconds not passed run it one more time
handler.postDelayed(runnable, 1000); // run every second
}
Note that this is not the most elegant way to do this, but still, it should work

Android sleep without thread

How can i make code sleep without threading / runnable. I require to modify layout in a android app, operate a method and reverse layout changes again. However this methods contains counters, whenever i have a inner class, like a runnable timertask or something simular the variable needs to be final, but then i cannot increase the counters.
ChangeLayout();
int round = 0;
while (isPlaying && round < 24){
round++;
int specificOccurrence = 0;
while (isPlaying && specificOccurence < 8) {
if (somethingSpecific){
specificOccurence++;
}
// operates this while somehow with a 1 second break;
// after that just continue.
waitASecondSomehow();
}
}
ReverseLayoutChanges();
Use a Handler to schedule work on the main thread using postDelayed:
Handler h = new Handler();
h.postDelayed(runnable, delayInMillis);
The runnable above is a Runnable instance that does what you want to execute on the main thread. Keep posting it at each interval, perhaps repeated within the runnable itself to schedule the next iteration.
You should use Timer for this.
Timer mUiUpdateTimer;
TimerTask uiUpdateTask;
int mistakes=0;
int periodTime=1000;
private void createTimeHandler()
{
mUiUpdateTimer = new Timer();
final Handler uiUpdateHandler = new Handler();
final Runnable uiUpdateRunnable = new Runnable() {
#Override
public void run() {
// other jobs
mistakes++;
}
};
uiUpdateTask = new TimerTask() {
#Override
public void run() {
//for safe UI handling
uiUpdateHandler.post(uiUpdateRunnable);
}
};
mUiUpdateTimer.scheduleAtFixedRate(uiUpdateTask, 0, periodTime);
}
Just Add bellow Handler inside your try block
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mistakes++;
}
}
}, 3000);

Making a simple counter that increments every second on android. What wrong am I doing?

Im writing code to display a counter that increments by 1 every second.
The app is getting forced closed before running with the error -
thread exiting with uncaught exception and No package identifier when getting value for resource number
public class MainActivity extends Activity {
Handler hand = new Handler();
TextView ti;
int i =0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ti = (TextView) findViewById(R.id.textView);
hand.postDelayed(run, 1000);
}
Runnable run = new Runnable() {
#Override
public void run() {
i++;
ti.setText(i);
}
};
}
What wrong am I doing ?
The method textView.setText(int id) takes an int as parameter. For e.g. R.string.app-name. When you pass i as parameter, it will check for id i in strings.xml. TextView also provides an overloaded method setText(CharSequence text), which you can use here.
textView.setText(""+i); or textView.setText(String.valueOf(i));
ti.setText(i) is trying to resolve a resource by the value of i.
Try ti.setText(String.valueOf(i)); instead.
If you need a precise timer, you should calculate a difference, from when started a timer, increment a variable in every call is not a accurate solution, here is the code, if you want a precise timer
private long startTime;
private final Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textView = (TextView) findViewById(R.id.textView);
startTime = System.currentTimeMillis();
handler.post(new Runnable() {
#Override
public void run() {
long diff = System.currentTimeMillis() - startTime;
textView.setText(Long.toString(diff / 1000));
handler.postDelayed(this, 1000);
}
});
}

Android: Nested TimerTask not stopping

I have some test code with nested TimerTasks, i.e. one task is called every 10s to change parameters and it starts another timer running some calcs every 100ms or so. When I call cancel on the first timer it cancels the outer TimerTask but the inner one keeps running.
What do I have to do to get the inner task stopped too? Note that in the following code the cancel() override never gets called, although the outer task does stop.
class CalcTask extends TimerTask
{
// randomly changes calc interval every time it is called
public void run(){
if (mTmr != null)
mTmr.cancel();
mTmr = null;
TimerTask calcTask = new TimerTask(){ public void run(){ Log.i("TempSensor","chad"); doCalcs(); } };
int min = Integer.parseInt(mEditThreadMin.getText().toString());
int max = Integer.parseInt(mEditThreadMax.getText().toString());
int interval = mRand.nextInt(max-min)+min + 1;
mTmr = new Timer(true);
mTmr.schedule(calcTask,0,interval);
}
#Override
public boolean cancel()
{
Log.i("TempSensor","Cancelling");
if(mTmr != null)
{
mTmr.cancel();
mTmr.purge();
}
return super.cancel();
}
private Random mRand = new Random();
private Timer mTmr = null;
};
... // later on
mTimerCalc1.scheduleAtFixedRate(new CalcTask(), 0, (int)10e3);

Categories

Resources