Androidアプリでプッシュ通知を利用する

2013 年 4 月 25 日 by shimizuy

Androidアプリでプッシュ通知を利用する方法をご紹介します。

プッシュ通知とはユーザがアプリを起動していなくても、アプリにリアルタイムに何らかの通知を送る仕組みのことです。

以前はC2DM(Cloud to Device Messaging)というサービスが利用可能でしたが、2012年6月頃から新しいサービスであるGCM(Google Cloud Messaging for Android)というサービスが用意されています。
今回はこのGCMを利用する方法をご紹介したいと思います。

まず、GCMの概要を図解したものを以下に載せます。

1) GoogleDevelopersSiteにてプロジェクトを登録
2) [ServerAPIKey]及び[ProjectID]を取得
3) [ProjectID]をアプリケーションへ埋め込み
4) [ProjectID]を使用して[RegistrationID]を要求
5) [RegistrationID]生成
6) [RegistrationID]応答
7) [RegistrationID]をコンテンツプロバイダーへ通達
8) Push配信要求([ServerAPIKey],[RegistrationID],メッセージ本文)
9) 認証及び配信先特定
10) Push配信

登場人物としては、以下の通り。

  • [プッシュ配信サーバ]
  • [Androidアプリ(端末)]
  • [Googleサーバ]

また、上記3者間でのやり取りを行う上で必要なキー情報は、以下の通り。

  • [Server API Key] :サーバ側API key
  • [ProjectID] :プロジェクトID
  • [RegistrationID] :端末登録ID

これらの情報を取得する手順も含めてご紹介します。

===================================
<< 事前準備 >>
===================================

-----------------------------------------
◆API利用登録
-----------------------------------------

Google提供のサービスの利用登録を行います。

◇ プロジェクト作成

以下のURLにアクセスし、「Create project…」をクリックします。
※Googleアカウントへのサインインが求められる場合はサインインしてください。

https://code.google.com/apis/console/

プロジェクト登録

左側メニューの「Overview」をクリックすると、以下のようなプロジェクト情報が表示される為、「Project Number」の値を控えておきます。([ProjectID])

ProjectID

◇ GCMの有効化

左側メニューの「Services」をクリックすると、以下のようなGoogleAPI のサービス一覧が表示される為、「Google Cloud Messaging for Android」を探し、Statusを「ON」にします。

GCM有効化

「Google Cloud Messaging for Android」のStatusが「ON」となっていることを確認します。

GCM有効化

◇ [ServerAPIKey]の生成

プッシュ通知を配信する際に使用する「server API key」を以下の手順にて生成します。

左側メニューの「API Access」をクリックします。
※デフォルトで「browser API key」が登録されていますが、今回使用するのは「server API key」となります。

APIKey生成

プッシュ通知配信サーバのIPを入力し、「Create」をクリックします。
APIKey生成

「Key for server apps」の欄が追加されていることを確認します。
また、欄内に記載されている「API key」の値を控えておきます。([Server API Key])

APIKey生成

以上で事前準備は完了です。

===================================
<< アプリ側の設定 >>
===================================

-----------------------------------------
◆GCM用ライブラリ設定
-----------------------------------------

Google提供のライブラリをプロジェクトに取込みます。

まず、Android SDK Manager を起動し、
Extras配下の GoogleCloudMessaging for Android Library をインストールします。

ライブラリ設定

次に、以下の場所に格納されている gcm.jar をプロジェクト直下の libs フォルダにコピーします。

(SDK_ROOT)/extras/google/gcm-client/dist/gcm.jar

-----------------------------------------
◆設定ファイル(AndroidManifest.xml)修正
-----------------------------------------

GCMが受信できるようにAndroidManifest.xmlを編集します。

まずは、以下のようにパーミッションの設定を追加します。
※以下の【app_package】は、プロジェクトのパッケージ名を記述します。

XML:
  1. <permission
  2.     android:name="【app_package】.permission.C2D_MESSAGE"
  3.     android:protectionLevel="signature" />
  4. <uses-permission android:name="【app_package】.permission.C2D_MESSAGE" />
  5. <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
  6. <uses-permission android:name="android.permission.WAKE_LOCK" />

次に、以下のようにGCM用のレシーバ(BroadcastReciever)の定義を追加します。
ライブラリに含まれている GCMBroadcastReceiver クラスを使用します。
※以下の【app_package】は、プロジェクトのパッケージ名を記述します。

XML:
  1. <receiver
  2.     android:name="com.google.android.gcm.GCMBroadcastReceiver"
  3.     android:permission="com.google.android.c2dm.permission.SEND">
  4.  
  5.     <intent-filter>
  6.         <action android:name="com.google.android.c2dm.intent.RECEIVE" />
  7.         <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
  8.         <category android:name="【app_package】" />
  9.     </intent-filter>
  10. </receiver>
  11. <service android:name="【app_package】.GCMIntentService" />

-----------------------------------------
◆GCMIntentService作成
-----------------------------------------

GCMを受信するServiceクラスを作成します。
ライブラリに含まれる GCMBaseIntentService を継承して作成します。
※以下はメッセージを受信後、通知領域にメッセージを表示し、MainActivityにメッセージを通知する例

JAVA:
  1. /**
  2. * プッシュ通知の受信に関する処理を行うクラス
  3. */
  4. public class GCMIntentService extends GCMBaseIntentService {
  5.  
  6.     /** コンストラクタ */
  7.     public GCMIntentService() {
  8.         super("[ProjectID]");
  9.     }
  10.  
  11.     /** RegistrationID が登録された場合に呼び出されるメソッド */
  12.     @Override
  13.     public void onRegistered(Context context, String registrationId) {
  14.         // [RegistrationID]を本体に保存する処理などを記述
  15.     }
  16.  
  17.     /** RegistrationID が登録解除された場合に呼び出されるメソッド */
  18.     @Override
  19.     protected void onUnregistered(Context context, String registrationId) {
  20.         // [RegistrationID]を本体から削除する処理などを記述
  21.     }
  22.  
  23.     /** エラーが発生した場合に呼び出されるメソッド */
  24.     @Override
  25.     public void onError(Context context, String errorId) {
  26.         // エラー処理などを記述
  27.     }
  28.  
  29.     /** メッセージを受信した場合に呼び出されるメソッド */
  30.     @Override
  31.     protected void onMessage(Context context, Intent intent) {
  32.         // メッセージ取得
  33.         String str = intent.getStringExtra("message");
  34.        
  35.         // ステータスバーに通知する情報を生成
  36.         NotificationManager notificationManager =
  37.                 (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
  38.         Notification notification =
  39.                 new Notification(R.drawable.ic_launcher, str, System.currentTimeMillis());
  40.  
  41.         // ステータスバーに表示するViewを生成
  42.         RemoteViews contentView =
  43.                 new RemoteViews(this.getPackageName(), R.layout.notify);
  44.  
  45.         // タイトル
  46.         contentView.setTextViewText(R.id.notify_title, "タイトル");
  47.         // 内容
  48.         contentView.setTextViewText(R.id.notify_content, str);
  49.         // 時刻
  50.         Date now = new Date(System.currentTimeMillis());
  51.         SimpleDateFormat sdf = new SimpleDateFormat("kk:mm");
  52.         contentView.setTextViewText(R.id.notify_time, sdf.format(now));
  53.  
  54.         // インテント生成
  55.         Intent mainIntent = new Intent(this, MainActivity.class);
  56.         mainIntent.putExtra("GCM_MESSAGE", str);
  57.  
  58.         PendingIntent contentIntent =
  59.                 PendingIntent.getActivity(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
  60.  
  61.         notification.contentView = contentView;
  62.         notification.flags =
  63.                 Notification.FLAG_ONGOING_EVENT | Notification.FLAG_AUTO_CANCEL;
  64.         notification.contentIntent = contentIntent;
  65.  
  66.         // 通知
  67.         notificationManager.notify(R.string.app_name, notification);
  68.     }
  69. }

-----------------------------------------
◆Activity実装(MainActivity)
-----------------------------------------

端末をGCMサービスへ登録する処理を実装します。

まず、onCreateメソッド内で、端末からGoogleサーバにアクセスし、[RegistrationID]を取得する処理を記述します。

JAVA:
  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3.     super.onCreate(savedInstanceState);
  4.  
  5.     /** GCM登録処理 */
  6.    
  7.     // デバイス・マニフェスト検証
  8.     GCMRegistrar.checkDevice(this);
  9.     GCMRegistrar.checkManifest(this);
  10.  
  11.     // ID取得
  12.     final String regId = GCMRegistrar.getRegistrationId(this);
  13.     if (StringUtil.isNull(regId)) {
  14.        
  15.         // 未登録の場合、登録
  16.         GCMRegistrar.register(this, PropertiesConst.GCM_SENDER_ID);
  17.        
  18.     }
  19. }

次に、onResumeメソッド内で、GCMIntentService がメッセージを受信した場合に、画面にメッセージを表示する処理を記述します。
通知されたメッセージを扱う場合にはここで処理を行います。

JAVA:
  1. @Override
  2. protected void onResume() {
  3.     super.onResume();
  4.  
  5.     /** GCM受信メッセージ表示 */
  6.    
  7.     // GCMメッセージの取得
  8.     Intent intent = this.getIntent();
  9.     if (intent != null) {
  10.         String gcmMsg = intent.getStringExtra("GCM_MESSAGE");
  11.         if (StringUtil.isNotNull(gcmMsg)) {
  12.             Toast.makeText(this, gcmMsg, Toast.LENGTH_SHORT);
  13.         }
  14.     }
  15. }

以上でアプリ側の設定は完了です。

===================================
<< サーバ側の設定 >>
===================================

プッシュ通知配信サーバでは次のことを行います。

◆クライアント(Androidアプリ)から送信される[RegistrationID]の受信
◆GCMサーバ(https://android.googleapis.com/gcm/send)へのHTTPSリクエスト発信
◆[ServerAPIKey]と[RegistrationID]の管理

主にはクライアントおよびGCMサーバとのHTTP通信と、キー情報([ServerAPIKey]と[RegistrationID])の管理を行うだけですので、ここでは詳細は控えさせていただきます。

===================================
<< 配信方法 >>
===================================

プッシュ配信要求は、単一または複数のデバイスに対して、JSON形式またはプレーンテキスト形式でメッセージ送信することが可能です。
ただし、複数のデバイスに対して配信を行う場合、JSON形式を使用しなければならなりません。
プッシュ配信要求は、https://android.googleapis.com/gcm/sendに対してPOSTリクエストを発送することで行います。

-----------------------------------------------------
◆配信要求フォーマット(HTTPヘッダ)
-----------------------------------------------------

Content-Type:
→JSON形式で送信する場合、”application/json”を指定
→プレーンテキスト形式で送信する場合、”application/x-www-form-urlencoded;charset=UTF-8”を指定。

Authorization:
→key=事前準備にて生成した[ServerAPIKey]

-----------------------------------------------------
◆配信要求フォーマット(HTTPボディコンテンツ(メッセージ))
-----------------------------------------------------

registration_ids:
→デバイスRegistration ID(JSON形式で1000台まで指定可)

collapse_key:
→送信するメッセージのグループ(任意文字列)デバイスがオフライン時に使用され、最後のメッセージだけがデバイスに送信される。time_to_liveを使用していなければオプション。

delay_while_idle:
→デバイスがアイドル状態の場合、メッセージをすぐに送るべきではないことを示す。サーバはデバイスがアクティブになるのを待ち、collapse_keyの最後のメッセージのみ送信される。

time_to_live:
→デバイスがオフラインの場合、メッセージを保持しておく期間(秒単位で指定)

data:
→メッセージ本体(送りたい文字列(JSON形式で複数可))

※詳細についてはこちら(GoogleCloud Messageing Android)を参照下さい。

-----------------------------------------------------
◆配信サンプル
-----------------------------------------------------

以下、プッシュ通知の配信例を記述します。

RUBY:
  1. #! ruby -Ku
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Ruby 1.9 execution
  5. # Android Push Notification Test
  6. #
  7. require 'json'
  8. require 'net/https'
  9.  
  10. #GCM サーバの接続先(https://android.googleapis.com/gcm/send)
  11. GCM_HOST = "android.googleapis.com"
  12. GCM_PATH = "/gcm/send"
  13.  
  14. #ServerAPI key
  15. API_KEY = "[Server API Key]"
  16.  
  17. #配信先登録ID
  18. REG_ID = "[RegistrationID]"
  19.  
  20. #送信するメッセージ
  21. send_message = {
  22.  "registration_ids" => [REG_ID],
  23.  "collapse_key" => "collapse_key",
  24.  "delay_while_idle" => true,
  25.  "time_to_live" => 240,
  26. # "data" => {"message" => "GCM TEST",
  27.  "data" => {"message" => "#{ARGV[0]}",
  28.    "detail" => "Hello GCM World"}
  29. }
  30.  
  31. #HTTPS POST実行
  32. http = Net::HTTP.new(GCM_HOST, 443);
  33. http.use_ssl = true
  34. http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  35. http.start{|w|
  36.  response = w.post(GCM_PATH,
  37.  send_message.to_json + "\n",
  38.  {"Content-Type" => "application/json",
  39.  "Authorization" => "key=#{API_KEY}"})
  40.  puts "response code = #{response.code}"
  41.  puts "response body = #{response.body}"
  42. }

以上、ここまでプッシュ通知を扱う手順をご説明しました。

サーバ側の処理に関しては詳しく記載していませんが、
上記の手順でプッシュ通知を実現できます。

ちょっとしたメッセージの一斉通知から送受信をトリガーにした機能の実現など
様々な用途で使用できると思いますので、一度お試しください。

タグ:

TrackBack