61

in my app I'm using IntentService for sending SMS.

    @Override
protected void onHandleIntent(Intent intent) {
    Bundle data = intent.getExtras();
    String[] recipients = null;
    String message = getString(R.string.unknown_event);
    String name = getString(R.string.app_name);
    if (data != null && data.containsKey(Constants.Services.RECIPIENTS)) {
        recipients = data.getStringArray(Constants.Services.RECIPIENTS);
        name = data.getString(Constants.Services.NAME);
        message = data.getString(Constants.Services.MESSAGE);
        for (int i = 0; i < recipients.length; i++) {
            if(!StringUtils.isNullOrEmpty(recipients[i])) {
                try {
                    Intent sendIntent = new Intent(this, SMSReceiver.class);
                    sendIntent.setAction(Constants.SMS.SEND_ACTION);
                    PendingIntent sendPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, sendIntent, PendingIntent.FLAG_UPDATE_CURRENT);
                    Intent deliveryIntent = new Intent(this, SMSReceiver.class);
                    deliveryIntent.setAction(Constants.SMS.DELIVERED_ACTION);
                    PendingIntent deliveryPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, deliveryIntent, PendingIntent.FLAG_UPDATE_CURRENT);
                    SmsManager.getDefault().sendTextMessage(recipients[i].trim(), null, "[" + name + "] " + message, sendPendingIntent, deliveryPendingIntent);
                } catch (Exception e) {
                    Log.e(TAG, "sendTextMessage", e);
                    e.printStackTrace();
                    Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
                    MainActivity.instance.writeToLogFile(e.getMessage(), System.currentTimeMillis());                       
                }
            }
        }
    }
}

when running the app, I get the following error:

W/MessageQueue(7180): Handler (android.os.Handler) {42586468} sending message to a Handler on a dead thread
W/MessageQueue(7180): java.lang.RuntimeException: Handler (android.os.Handler) {42586468} sending message to a Handler on a dead thread
W/MessageQueue(7180):   at android.os.MessageQueue.enqueueMessage(MessageQueue.java:294)
W/MessageQueue(7180):   at android.os.Handler.enqueueMessage(Handler.java:618)
W/MessageQueue(7180):   at android.os.Handler.sendMessageAtTime(Handler.java:587)
W/MessageQueue(7180):   at android.os.Handler.sendMessageDelayed(Handler.java:558)
W/MessageQueue(7180):   at android.os.Handler.post(Handler.java:323)
W/MessageQueue(7180):   at android.widget.Toast$TN.hide(Toast.java:367)
W/MessageQueue(7180):   at android.app.ITransientNotification$Stub.onTransact(ITransientNotification.java:55)
W/MessageQueue(7180):   at android.os.Binder.execTransact(Binder.java:351)
W/MessageQueue(7180):   at dalvik.system.NativeStart.run(Native Method)

My SMSReceiver is located in another class. How can i solve this problems? Thanks; Eyal.

petey
  • 16,914
  • 6
  • 65
  • 97
eyal
  • 2,379
  • 7
  • 40
  • 54

3 Answers3

164

The problem here is that you are creating a Toast inside a thread that is managed by the IntentService. The system will use the Handler associated with this thread to show and hide the Toast.

First the Toast will be shown correctly, but when the system tries to hide it, after the onHandleIntent method has finished, the error "sending message to a Handler on a dead thread" will be thrown because the thread on which the Toast was created is no longer valid, and the Toast will not disappear.

To avoid this you should show the Toast posting a message to the Main Thread. Here's an example:

    // create a handler to post messages to the main thread
    Handler mHandler = new Handler(getMainLooper());
    mHandler.post(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(getApplicationContext(), "test", Toast.LENGTH_SHORT).show();
        }
    });
Murtaza Khursheed Hussain
  • 15,176
  • 7
  • 58
  • 83
rubenlop88
  • 4,171
  • 2
  • 28
  • 32
  • @rubenlop88 I still don't get how the problem is solved when I use a runnable. What I understand is that the problem is, when onHandle is called, it will call the Toast, and then it will exit, and after that Toast will be hidden? Is that the sequence, but then if that is the case, then when I use runnable, then also, the runnable thread should kill itself before it hides the Toast. What am I missing here? Thanks – Kraken Sep 14 '14 at 10:40
  • @Kraken The `Runnable` is used to create the `Toast` on the main thread of the application. If you don't use a `Runnable` the `Toast` will be created in a thread managed by the `IntentService`. If the thread of the `IntentService` finishes too quickly then the `Toast` wont be dismissed. – rubenlop88 Sep 29 '14 at 03:39
  • 1
    Great. work properly, but for my case the problem was that Toast is not shown at all. – Amt87 Apr 05 '15 at 08:00
5

Display Toast on IntentService. try this code..

@Override
public void onCreate() {
    super.onCreate();
    mHandler = new Handler();
}

@Override
protected void onHandleIntent(Intent intent) {
    mHandler.post(new Runnable() {            
        @Override
        public void run() {
            Toast.makeText(MyIntentService.this, "Test", Toast.LENGTH_LONG).show();                
        }
    });
}

source :- https://stackoverflow.com/a/5420929/4565853

Community
  • 1
  • 1
Finava Vipul
  • 998
  • 1
  • 11
  • 24
2

I think you need to check a condition:

mHandler.getLooper().getThread().isAlive()

The application will just warn you about this error. Of course it s mostly not fatal one. But if there are many spawned usages of this handler these warnings will slow down the application.

CodeToLife
  • 3,672
  • 2
  • 41
  • 29