0

I used postDelayed for delaying dynamic duration. And I found it did not work correctly. Here is my source code.

public Runnable service = new Runnable() {
        public void run() {     
            endTimeHere = System.currentTimeMillis();
            Log.d("Time",(endTimeHere-startTimeHere)/1000);
            switch (step)
            {
                case 0: 
                    delay = 0;
                    step = 1;
                    break;
                case 1:
                    delay = 600;        //delay 10 min = 600 sec
                    step = 2;
                    break;

                case 2:     
                    delay = 1200;   //delay 20 min = 1200 sec
                    step = 3;
                    break;
                case 3:     
                    delay = 1800;   //delay 30 min = 1800 secs
                    step = 0;
                    break;
                default:
                    break;
            }
            startTimeHere = System.currentTimeMillis();
            handler.postDelayed(service, delay*1000);   
        }
    };

And I start and stop the handler in a BroadcastLintener.

public Handler handler = new  Handler();    
private BroadcastReceiver screenReceiver = new BroadcastReceiver()
    {
        public void onReceive(Context context, Intent intent)
        {
            String action = intent.getAction();
            if(Intent.ACTION_SCREEN_ON.equals(action))
            {
                handler.removeCallbacks(service);
            }
            else if(Intent.ACTION_SCREEN_OFF.equals(action))
            {
                handler.post(service);
            }
        }
    }

I'm sure that postDelayed is added in queue because the return value is true. However, the time duration I recorded is not matching with the delay value I set. For example, I set delay = 600 secs and the recorded duration = 958 secs.

Does anyone know why this happened?

iscnorthwind
  • 143
  • 1
  • 9

1 Answers1

0

Handlers are not perfect at firing exactly when they should. Other threads (like the UI thread) may take priority. Additionally, Android has overhead for processing the Intent. In other words, the handler may fire at 650ms due to delays in thread monitoring from the OS, but then the intent needs to be handled, the receiver instantiated, the intent processed, etc.

You may be better off sending the intent with the delay data and then have the service setup a queue and poll it frequently based on the expected delay. e.g. an event scheduled for 500ms in the future maybe should be polled every 50ms to see if the delay time has expired. While an event 10,000ms in the future can be polled at 5,000ms or 9,000ms and then increase the polling frequency as the time approaches.

Jim
  • 10,172
  • 1
  • 27
  • 36