0

I'm using AlarmManager to wake up the device and run some tasks. These are done inside an IntentService, so on a thread separate from the main one. When the work is done, I'd like to show a toast. However, I'm getting this log warning and no toast is shown:

W/MessageQueue﹕ Handler (android.os.Handler) {b12716d0} sending message to a Handler on a dead thread
    java.lang.RuntimeException: Handler (android.os.Handler) {b12716d0} sending message to a Handler on a dead thread
            at android.os.MessageQueue.enqueueMessage(MessageQueue.java:320)
            at android.os.Handler.enqueueMessage(Handler.java:626)
            at android.os.Handler.sendMessageAtTime(Handler.java:595)
            at android.os.Handler.sendMessageDelayed(Handler.java:566)
            at android.os.Handler.post(Handler.java:326)
            at android.widget.Toast$TN.hide(Toast.java:370)
            at android.app.ITransientNotification$Stub.onTransact(ITransientNotification.java:55)
            at android.os.Binder.execTransact(Binder.java:404)
            at dalvik.system.NativeStart.run(Native Method)

I know there are a few other questions on this topic, but I've tried all the suggestions and none worked. I'm using:

Handler handler = new Handler();
handler.post(new Runnable()
{
    @Override
        public void run()
            {
                Toast.makeText(context, R.string.toast, Toast.LENGTH_LONG).show();
            }
});

I've also tried:

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

I'm still getting the warning and no toast.

What is the way to show this toast from my IntentService?

Thanks in advance!

Andrei
  • 23
  • 5
  • 2
    Use a `Notification` instead of a `Toast`. Reasoning? In general `Services` shouldn't interfere with the UI (except maybe if an associated `Activity` from your app is currently showing) and also a `Toast` is very short lived (just a few seconds). If the object of the exercise is to convey some useful information to the user then it would be easy for the user to be looking away from their device and completely miss the `Toast` - a waste of your time and code and of no use to the user. A `Notification` serves a better purpose. – Squonk Aug 17 '14 at 17:16
  • Yes, I realised that shortly after I posted the question and changed my app accordingly. Nonetheless, I though it would still be a good topic, academically speaking. Thank you for the answers and comments! – Andrei Aug 26 '14 at 11:32

1 Answers1

4

First of all, you really shouldn't send Toast messages from a Service or from any task that wasn't initiated by the user a very short time ago. Otherwise the user won't know where the Toast is originating from; she can't even be sure from which app it comes - absolutely confusing and bad practice in general.

But to answer your question, when you create a Handler with new Handler() then it is attached to the thread it was created on. Thus, if you want to post something to the UI/main thread from a service (from any thread) then you should create the Handler in, for instance, the onCreate() method; because onCreate(), and usually any Android callback method, is called on the UI thread. So:

public class MyService extends Service {

    private Handler mMainThreadHandler;

    @Override
    public void onCreate() {
        mMainThreadHandler = new Handler();
    }

    [...]
}

Or, of you want to create a Handler that is attached to the UI thread and don't want to care about where it is created then use new Handler(Looper.getMainLooper()). This way it is attached to the main looper; which is the looper of the main thread.

public class MyService extends Service {

    private Handler mMainThreadHandler = new Handler(Looper.getMainLooper());

    [...]
}

I know you wrote you tried it; but it should work.

Though, what I would recommend you is not to bother with Handlers; use Needle instead. Needle is a simple and powerful multithreading library for Android. With it, you can say things like:

Needle.onMainThread().execute(new Runnable() {
    @Override
    public void run() {
        // e.g. change one of the views
    }
});

Check it out on GitHub: https://github.com/ZsoltSafrany/needle

Zsolt Safrany
  • 13,290
  • 6
  • 50
  • 62