2013年12月23日

【Android】Silent Notificationをやってみたい



Android Advent Calendar 2013の23日目。

リア充イベントのクリスマスがもう目の前に迫ってますが、
今年は急遽、サンタがインフルエンザの為、中止みたいですよ。


この記事は23日に急遽書いています。

忘れていたわけではありません。

どちらかと言うとネタが無かった。
無理やり探しました。
ネタ無いんだもん。

Androidのコードを全然書いていないので、
KitKatについてとか書きたかったんですが、
あんまりネタが無い。

ので、iOSから横流しし、Silent Notificationの記事を書きます。

ってか、そもそも、AndroidのNotificationは、自分で書かないと、
表示してくれません。

何もしなくてもSilent Notificationになるんです。

そんな事は分かっています。

やりたい事は、

1. アプリケーションがバックグラウンドにいるかどうかのチェック
2. アプリケーションがバックグラウンドの場合にのみ追加コンテンツのダウンロード

という2点です。

iOSのSilent Notificationはアプリケーションへの通知が、
アプリが起動していない時しか来ませんが、
Androidの場合は起動していても来ます。

アプリケーションがバックグラウンドにいるかどうかのチェック

を実現する為に、GCMIntentService.javaをちょっと改造します。

public class GCMIntentService extends GCMBaseIntentService {
  public static Activity currentActivity;
  public static final Object CURRENTACTIVIYLOCK = new Object();
  
  /**
    * 普段通りのonRegisteredとかいろいろ
    */

  @Override
  protected void onMessage(Context context, Intent intent) {
    synchronized(CURRENTACTIVIYLOCK) {
      if (currentActivity != null) {
        if (currentActivity.getClass() == BaseActivity.class) {
          BaseActivity act = (BaseActivity)currentActivity;
          act.runOnUiThread(new Runnable() {
            public void run() {
              BaseActivity.onMessage(intent);
            }
          });
        } else {
          showNotification(context, intent);
        }
      } else {
        showNotification(context, intent);
      }
    }
  }

  private void showNotification(Context context, Intent intent) {
    Bundle bundle = intent.getExtras();
    String contentAvailable = bundle.getString("content-available");
    if (contentAvailable == null) {
      // show notification
    } else {
      // download contents
    }
  }
}

そして、onResumeとonPauseに、現在のActivityが何であるか教えてあげます。

  @Override
  protected void onResume() {
    synchronized (GCMIntentService.CURRENTACTIVITYLOCK) {
      GCMIntentService.currentActivity = this;
    }
    super.onResume();
  }

  @Override
  protected void onPause() {
    synchronized (GCMIntentService.CURRENTACTIVITYLOCK) {
      GCMIntentService.currentActivity = null;
    }
    super.onPause();
  }

  public abstract void onMessage(Intent intent) {
    // notified new message
  }

コンテンツをダウンロードするか、メッセージを表示するかは、
GCMから受け取ったPayloadの内容次第ですが、
content-availableにしてあるのは、iOSに合わせただけです。


上のコードを真似すれば、アプリが起動中かどうかが分かります。

起動中かが分かれば、バックグラウンドにいる間だけ、
コンテンツをダウンロードしたり、通知を出したり出来る訳です。



Androidを開発していると、
iOSの動きに合わせてくれと言われる事が多いですが、
これでちょっとは動きが合うかな?

こんなネタでいいですか?

よいお正月を〜!