pie - android versiones
Toast "enviar mensaje a un controlador en un hilo muerto" (6)
Debe mostrar un brindis desde el hilo principal o no se mostrará en la pantalla. El controlador se ejecuta desde el subproceso en el que se creó. Si crea su controlador en onCreate de su servicio interno, debería funcionar de la forma prevista cuando envíe su mensaje.
Estoy tratando de mostrar un mensaje simple a través de Toast, y obtengo una Excepción de Tiempo de Ejecución "enviando un mensaje a un Controlador en un hilo muerto". La clase que está tratando de mostrar el mensaje de Toast extiende IntentService. La clase (C2DMReceiver) en realidad proviene del ejemplo de ChromeToPhone para C2DM. Aquí está el método:
/**
* 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);
}
}
Asumí, ya que la clase extiende IntentService que sería posible solicitar un mensaje simple de Toast desde aquí de esta manera. ¿No es esto correcto?
El método onMessage no fue llamado en el subproceso principal.
Así que necesitas hacer un nuevo controlador.
Aplica este código:
public class GCMIntentService extends GCMBaseIntentService
{
Handler handler;
public GCMIntentService()
{
handler = new Handler();
}
}
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();
Espera que esto se inicialice en el subproceso principal, pero eso no está garantizado, ya que se inicializará en cualquier subproceso que haga que la clase ejecute sus inicializadores estáticos. Reproducí este problema donde el controlador hace referencia a un subproceso de trabajo.
Un patrón común que hace que esto suceda es usar la clase IntentService. El código de ejemplo C2DM hace esto.
Una solución simple es agregar el siguiente código al método onCreate de la aplicación:
Class.forName("android.os.AsyncTask");
Esto forzará que AsyncTask se inicialice en el hilo principal. He archivado un error en esto en la base de datos de errores de Android. Consulte http://code.google.com/p/android/issues/detail?id=20915 .
Otra forma de cumplir con los mensajes de tostado en el hilo principal desde el fondo es usar un pequeño método de utilidad para esto. El truco es crear un controlador que se adjunte al looper 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();
}
});
}
}
Puede ejecutar su código en el hilo de la interfaz de usuario de esta manera:
runOnUiThread(new Runnable() {
public void run() {
try {
//YOUR CODE
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
}
});
Esto debería funcionar bien
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();
}
});
}
}