Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display Toast from a Service after main Activity finishes?

UPDATE: I don't agree that this is a duplicate - because I am seeking for a way to exit the main app and still show a Toast from the service.

In a very simple test app I have 2 buttons:

screenshot

Clicking any of the buttons will run a service with a corresponding action string ("open" or "flash") -

OpenActivity.java:

public class OpenActivity extends Activity {
    private Intent mServiceIntent;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_open);
        mServiceIntent = new Intent(this, RegionService.class);
   }

    public void openCar(View v) {
        mServiceIntent.setAction("open");
        startService(mServiceIntent);
    }

RegionService.java:

public class RegionService extends IntentService {
    private static final String TAG = "RegionService";

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG, "Received an intent: " + intent);
        String action = intent.getAction();
        Log.d(TAG, "Received an action: " + action);

        if(action.equals("open")) {
            Toast.makeText(this, 
                    getString(R.string.car_opened), 
                    Toast.LENGTH_SHORT).show();
        } 

Unfortunately my app crashes with:

D/RegionService(24506): Received an intent: Intent { act=open cmp=de.afarber.mynotification/.RegionService }

D/RegionService(24506): Received an action: open

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

Being an Android programming newbie I wonder How to display a Toast from Service in a correct way?

I think I've already seen Toasts at Android Home (i.e. there was no Activity on the device screen and still there were Toasts).

My background: I would like to monitor a beacon device from my service and show some text Toasts - even when my app has been closed.

like image 633
Alexander Farber Avatar asked Dec 08 '14 12:12

Alexander Farber


People also ask

Can we show toast from service in Android?

To display a simple Toast message, we can do the following. // Declare the parameters to use for the Toast Context context = getApplicationContext(); // in an Activity, you may also use "this" // in a fragment, you can use getActivity() CharSequence message = "I'm an Android Toast!"; int duration = Toast.

How to display Toast in Android?

Display the created Toast Message using the show() method of the Toast class. The code to show the Toast message: Toast. makeText(getApplicationContext(), "This a toast message", Toast.

What is Toast in Android explain the various methods of Toast class?

A toast provides simple feedback about an operation in a small popup. It only fills the amount of space required for the message and the current activity remains visible and interactive. Toasts automatically disappear after a timeout.


3 Answers

OnHandleIntent will run in a differant Thread so you are showing Toast in a thread which is not allowed in android

so change your code like this

Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {

    @Override
    public void run() {
         Toast.makeText(getApplicationContext(), 
                       getString(R.string.car_opened), 
                       Toast.LENGTH_SHORT).show();              
    }
});

From this dead thread in service

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.

like image 128
kalyan pvs Avatar answered Sep 20 '22 03:09

kalyan pvs


An IntentService has a few limitations:

It can't interact directly with your user interface. To put its results in the UI, you have to send them to an Activity.

Everything is happening in the background thread and not on the UI thread, so you need a different way as shown below:

@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();                
        } 
    }); 
} 

Source: Toast created in an IntentService never goes away

like image 38
An SO User Avatar answered Sep 18 '22 03:09

An SO User


OnHandleIntent is called on a background thread, and any attempt to touch the UI will result in a crash. Use an Handler to post a Runnable on the UI Thread to show your toast.

private class MyRunnable implements Runnable {

   final int mTextId = -1; 
   final Context mContext;
   public MyRunnable(Context c, int textId) {
       mTextId = textId;
       mContext = c;
   }

   @Override
   public void run() {
       Toast.makeText(mContext, 
           getString(mTextId), 
           Toast.LENGTH_SHORT).show();             
    }
}

   Handler handler = new Handler();
   handler.post(new MyRunnable(this, R.string.car_opened));
like image 25
Blackbelt Avatar answered Sep 20 '22 03:09

Blackbelt