web-dev-qa-db-fra.com

Comment afficher Toast à partir d'un service une fois l'activité principale terminée?

MISE À JOUR: Je ne suis pas d'accord pour dire qu'il s'agit d'un doublon - parce que je cherche un moyen de quitter l'application principale tout en affichant un toast de la un service.

Dans ne application de test très simple J'ai 2 boutons:

screenshot

Cliquez sur l'un des boutons pour exécuter un service avec une chaîne d'action correspondante ("open" ou "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();
        } 

Malheureusement, mon application se bloque avec:

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)

Être un Android débutant en programmation je me demande Comment afficher un Toast du service de manière correcte?

Je pense que j'ai déjà vu Toasts sur Android Home (c'est-à-dire qu'il n'y avait pas d'activité sur l'écran de l'appareil et qu'il y avait toujours des toasts).

Mes antécédents: Je voudrais surveiller un périphérique de balise de mon service et afficher du texte Toasts - même lorsque mon application a été fermée.

13
Alexander Farber

OnHandleIntent s'exécutera dans un Thread différent, vous affichez donc Toast dans un fil de discussion qui n'est pas autorisé dans Android

alors changez votre code comme ça

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

De cela thread mort en service

IntentService créera un thread pour gérer la nouvelle intention et la terminera immédiatement une fois la tâche terminée. Ainsi, le Toast sera hors de contrôle par un thread mort.

Vous devriez voir quelques exceptions dans la console lorsque le toast s'affiche à l'écran.

39
kalyan pvs

Un IntentService a quelques limitations:

Il ne peut pas interagir directement avec votre interface utilisateur. Pour mettre ses résultats dans l'interface utilisateur, vous devez les envoyer à une activité.

Tout se passe dans le thread d'arrière-plan et non sur le thread d'interface utilisateur, vous avez donc besoin d'une manière différente comme indiqué ci-dessous:

@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 créé dans un IntentService ne disparaît jamais

5
Little Child

OnHandleIntent est appelé sur un thread d'arrière-plan et toute tentative de toucher l'interface utilisateur entraînera un plantage. Utilisez un gestionnaire pour publier un Runnable sur le thread d'interface utilisateur pour montrer votre 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));
2
Blackbelt

utilisez le code suivant:

  runOnUiThread(new Runnable(){
     public void run() {
          // UI code goes here
     }
    });
1
TechHelper

Ce problème est dû au fait de ne pas exécuter le Toast à partir de main_thread, et pour le résoudre, lors de la création de l'activité, enregistrez son contexte à partir de la méthode onCreate():

public static Context ctx;

// the method responsible for running the MainActivity
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ctx = this;
}

puis, dans le service, ajoutez un gestionnaire et exécutez un thread à partir de celui-ci (car le gestionnaire est exécuté via le thread principal):

    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(OpenActivity.ctx, getString(R.string.car_opened),
                    Toast.LENGTH_SHORT).show();
        }
    });
0
Muhammed Refaat