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:
Cliquez sur l'un des boutons pour exécuter un service avec une chaîne d'action correspondante ("open" ou "flash") -
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);
}
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.
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.
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
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));
utilisez le code suivant:
runOnUiThread(new Runnable(){
public void run() {
// UI code goes here
}
});
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();
}
});