Toast created in an IntentService never goes away
Asked Answered
T

6

29

I have an IntentService that downloads some files. The problem is that I create a Toast inside the IntentService like this

Toast.makeText(getApplicationContext(), "some message", Toast.LENGTH_SHORT).show();

The Toast will never disappear event if I exit the app. The only way to destroy it is to kill the process.

What am I doing wrong?

Tantivy answered 21/7, 2010 at 5:56 Comment(2)
There's no reason not to create a Toast from a service. From the notification dev guide: >If you create a toast notification from a Service, it appears in front of the Activity currently in focus.Homelike
That must be wrong, because it doesn't work when you test it with IntentService. @rony's solution works best.Lowercase
P
-8

You shouldn't create Toasts from a Service. You should use a Notification instead.

Pacification answered 21/7, 2010 at 22:15 Comment(5)
Wrong. from developer.android.com/guide/topics/ui/notifiers/toasts.html "A toast can be created and displayed from an Activity or Service". Its not working because "Service" runs on Main thread, whereas "Intent service" run on another thread.Hollingshead
Just because you can do a thing doesn't mean you should do a thing. You shouldn't create toasts from a service.Pacification
@Qberticus, can you update your answer with a code example of how Notification would be used in this case?Positivism
Why should we use Notifications instead of Toasts from services? Is it because of a technical limitation? Is it because the user mightn't be looking at the screen?Barbarity
A notification would be a good solution. Only issue is that user may turn off notifications for an app.Mclaren
B
75

The problem is that IntentService is not running on the main application thread. you need to obtain a Handler for the main thread (in onCreate()) and post the Toast to it as a Runnable.

the following code should do the trick:

@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, "Hello Toast!", Toast.LENGTH_LONG).show();                
        }
    });
}
Balaklava answered 24/3, 2011 at 14:43 Comment(3)
@rkmax android studio for some reason defaults to import java.util.logging.Handler; (which is abstract) change it to import android.os.Handler;Yard
@rony If I call this from JNI I get a null pointer exception, any idea why that is? Do I need a new thread in JNI?Hoplite
Is new Handler() call expensive?Ursala
N
24

This works for me:

public void ShowToastInIntentService(final String sText) {
    final Context MyContext = this;

    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            Toast toast1 = Toast.makeText(MyContext, sText, Toast.LENGTH_LONG);
            toast1.show();
        }
    });
};
Noneffective answered 13/8, 2013 at 16:48 Comment(1)
Perfect solutionClinch
J
8

IntentService will create a thread to handle the new intent, and terminated it immediately once the task has done. So, the Toast will be out of controlled by a dead thread.

You should see some exceptions in the console when the toast showing on the screen.

Josefinejoseito answered 27/5, 2013 at 3:59 Comment(1)
+1 for pointing out worker thread mechanism in IntentService.Welford
C
1

For people developing in Xamarin studio, this is how its done there:

Handler handler = new Handler ();
handler.Post (() => {
    Toast.MakeText (_Context, "Your text here.", ToastLength.Short).Show ();
});
Crabber answered 2/12, 2014 at 6:18 Comment(0)
S
0

To show a toast when the user is in one of the application activity.

Just need a reference of the current activity, and call it with this sample code:

public void showToast(final String msg) {
    final Activity a = currentActivity;
    if (a != null ) {
        a.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                Toast.makeText(a, msg, Toast.LENGTH_SHORT).show();
            }
        });
    }
}

There is a lot of options to get the current activity, check this question: How to get current foreground activity context in android?

But I use this approach:

The application must have:

private Activity currentActivity = null;

public Activity getCurrentActivity() {
    return currentActivity;
}

public void setCurrentActivity(Activity mCurrentActivity) {
    this.currentActivity = mCurrentActivity;
}

Each activity must have:

@Override
protected void onResume() {
    super.onResume();
    ((MyApplication) getApplication()).setCurrentActivity(this);

}
@Override
protected void onPause() {
    super.onPause();
    ((MyApplication) getApplication()).setCurrentActivity(null);
}
Scales answered 13/6, 2013 at 21:35 Comment(2)
Call super.onPause() from onPauseEducative
Oh my god a bug!... But it's gone now.Arand
P
-8

You shouldn't create Toasts from a Service. You should use a Notification instead.

Pacification answered 21/7, 2010 at 22:15 Comment(5)
Wrong. from developer.android.com/guide/topics/ui/notifiers/toasts.html "A toast can be created and displayed from an Activity or Service". Its not working because "Service" runs on Main thread, whereas "Intent service" run on another thread.Hollingshead
Just because you can do a thing doesn't mean you should do a thing. You shouldn't create toasts from a service.Pacification
@Qberticus, can you update your answer with a code example of how Notification would be used in this case?Positivism
Why should we use Notifications instead of Toasts from services? Is it because of a technical limitation? Is it because the user mightn't be looking at the screen?Barbarity
A notification would be a good solution. Only issue is that user may turn off notifications for an app.Mclaren

© 2022 - 2024 — McMap. All rights reserved.