10
final Handler handler = new Handler();
LOG.d("delay");
handler.postDelayed(new Runnable() {
    @Override public void run() {
        LOG.d("notify!");
        //calling some methods here
    }
}, 2000);

The "delay" does shows in the log, but not others at all. And the method called in the run() is not called at all also. Can anyone help explain why this happens, am I doing anything wrong?

The class that has this code extends IntentService, will this be a problem?

============================

UPDATE: I put this code in the class that extends IntentService. The only place I found it worked was in the constructor. But I need to put it in the onHandleIntent method. So I checked the documentation for onHandleIntent and it said:

This method is invoked on the worker thread with a request to process.Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf.

So based on the result I get, I feel like I cannot use postDelayed in "worker thread". But can anyone explain this a bit more, like why this is not working in worker thread? Thanks in advance.

Zip
  • 809
  • 2
  • 14
  • 30
  • 2
    is import from `os.Handler` ? – N J Apr 30 '16 at 00:17
  • @NJ yes it is. android.os.Handler – Zip Apr 30 '16 at 00:24
  • Where are you calling this from? Needs context. – Nathanael Apr 30 '16 at 00:46
  • 1
    Why is the @Override next to public and not above? Why is it "LOG.d" and not "Log.d("your tag", "notify!")" ? If you indeed imported os.Handler then it should work. – UFC Insider Apr 30 '16 at 01:08
  • @Nathanael I'm calling this to delay a notification for 2 seconds before it shows up. Not sure if this is the right place to call. Can you explain where I should call the handler from? – Zip Apr 30 '16 at 03:20
  • @UFCInsider it shouldn't matter if the override is next to public, it's automatically generated by IDE. Also the "LOG" is the variable name of a logger. – Zip Apr 30 '16 at 03:21
  • 1
    IntentService is usually used for long tasks that don't require comminucation with the Main thread. maybe explain what you're trying to achieve – UFC Insider Apr 30 '16 at 12:50
  • @UFCInsider this class is used to send notifications when necessary, say SCREEN_ON. but what i want to do is the delay the showing of notification for 30s. So that only after screen is on for 30s, the notification can be show. – Zip May 01 '16 at 04:19
  • How did you resolve this? I'm running into something similar... just that I'm using the handler.sendEmptyMessageDelayed instead, in intentservice... my next try would've been where you got stuck... my screen is also on, so it should be a wakelock issue either... – AA_PV May 25 '17 at 21:52
  • This might resolve the problem, yet to try... However, doesn't explain what the problem is... https://stackoverflow.com/a/21407206/4411645 – AA_PV May 25 '17 at 21:55
  • Tried and confirmed, using normal service instead of IntentService resolves the problem – AA_PV May 25 '17 at 22:18

6 Answers6

17

Convert

final Handler handler = new Handler();

to

final Handler handler = new Handler(Looper.getMainLooper());

This worked for me.

Kivvil
  • 211
  • 3
  • 6
12

You are using looper of the main thread. You must create a new looper and then give it to your handler.

HandlerThread handlerThread = new HandlerThread("background-thread");
handlerThread.start();
final Handler handler = new Handler(handlerThread.getLooper());
handler.postDelayed(new Runnable() {
    @Override public void run() {
        LOG.d("notify!");
        // call some methods here

        // make sure to finish the thread to avoid leaking memory
        handlerThread.quitSafely();
    }
}, 2000);

Or you can use Thread.sleep(long millis).

try {
    Thread.sleep(2000);
    // call some methods here

} catch (InterruptedException e) {
    e.printStackTrace();
}

If you want to stop a sleeping thread, use yourThread.interrupt();

Ashwin
  • 7,277
  • 1
  • 48
  • 70
1

this is how i use handler:

import android.os.Handler;

Handler handler;
//initialize handler
handler = new Handler();

//to start handler
handler.post(runnableName);

private Runnable runnableName= new Runnable() {
        @Override
        public void run() {
            //call function, do something
            handler.postDelayed(runnableName, delay);//this is the line that makes a runnable repeat itself
        }
};
rmanalo
  • 342
  • 3
  • 23
  • Thanks for answering but it's not working. I don't know if its because i cannot put this guy in some threads or something else. – Zip Apr 30 '16 at 09:16
  • but I can't import android.os.Handler in my project. – Prince Dholakiya Feb 22 '19 at 13:01
  • shouldn't ```runnableName``` be assigned before calling ```handler.post```? – kbsbng Apr 03 '19 at 03:49
  • @kbsbng no, just think of it as a method. – rmanalo Apr 05 '19 at 01:17
  • @Zip I don't think you should combine a `Thread` and a `Handler`. They kinda do the same thing so you just need to choose which one to use. – rmanalo Apr 05 '19 at 01:22
  • @DPrince try to remove the import statement on the top of your code, if you placed it there. Sometimes, if you got auto-import turned-on, Android Studio will import the correct one. If not, the word `Handler` should be in red. Place your cursor over it. Then `Handler` would have an underscore, press Alt+Enter. The import options will appear and choose there `os.Handler`. – rmanalo Apr 05 '19 at 01:26
0

Handlers and Services will be predictable when the device screen is on. If the devices goes to sleep for example the Handler will not be a viable solution.

A much more better and reliable solution will be to use: AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

0

IntentService is not designed for such scenario. You can use a regular Service instead. You can put the handler inside the onStartCommand(). Don't forget to call stopSelf() on the Service instance to shut it down after the handler.postDelayed(){}

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
BriniH
  • 35
  • 11
0

The most simple is to wait before ending onHandleIntent():

SystemClock.sleep(2000);
Bruno L.
  • 457
  • 6
  • 8