GCMについてはすでに書かれています。 この記事の目的は何ですか?
そうです、彼らは書きました。 文字通り今週、Habréで記事
GCMが公開されました-Google
からのプッシュ通知の新しいサービス (Android向けのGoogle Cloud Messagingに慣れていない場合は、特に私の記事ではプロジェクトの作成プロセスについて説明していないため、この記事を読む前に読むことをお勧めします) GCMを使用)。 著者GCMが実際のアプリケーションで使用したかどうかはわかりませんが、私はしなければなりませんでした。 それが、前の記事で場所を見つけられなかったか、説明されなかった何かを説明したい理由です。 前の記事にコメント付きでこれらすべてを追加するために、私は不可能な仕事を恐れています。
必要な許可
<uses-permission android:name="android.permission.INTERNET" />
ここではすべてが明らかです。インターネットにアクセスしなければGCMは必要ありません。
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
GCMにはGoogleアカウントへのアクセスが必要です
<uses-permission android:name="android.permission.WAKE_LOCK"/>
最後のトピックでこれについては論争さえありましたが、ソースコードを見ることに決めた参加者はいませんでした。 ドキュメントにはこの点については記載されていませんが、 PowerManager.WakeLock
をキャプチャすることをおPowerManager.WakeLock
ます。 したがって、標準のGCMライブラリを使用する場合は、そのような許可を追加する必要があります。
要するに、作業のメカニズムは次のとおりです。アプリケーションは、ブロードキャスト要求を受信するためにサブスクライブします。 要求を受信すると、受信したIntentをGCMBaseIntentService
拡張するサービスの名前のクラス名( setClassName()
)にWakeLock
し、 PowerManager.PARTIAL_WAKE_LOCK
フラグでWakeLock
をPowerManager.PARTIAL_WAKE_LOCK
ます(CPUのみがスリープ状態にならない、画面がスリープ状態になりません)、Intentをサービスとして起動します。 onHandleIntent
サービスを終了すると、無料のWakeLock
ます。
彼らはこの許可を信じず、追加もしませんでしたが、最終的にこの例外が発生します。
java.lang.SecurityException: Neither user 10110 nor current process has android.permission.WAKE_LOCK.
<permission android:name="{ }.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="{ }.permission.C2D_MESSAGE" />
独自の許可を作成し、自分で要求します。 これは、私たち以外の誰もメッセージを受け取れないようにするためです。
注: minSdkVersion
を16
以上(Jelly Bean以降のバージョン)に設定する場合、この許可は必要ありません(2年後、省略できることを望みます)。 <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
実際にGCMに登録してメッセージを受信する許可。
登録コード(registationId)は変更されていますか?
サンプルアプリケーションのコードを考えてみましょう。
final String regId = GCMRegistrar.getRegistrationId(this); if (regId.equals("")) {
他の条件はないようです。 だから、変わらない? このリンク
http://developer.android.com/intl/en/guide/google/gcm/adv.html#reg-stateをクリックすると、何が変更される可能性があるかがわかります。 次の2つのケースがあります。
- プログラム更新
- バックアップを作成してそこから復元する
プログラムの更新を確認するために、小さなヘルパークラスを作成しました。 誰かが役に立つかもしれません:
import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.preference.PreferenceManager; public final class ApplicationVersionHelper { public static final String APP_VERSION_PREFS = "application_version"; public static boolean isApplicationVersionCodeEqualsSavedApplicationVersionCode(Context context) { return getApplicationVersionCode(context) == getApplicationVersionCodeFromPreferences(context); } public static int getApplicationVersionCode(Context context) { PackageManager pm = context.getPackageManager(); PackageInfo packageInfo; int applicationVersion = 1; try { packageInfo = pm.getPackageInfo(context.getPackageName(), 0); applicationVersion = packageInfo.versionCode; } catch (NameNotFoundException ignored) { } return applicationVersion; } public static int getApplicationVersionCodeFromPreferences(Context context) { return context.getSharedPreferences(APP_VERSION_PREFS, Context.MODE_PRIVATE).getInt("application_version_code", 0); } public static void putCurrentPackageVersionInPreferences(Context context) { context.getSharedPreferences(APP_VERSION_PREFS, Context.MODE_PRIVATE).edit().putInt("application_version_code", getApplicationVersionCode(context)).commit(); } }
設定は
PreferenceManager.getDefaultSharedPreferences
からではなく、指定された設定ファイルから取得されることに注意してください。 これが行われる理由は、後で説明します。
ここで、GCMおよびサービスでの登録が成功した後、
putCurrentPackageVersionInPreferences
を呼び出す必要があり、登録確認コードは次のようになります。
final String regId = GCMRegistrar.getRegistrationId(this); if (regId.equals("") || !isApplicationVersionCodeEqualsSavedApplicationVersionCode(this)) {
バックアップの作成を処理するため(誰もがこの機能についてまったく知っているわけではありません。おもしろくなった場合は、
http://developer.android.com/intl/en/guide/topics/data/backup.htmlを読んでください)次の解決策を提案します:バックアップ時に定数
ApplicationVersionHelper.APP_VERSION_PREFS
名前で設定を保存しないでください。 そのため、名前付き設定ファイルが便利になりました:)その後、
isApplicationVersionCodeEqualsSavedApplicationVersionCode
はデータを復元するときに
false
を返し、登録要求を送信します。
GCMIntentServiceのハンドラー
GCMIntentService
(
GCMIntentService
から継承された
GCMBaseIntentService
)
いくつかのメソッドを再定義する必要があります。 簡単に言うと:
protected void onRegistered(Context context, String registrationId)
このメソッドは、GCMに正常に登録された後に呼び出されます。ここから、 registrationId
をサーバーに転送する必要があります。 protected void onUnregistered(Context context, String registrationId)
このメソッドはGCMで登録が正常にキャンセルされた後に呼び出されます。また、メーリングリストから除外するためにregistrationId
をサーバーに転送します(多くのアプリケーションはこの機能を使用しません) protected void onMessage(Context context, Intent intent)
GCMからメッセージを受信し、ペイロードがある場合、データはintent
protected void onDeletedMessages(Context context, int total)
GCMから削除されたメッセージ、その内容、およびその内容に関する通知を受信します。http://developer.android.com/intl/en/guide/google/gcm/adv.html#payloadを参照してください public void onError(Context context, String errorId)
errorId
エラーコードでのデータ受信中の回復不能エラー protected boolean onRecoverableError(Context context, String errorId)
errorId
エラーコードでのデータ受信中の回復可能なエラー。 true
を返したtrue
、別の試行を行い、 false
場合、試行を停止します。 このメソッドでsuper.onRecoverableError(context, errorId);
を返すことをお勧めしますsuper.onRecoverableError(context, errorId);
自分で掃除します!
登録プロセスを実行している場合は、忘れずにキャンセルし、メインアクティビティのonDestroyメソッドでGCMRegistrar.onDestroyを呼び出します。 以下がその方法です。
@Override protected void onDestroy() { if (registerTask != null) { registerTask.cancel(true); } try { CMRegistrar.onDestroy(this); } catch(Exception ignored) { } super.onDestroy(); }
ここでの
registerTask
は、非同期ジョブ(
AsyncTask
)です。
おわりに
アプリケーションでGCMを使用する前に
http://developer.android.com/intl/en/guide/google/gcm/index.htmlを読んで(5つのポイントがあります)、質問がある場合(WAKE_LOCK許可について)、ソースコードに入ることを恐れないでください。