push通知とottoで擬似チャット

Websocketでチャットを実装するのはなかなか大変だが、新着メッセージのプッシュ通知の仕組みが既にあれば、ottoと組み合わせて擬似的にリアルタイム更新が可能。
もちろんプッシュ通知にはタイムラグが発生するし、そもそも着信が保証されるものでもないので、あくまで擬似的なもの。

具体的には、通知レシーバークラスからottoでイベントを投げ、チャット画面Activityのイベントコールバックでリストを更新する。以上。

Otto : square社製の軽量イベントバスライブラリ
http://square.github.io/otto/

```java:プッシュ通知を受け取るレシーバクラス
public class NotificationReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {
            if(intent!=null){
                Bundle extras = intent.getExtras();
                // GCMからpushされたデータのパース
                if(extras!=null){
                    for(String key: extras.keySet()){
                        if(key.equals("result")) {
                            strResult = extras.getString(key);
                        }
                    }
                    if(strResult != null) {
                        Gson gson = new GsonBuilder()
                            .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                            .registerTypeAdapter(Date.class, new DateTypeAdapter())
                            .create();
                        NewMessage newMessage = gson.fromJson(strResult, NewMessage.class);
                        if (newMessage != null && strResult != null) {
                            boolean isForeground = false;
                            // 起動中のプロセスをすべてチェックしてアプリがバックグラウンドかどうかをチェックする
                            ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
                            List<ActivityManager.RunningAppProcessInfo> processInfoList = am.getRunningAppProcesses();
                            for( ActivityManager.RunningAppProcessInfo info : processInfoList) {
                                if (info.processName.equals(context.getPackageName())) {
                                    if (info.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                                        isForeground = true;
                                    } else {
                                        isForeground = false;
                                    }
                                }
                            }
                            if (isForeground) {
                        　　　　　　　　    　// イベント発行
                          　　　　　    BusHolder.get().post(new NewMessageEvent(newMessage.name, newMessage.body));
                            } else {
                                // バックグラウンド時はNotificationを飛ばすだけ
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　// 省略
                            }
                        }
                    }
                }
            }
      }
}

public class NewMessage {
    @SerializedName("sender_name")
    public String name;
    public String body;
}
```

```java:イベントバスホルダークラス
import com.squareup.otto.Bus;

public class BusHolder {

    private static Bus sBus = new Bus();

    public static Bus get() {
        return sBus;
    }

}
```

```java:イベント定義
public class NewMessageEvent {

    public name;
    public body;

    public NewMessageEvent(String name, String body) {
        super();
        this.name = name;
        this.body = body;
    }
}
```

```java:チャット画面のリスト
public class ChatActivity extends Activity {

    private ChatAdapter adapter;

    @Override
    protected void onResume() {
        super.onResume();

        // Subscriberを登録する
        BusHolder.get().register(this);
    }

    @Override
    protected void onPause() {
        super.onPause();

        // Subscriberの登録を解除する
        BusHolder.get().unregister(this);
    }

    @Subscribe
    public void subscribe(NewMessageEvent event) {
        // イベント経由で受け取ったメッセージ内容を追加してリストを更新する
        Message message = new Message(event.name, evant.name);
        adapter.add(message);
        adapter.notifyDataSetChanged();
    }

    @Override
    protected void onCreate() {
        // リストの初期化など（省略）
    }
}
```