プッシュ通知
概要
本投稿は「Kiicloudのユーザー間のプッシュ通知(Android)」について書きます.
前回記事
github
volleyとkiicloudのライブラリを設定の上、以下のパラメータを設定するとログインユーザーがTARGET_IDに指定したユーザーに対し、プッシュ通知を送信できます。
サンプルプロジェクト
//以下のIDとKEYを設定するとTARGET_IDのuserへプッシュ通知が送れます。
// TODO:APP_IDとAPP_KEYはKiiCloudでアプリケーションを作成した際に発行された値に書き換えてください。
public static final String APP_ID = "your App ID";
public static final String APP_KEY = "your App Key";
// TODO:Google Developers Console Project ID SENDER_IDはGCMの設定を有効にした際に発行された値に書き換えてください。
public static final String SENDER_ID = "your Project ID";
// TODO:送信したいtest用のuserのID。
public static final String TARGET_ID = "TEST USER ID";
プッシュ通知の種類
KiiCloudのプッシュ通知は、GCM、APNS、JPush のアプリケーションサーバを想定した実装モデルを採用しているそうです。
Kii Cloud では、以下の3つのプッシュ通知を利用できます。
参考
- プッシュ通知
-
サーバ上変更のプッシュ通知 (Push To App):
購読済みの Bucket 内の更新をプッシュ通知として受け取ります。 -
ユーザープッシュ通知 (Push to User):
購読済みのトピックへのメッセージをプッシュ通知として受け取ります。 -
運用者メッセージのプッシュ通知 (Direct Push):
開発者ポータルからアプリ開発者がプッシュ通知を送信します。
今回はグループに招待するためにプッシュ通知を利用したいので,ユーザープッシュ通知を使用します.
参考:ユーザープッシュ通知について
実装
プロジェクト,GCMの設定
以下参考は開発者ポータルからのプッシュ通知ですが,設定周りは大体同じなので,1-7を設定します.
参考:Android (GCM) プッシュ通知設定チュートリアル
Android (GCM) プッシュ通知設定チュートリアル
1. Android アプリの作成
2. Google プロジェクトの作成
3. Google Cloud Messaging の設定
4. Kii Cloud の設定
5. ビルド環境の設定
6. マニフェストの設定
7. プログラムの実装(受信側の設定)
送信の実装
参考:Kii Cloudを用いたチャットアプリケーションの開発 [その4] ―メッセージ送受信機能の実装
トピックの作成
トピックは、プッシュメッセージを送信するためのチャンネルの役割を果たします。あるトピックに興味のあるユーザーは、このトピックを購読することにより、以後このトピックに送信されたプッシュメッセージを受信できます。
参考:トピックとは
//ログイン時のアクティビティーに記述
//....省略
//push通知用のtopicを作成
private void createPushTopic(final KiiUser user) {
Log.d("pushTopic", user.getUsername());
// GCMの設定
try {
installGCMRegistrationID();
Log.d("GCM", "セッティング");
} catch (Exception e) {
e.printStackTrace();
}
final KiiTopic topic = KiiUser.topic(ApplicationValue.TOPIC_INVITE_NOTIFICATION);
// Save the topic to Kii Cloud
topic.save(new KiiTopicCallBack() {
@Override
public void onSaveCompleted(int taskId, KiiTopic target, Exception exception) {
//////////////////////////
//トピックの ACL を変更する
//////////////////////////
}
});
}
//GCMの設定
private void installGCMRegistrationID() throws Exception {
String registrationId = GCMUtils.register(senderID);
KiiUser.pushInstallation().install(registrationId);
}
トピックのACLを変更する
トピックにプッシュメッセージを送信するための権限を付与します。
//上記コードの //トピックの ACL を変更する部分
//....省略
// Save the topic to Kii Cloud
topic.save(new KiiTopicCallBack() {
@Override
public void onSaveCompleted(int taskId, KiiTopic target, Exception exception) {
if (exception != null) {
// Error handling
Log.d("topic err", exception.toString());
return;
}
KiiACL acl = topic.acl();
//権限付与
acl.putACLEntry(new KiiACLEntry(KiiAnyAuthenticatedUser.create(), KiiACL.TopicAction.SEND_MESSAGE_TO_TOPIC, true));
acl.save(new KiiACLCallBack() {
@Override
public void onSaveCompleted(int token, KiiACL acl, Exception exception) {
if (exception != null) {
// Error handling
Log.d("topic err acl", exception.toString());
return;
}
KiiPushSubscription subscription = user.pushSubscription();
subscription.subscribe(topic, new KiiPushCallBack() {
@Override
public void onSubscribeCompleted(int taskId, KiiSubscribable target, Exception exception) {
if (exception != null) {
// Error handling
Log.d("topic err subscription", exception.toString());
return;
}
}
});
}
});
}
});
GCMの準備(Google Cloud Messaging)
//senderIDはGoogle Developers Consoleのproject ID
//ログイン後のKiiUserを取得後に記述
//SharedPreferences に GCM から取得した登録 ID を文字列として保存
private void registerGCM(final KiiUser user) {
new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
try {
// call register
String regId = gcm.register(senderID);
// install user device
boolean development = false;
user.pushInstallation(development).install(regId);
// if all succeeded, save registration ID to preference.
GCMPreference.setRegistrationId(MainActivity.this.getApplicationContext(), regId);
Log.d("regId", regId);
return null;
} catch (Exception e) {
// Error Handling
Log.d("registerGCM", e.toString());
return null;
}
}
}.execute();
}
public class GCMPreference {
private static final String PREFERENCE_NAME = "KiiTest";
private static final String PROPERTY_REG_ID = "GCMregId";
public static String getRegistrationId(Context context) {
SharedPreferences prefs = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
return registrationId;
}
public static void setRegistrationId(Context context, String regId) {
SharedPreferences prefs = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(PROPERTY_REG_ID, regId);
editor.commit();
}
}
メッセージの送信
//受け取るときにApplicationValue.SEND_MESSAGE_INTENTを使います。
//受信すると"Hello push 受信したよ!!"のToastがでます。
//push通知 sendMessage
private void sendMessage() {
final KiiUser target = KiiUser.userWithID(targetID);
//ユーザーの取得
target.refresh(new KiiUserCallBack() {
@Override
public void onRefreshCompleted(int token, Exception exception) {
if (exception != null) {
// Error handling
Log.d("Refresh err", exception.toString());
return;
}
KiiTopic topic = target.topicOfThisUser(TOPIC_INVITE_NOTIFICATION);
Log.d("target topic", topic.getName());
KiiPushMessage.Data data = new KiiPushMessage.Data();
data.put(ApplicationValue.SEND_MESSAGE_INTENT, "Hello push 受信したよ!!");
KiiPushMessage message = KiiPushMessage.buildWith(data).build();
// Send the push message.
topic.sendMessage(message, new KiiTopicCallBack() {
@Override
public void onSendMessageCompleted(int taskId, KiiTopic target, KiiPushMessage message, Exception exception) {
if (exception != null) {
// Error handling
Log.d("SendMessage", exception.toString());
return;
}
Log.d("送信完了", "success");
}
});
// check whether user is disabled.
boolean disabled = target.disabled();
if (target.isLinkedWithSocialProvider(KiiSocialNetworkConnector.Provider.FACEBOOK)) {
// User is linked to the Facebook account.
}
if (target.isLinkedWithSocialProvider(KiiSocialNetworkConnector.Provider.TWITTER)) {
// User is linked to the Twitter account.
}
}
});
}
受信の実装
onReceiveの実装
BroadcastReceiverのonReceive() を実装します。
以下ではswich文でプッシュ通知の種類を分岐してありますが、本投稿ではユーザー間のプッシュ通知なので「PUSH_TO_USER」の部分しか動作しません。
参考:メッセージを受信する
public class KiiPushBroadcastReceiver extends BroadcastReceiver {
public KiiPushBroadcastReceiver(){
}
@Override
public void onReceive(final Context context, final Intent intent) {
Log.d("onReceive", "received push message");
if (KiiUser.getCurrentUser() == null) {
// ログイン中でない場合は何もしない
Log.d("onReceive", "user null return");
return;
}
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
String messageType = gcm.getMessageType(intent);
if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
final Bundle extras = intent.getExtras();
final ReceivedMessage message = PushMessageBundleHelper.parse(extras);
PushMessageBundleHelper.MessageType type = message.pushMessageType();
switch (type) {
case DIRECT_PUSH:
Toast.makeText(context, "DIRECT_PUSH", Toast.LENGTH_LONG).show();
Log.d("onReceive", "DIRECT_PUSH");
return;
case PUSH_TO_APP:
Log.d("onReceive", "PUSH_TO_APP");
Toast.makeText(context, "PUSH_TO_APP", Toast.LENGTH_LONG).show();
try {
Log.d("onReceive", "PUSH_TO_USER");
} catch (Exception e) {
}
break;
case PUSH_TO_USER:
// ユーザー間のプッシュ通知
Log.d("onReceive", "received PUSH_TO_USER");
String getMessage = extras.getString(ApplicationValue.SEND_MESSAGE_INTENT);
sendBroadcast(context, ApplicationValue.ACTION_RECEIVED_INTENT, getMessage);
Toast.makeText(context, "PUSH_TO_USER: " + getMessage, Toast.LENGTH_LONG).show();
break;
}
}
}
/**
* プッシュ通知を受信したことをBroadcast Intentを使ってActivityに通知します。
*
*/
private void sendBroadcast(Context context, String action, String message) {
Intent intent = new Intent(action);
intent.putExtra(ApplicationValue.GET_MESSAGE_INTENT, message);
context.sendBroadcast(intent);
}
}
Activityで取得
受け取れた場合、「push通知:hogehoge」みたいなToastが出ます。
//KiiPushBroadcastReceiverから受信したメッセージをActivityで取得
private final BroadcastReceiver handleNewReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra(ApplicationValue.GET_MESSAGE_INTENT);
Toast.makeText(context, "push通知:"+ message, Toast.LENGTH_LONG).show();
Log.d("push通知", message);
}
};
@Override
public void onResume() {
super.onResume();
registerReceiver(this.handleNewReceiver, new IntentFilter(ApplicationValue.ACTION_RECEIVED_INTENT));
}
@Override
public void onPause() {
super.onPause();
unregisterReceiver(this.handleNewReceiver);
}
Manifestの設定
receiverが必要です。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.luky_ponies.pushtest" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission android:name="com.luky_ponies.pushtest.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.luky_ponies.pushtest.permission.C2D_MESSAGE" />
<application
android:name=".VolleyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".UserActivity"
android:label="UserActivity"></activity>
<!-- *** add following lines *** -->
<receiver android:name="com.luky_ponies.pushtest.KiiPushBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.luky_ponies" />
</intent-filter>
</receiver>
</application>
</manifest>
送信の検証
注意
メッセージの送信を検証するためには,実機を2台使うのが理想的です.genymotionを用いた実験では実機→エミュレータでは送信と受信は可能ですが,エミュレータ→実機では送信ができないことが注意です.
エミュレータではregisterGCMのメソッド部分でエラーが出て登録ができていないようです.
メッセージの送信機能でグループに追加
このプッシュ通知にuserIDなどをのせて通知を行えば、グループのメンバーの追加ができるかと思います。
前回記事