2012年1月4日水曜日

IntentServiceでToastを表示する

IntentServiceではToastを表示できない。
また、不要になったらきっちり死ぬようにしているServiceでもToastが表示できない。
出力されている警告を見ると、Toast表示を行うUIスレッドが死んでるから表示要求が届かなかったとのこと。少なくとも表示メッセージがUIスレッドに届くまではServiceが生存してなきゃいけないらしい。

ということで、Toast表示用のServiceを作った。
public class ToastService extends Service {
    private static final String TAG = ToastService.class.getName();

    public static void showToast(Context context, int strResId) {
        Intent service = new Intent(context, ToastService.class);
        service.putExtra(EXTRA_MESSAGE, strResId);
        context.startService(service);
    }


    private ToastHandler mToastHandler;

    public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";

    public static final int MESSAGE_DISPLAY = 0;
    public static final int MESSAGE_TIMER = 1;

    private class ToastHandler extends Handler {
        private Toast mToast = null;
        private int curMsgResId;

        public ToastHandler() {
            super();
        }

        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
            case MESSAGE_DISPLAY: {
                if (curMsgResId != msg.arg2) {
                    if (mToast != null) {
                        mToast.cancel();
                    }
                    curMsgResId = msg.arg2;
                    mToast = Toast.makeText(
                            getApplication(),
                            curMsgResId,
                            Toast.LENGTH_LONG);
                    mToast.show();
                }
                removeMessages(MESSAGE_TIMER);
                sendMessageDelayed(obtainMessage(MESSAGE_TIMER, msg.arg1, 0), 4 * 1000);
                break;
            }
            case MESSAGE_TIMER: {
                stopSelf(msg.arg1);
                break;
            }
            }
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mToastHandler = new ToastHandler();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int msgResId = intent.getIntExtra(EXTRA_MESSAGE, 0);
        Message msg = mToastHandler.obtainMessage(MESSAGE_DISPLAY, startId, msgResId);
        mToastHandler.sendMessage(msg);
        
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

1 件のコメント:

匿名 さんのコメント...

私もハマりかけていたのですが、以下のサイトが参考になりました。
http://stackoverflow.com/questions/5346980/intentservice-wont-show-toast