2010-12-14 14 views
20

Estoy tratando de mostrar un mensaje simple a través de Toast, y estoy recibiendo una excepción RunTime "enviando un mensaje a un controlador en un hilo muerto". La clase que intenta mostrar el mensaje Toast extiende IntentService. La clase (C2DMReceiver) en realidad proviene del ejemplo de ChromeToPhone para C2DM. Aquí está el método:Toast "enviando un mensaje a un controlador en un hilo muerto"

/** 
* Called when a cloud message has been received. 
*/ 
@Override 
public void onMessage(Context context, Intent intent) { 
    Log.i(LOG_TAG, "A message notification has occured with the cloud."); 

     Log.i(LOG_TAG, "Showing toast message of the broadcast..."); 
     Toast toast = Toast.makeText(context, "Some text", Toast.LENGTH_LONG); 
     toast.show(); 

     Log.i(LOG_TAG, "Sending notification of the broadcast..."); 
     LauncherUtils.generateNotification(this, "this is where the text would go.", "Broadcast", intent); 

    } 
} 

que supone ya la clase amplía IntentService que sería posible solicitar un mensaje simple tostada de aquí de esta manera. ¿No es esto correcto?

Respuesta

0

Debe mostrar un brindis por el hilo principal o no se mostrará en la pantalla. El controlador se ejecuta desde la secuencia en la que se creó. Si crea su controlador en onCreate of intentservice, debería funcionar como estaba previsto cuando envíe su mensaje.

+0

No estoy seguro de entender, ya que no hay ninguna referencia directa al controlador del objeto tostado Implementé el método onCreate, pero sigo obteniendo la excepción de thread inactivo. ¿Cuál es la forma correcta de crear un controlador en esta situación? Este es mi onCreate, con controlador Handler protegido; @Override public void onCreate() { super.onCreate(); manejador = new Handler() { @ Override pública handleMessage vacío (msg Mensaje) { Log.i (LOG_TAG, "En handleMessage ..."); } }; } – John

28

Esto se debe a un error en AsyncTask en el marco de Android. AsyncTask.java tiene el siguiente código:

private static final InternalHandler sHandler = new InternalHandler(); 

Se espera que esto se debe inicializar en el hilo principal, pero que no está garantizada ya que se iniciará en el que sea el hilo que pasa a causar la clase para ejecutar sus inicializadores estáticos. Reproduje este problema donde el Manejador hace referencia a un hilo de trabajo.

Un patrón común que hace que esto suceda es el uso de la clase IntentService. El código de muestra C2DM hace esto.

Un simple solución es agregar el código siguiente al método onCreate de la aplicación:

Class.forName("android.os.AsyncTask"); 

Esto obligará AsyncTask que ser inicializado en el hilo principal. Archivé un error en esto en la base de datos de errores de Android. Ver http://code.google.com/p/android/issues/detail?id=20915.

+0

Muchas gracias, acabo de notar que esto sucede al azar, y su solución resolvió el problema. –

+4

Hice esto y no ayudó ni un poco. Siempre cuando recibió una notificación c2dm, registra la misma excepción. – Ixx

+0

Tampoco funcionó para mí. – easycheese

24
public class NetworkService extends IntentService { 
    Handler mMainThreadHandler = null; 

    public NetworkService() { 
     super(NetworkService.class.getName()); 

     mMainThreadHandler = new Handler(); 
    } 

    @Override 
    protected void onHandleIntent(Intent arg) { 
     System.out.printf("Network service intent handling: %s\n", arg.toString()); 
     mMainThreadHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       Toast.makeText(getApplicationContext(), "BusyBox updated", Toast.LENGTH_LONG).show(); 
      } 
     }); 
    } 
} 
+0

[Esto funciona para mí] ¿Puede alguien explicar por favor qué está sucediendo aquí y por qué funcionó? –

+3

Como [Jonathan Perlow declaró en su respuesta] (http://stackoverflow.com/a/7818794/1208581), hay un error en el Android Framework, que causa un Toast, que no se crea en el hilo principal, para ejecutar en un controlador, que no está conectado al hilo principal. Al crear 'mMainThreadHandler' en el hilo principal (en el constructor), nos aseguramos de que Toast se ejecute en el hilo principal. De esa forma resolvemos el error. – sulai

0

El método onMessage no se invocó en Main Thread.

Así que debe crear un nuevo controlador.

aplicación de este código:

public class GCMIntentService extends GCMBaseIntentService 
{ 
    Handler handler; 
    public GCMIntentService() 
    { 
     handler = new Handler(); 
    } 
} 
9

Otra manera de lograr el tostado mensajes en el hilo principal del fondo es utilizar un método de utilidad pequeña para esto. El truco es crear un controlador que esté unido al enlazador del hilo principal (Looper.getMainLooper()).

public class ToastUtils { 

    public static void showToastInUiThread(final Context ctx, 
     final int stringRes) { 

     Handler mainThread = new Handler(Looper.getMainLooper()); 
     mainThread.post(new Runnable() { 
      @Override 
      public void run() { 
       Toast.makeText(ctx, ctx.getString(stringRes), Toast.LENGTH_SHORT).show(); 
      } 
     }); 
    } 
} 
+0

Consejo muy útil. Funciona de maravilla –

0

Puede ejecutar el código en el subproceso de interfaz de usuario de la siguiente manera:

runOnUiThread(new Runnable() { 
    public void run() { 
    try { 
    //YOUR CODE 
    } catch (Exception e) { 
    Log.d(TAG, e.getMessage()); 
    } 
} 
}); 

Esto debería funcionar bien

Cuestiones relacionadas