Safe Whileloop that runs every second

0

So I want a whileloop that runs every second but appearently using Thread.sleep(1000); , doesn't work as it makes the app freeze and crash with this error :

07-28 15:03:17.641: A/libc(5792): Fatal signal 6 (SIGABRT) at 0x00000280 (code=0), thread 5792 ()

So im guessing The loop im using isnt safe enough and uses too much resources the loop is running in a service and is initzalated by a actionbutton :)

while(buttonpressed != false);
        try {
            writer = new FileWriter(timedata);
                   writer.append(TIME);

                    writer.flush();
                    writer.close();   
                    Thread.sleep(1000);
        }       
java
android
asked on Stack Overflow Jul 28, 2014 by AmazingHorse • edited Jul 28, 2014 by AmazingHorse

3 Answers

2

Use AlarmManager instead.

Register your service to run said action every second (from this question):

  Intent myIntent = new Intent(context, MyServiceReceiver.class);
  PendingIntent pendingIntent = PendingIntent.getBroadcast(context,  0, myIntent, 0);

  AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
  Calendar calendar = Calendar.getInstance();
  calendar.setTimeInMillis(System.currentTimeMillis());
  calendar.add(Calendar.SECOND, 1); // first time
  alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000, pendingIntent);

What you were trying to do is call sleep(1000) on the UI thread (the thread responsible for updating the user-facing UI changes). That is a big no-no on Android, as it makes your app appear to be unresponsive.

EDIT for clarification after user comment:

I don't know how you are setting buttonpressed, but you probably want to use an OnTouchListener:

boolean shouldBeDoingThings = true;
writer = new FileWriter(timedata);
Button.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            shouldBeDoingThings = true;
            return true;
        }
        else  if(event.getAction() == MotionEvent.ACTION_UP){
            shouldBeDoingThings = false;
            return true;
        }
        return false;
    }
});

Then you use messages or intents to start the flow (with the AlarmReceiver sending a message to your Service to set shouldBeDoingThings to true).

After that, somewhere in your service, you can run:

class Task implements Runnable {

        private long lastUpdatedTime;

        public Task()
        {
                 lastUpdatedTime = 0;
        }

        @Override
        public void run() {
                if(shouldBeDoingThings)
                {
                    if(TIME - lastUpdatedTime > 1000)
                    {
                        writer.append(TIME);
                        writer.flush();
                        lastUpdatedTime = TIME;
                    }
                }
            }
        }
    }

All in all, always remember: never block the UI thread. This is applicable for most Mobile SDKs today.

Hope I cleared things up for you.

answered on Stack Overflow Jul 28, 2014 by Robin Eisenberg • edited May 23, 2017 by Community
0

Use this simple spinning loop,

long now = System.currentMillisec();
while(now < expectedElapsedTime){ now = System.currentMillisec(); }

You won't have the accurate type pause because after the thread sleeps and when it wakes up, it will be scheduled to the CPU-Scheduling and then it may not totally be 10 seconds(if that is the time you want it to stop.)

answered on Stack Overflow Jul 28, 2014 by Shayan Ahmad
0

I don't have the rest of your code to work with, but I managed to write a piece of code that does what you want: you can just change the print statement that I added with what you want to include. I think that what you're missing is the catch statement in the while loop.

public class StackOverflow 
{
    static boolean buttonpressed = true;
    public static void main(String[] args)
    {
    while(buttonpressed != false)
    {
    try 
    {
     System.out.println("hi");
        Thread.sleep(1000);
    }
    catch (Exception e)
    {

    }
    }
    }
}
answered on Stack Overflow Jul 28, 2014 by CodeWiz808

User contributions licensed under CC BY-SA 3.0