Подтвердить что ты не робот

Toast "отправляет сообщение обработчику по мертвой теме"

Я пытаюсь показать простое сообщение через Toast, и я получаю исключение RunTime Exception, отправляя сообщение обработчику по мертвому потоку. Класс, который пытается показать сообщение Toast, расширяет IntentService. Класс (C2DMReceiver) фактически исходит из примера ChromeToPhone для C2DM. Вот способ:

/**
 * 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);

    }
}

Я предположил, что, поскольку класс расширяет IntentService, можно было бы здесь запросить простое сообщение Toast. Разве это не так?

4b9b3361

Ответ 1

Это связано с ошибкой в ​​AsyncTask в платформе Android. AsyncTask.java имеет следующий код:

private static final InternalHandler sHandler = new InternalHandler();

Он ожидает, что это будет инициализировано в основном потоке, но это не гарантируется, так как оно будет инициализировано в зависимости от того, какой поток произошел, чтобы заставить класс запускать свои статические инициализаторы. Я воспроизвел эту проблему, когда обработчик ссылается на рабочий поток.

Общим шаблоном, который вызывает это, является использование класса IntentService. Код примера C2DM делает это.

Простым обходным путем является добавление следующего кода в метод onCreate:

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

Это приведет к инициализации AsyncTask в основном потоке. Я зарегистрировал ошибку об этом в базе данных ошибок Android. См. http://code.google.com/p/android/issues/detail?id=20915.

Ответ 2

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

Ответ 3

Другой способ выполнения сообщений обжарки в основном потоке из фона - использовать для этого небольшой метод. Хитрость заключается в создании обработчика, который прикреплен к петлевому механизму основного потока (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();
            }
       });
    }
}

Ответ 4

Вы должны отображать тост из основного потока или он не будет отображаться на экране. Обработчик выполняется из потока, в котором он был создан. Если вы создаете свой обработчик в onCreate вашего intentservice, он должен работать так, как предполагалось, когда вы отправляете свое сообщение.

Ответ 5

Метод onMessage не вызывается в главной теме.

Итак, вам нужно создать новый обработчик.

Применить этот код:

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

Ответ 6

Вы можете запустить свой код в потоке ui следующим образом:

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

Это должно работать нормально