androidでプッシュ通知の実装をテーマとして第5回目。
まずは、プッシュ通知を実装する上でアプリ側に必要な機能をおさらいです。
- 通知を受け取る
- 受け取ったメッセージを処理する
- レジストレーションIDの登録と端末保存
- (取得したレジストレーションIDのAppサーバへの送信)
大きく分けて以上の4つが必要でした。
そして第4回ではそのうち1にあたるBroadcastRecieverと2にあたるIntentServiceについて書きました。
今回は残りの3.レジストレーションIDの登録と端末保存について書いていきます。
MainActivity
まずなにはともあれサンプルのMainActivityをのせます。
クリックするとレジストレーションIDを取得するボタンを持つだけの単純なつくりです。
package jp.techpjin.samplepushnotification; import java.io.IOException; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.gcm.GoogleCloudMessaging; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { public static final String PROPERTY_REG_ID = "registration_id"; private static final String PROPERTY_APP_VERSION = "appVersion"; private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000; //デベロッパーコンソールで取得したセンダーID private static final String SENDER_ID = "************"; private GoogleCloudMessaging gcm; private String registrationId; private Context context; private AsyncTask<Void, Void, Void> registerTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button registerButton = (Button) findViewById(R.id.button_register); registerButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if ("".equals(registrationId)) { registerTask = new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { if (gcm == null) { gcm = GoogleCloudMessaging.getInstance(context); } try { registrationId = gcm.register(SENDER_ID); sendRegistrationIdToAppServer(); storeRegistrationId(context, registrationId); } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void result) { registerTask = null; } }; registerTask.execute(null, null, null); } } }); context = getApplicationContext(); if (checkPlayServices()) { gcm = GoogleCloudMessaging.getInstance(context); registrationId = getRegistrationId(context); } else { } } /** * 端末のGooglePlayServiceAPKの有無をチェック */ private boolean checkPlayServices() { int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); if (resultCode != ConnectionResult.SUCCESS) { if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) { GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_RESOLUTION_REQUEST).show(); } else { finish(); } return false; } return true; } /** * 端末に保存されているレジストレーションIDの取得 */ private String getRegistrationId(Context context) { final SharedPreferences prefs = getGCMPreferences(context); String registrationId = prefs.getString(PROPERTY_REG_ID, ""); if (registrationId.equals("")) { return ""; } int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE); int currentVersion = getAppVersion(context); if (registeredVersion != currentVersion) { return ""; } return registrationId; } /** * アプリケーションのバージョン情報を取得する */ private static int getAppVersion(Context context) { try { PackageInfo packageInfo = context.getPackageManager() .getPackageInfo(context.getPackageName(), 0); return packageInfo.versionCode; } catch (NameNotFoundException e) { throw new RuntimeException("パッケージが見つかりません:" + e); } } /** * アプリのプリファレンスを取得する */ private SharedPreferences getGCMPreferences(Context context) { return getSharedPreferences(MainActivity.class.getSimpleName(), Context.MODE_PRIVATE); } /** * レジストレーションIDの端末保存 */ private void storeRegistrationId(Context context, String regId) { final SharedPreferences prefs = getGCMPreferences(context); int appVersion = getAppVersion(context); SharedPreferences.Editor editor = prefs.edit(); editor.putString(PROPERTY_REG_ID, regId); editor.putInt(PROPERTY_APP_VERSION, appVersion); editor.commit(); } private void sendRegistrationIdToAppServer(){ //各々の仕様にあわせて実装してください } @Override protected void onResume() { super.onResume(); checkPlayServices(); } @Override protected void onDestroy() { if (registerTask != null) { registerTask.cancel(true); } gcm.close(); super.onDestroy(); } }
個々の要素に補足を加えますが少々冗長になる点についてはご容赦ください。
checkPlayServices
GCMを利用するには端末にGooglePlayServiceAPKがインストールされている必要があります。
これがないと以降の処理が行えないのでGooglePlayServicesUtilのisGooglePlayServicesAvailableメソッド
を用いてGooglelayServiceが利用可能かどうか判別しています。
getGCMPreferences
アプリのプリファレンスを取得するメソッドです。
プリファレンスとはアプリの設定値等をキー・バリュー型で端末内に保存できる仕組みです。
文字や数値の保存に向いており、アプリを終了しても残るので便利です。
getSharedPreferencesメソッドでは第一引数ではプリファレンスの名前、
第二引数ではプリファレンスのモードを指定します。
今回のサンプルではMODE_PRIVATE、すなわちそのアプリケーションのみが参照できるという設定ですね。
SharedPreferencesを用いてレジストレーションIDをの端末への保存、また端末からの取得を行います。
getRegistrationId,storeRegistrationId
getRegistrationIdはプリファレンスにすでにレジストレーションIDが保存されていれば
そのバリューを、なければ空文字を返します。
SharedPreferences#getStringの第一引数はキー、第二引数はプリファレンスがなかった場合に返すデフォルト値です。
storeRegistrationIdはGCMから取得したレジストレーションIDと
そのときのアプリのバージョンをプリファレンスに保存するメソッドです。
SharedPreferences.Editor#putString,or:putIntの第一引数はキー、第二引数はバリューです。
アプリのバージョンが更新された場合、以前のバージョン時に取得したレジストレーションIDが有効であることは保証されません。
よってバージョンを更新するたびにレジストレーションIDを再取得する必要があること、
プリファレンスには保存時のアプリのバージョンの情報も一緒にもっておく必要があることに留意しましょう。
onClick
最後にButtonにセットしたリスナーのonClickについてです。
プリファレンスを確認した後、レジストレーションIDの取得が必要であれば
GoogleCloudMessaging#register(SENDER_ID)を呼び出すことでGCMサーバへの登録が行えます。
GCMサーバとの通信を行うのでAsncTaskを用いてUIスレッドとは別のスレッドに処理を任せましょう。
GCMサーバからレジストレーションIDの取得ができたらそのレジストレーションIDを
sendRegistrationIdToAppServerメソッドでAppサーバに送ります。
その中身は各々の設計にあわせて実装してください。
以上です。
前回のBroadcastRecieverとIntentServiceとあわせてクライアントアプリの実装は終わりです。
次回
二回にわたってクライアントアプリの実装について書きました。
次回はAppサーバ側の実装例を書いていきます。
androidでプッシュ通知を実装する【第1回 概要】
androidでプッシュ通知を実装する【第2回 事前準備】
androidでプッシュ通知を実装する【第3回 アプリ側実装前編】
androidでプッシュ通知を実装する【第4回 アプリ側実装中編】