前回はKii Cloudを用いたアプリケーション開発環境のセットアップを行いました。そしていよいよ今回から、
この連載で開発したアプリケーションについては、
チャットアプリケーションの機能
今回開発するチャットアプリケーションの機能は下記の4つです。チャットアプリケーションとして機能するよう最低限の機能のみに絞っています。
これらの機能は今回の連載を通じて1つずつ実装していきます。
- ユーザサインアップ
(サインイン) - 友達追加
- チャットルーム作成
- メッセージ送受信
チャットアプリケーションの設計・全体像
チャットアプリケーションとして必要な機能を実現するために、
「バケット」
一方
これらの

chat_users(アプリケーションスコープ:バケット)
チャットアプリケーションに登録しているユーザを格納します。
アプリケーションスコープのバケットは全てのユーザから閲覧・
chat_room(グループスコープ:バケット)
チャットルームを表すバケットです。1つのバケットで1チャットルームとします。
このバケットにメッセージをオブジェクトとして保存し、
chat_friends(ユーザスコープ:バケット)
友達を登録するバケットです。友達を追加した場合にこのバケットへ情報を格納し、
invite_notify(ユーザスコープ:トピック)
チャットルームへの招待通知を行うためのトピックです。
初回のサインアップ時にこのトピックを作成・
このようにバケット・
次に各機能ごとに、
ユーザサインアップ(サインイン)

ユーザサインアップ時には、
- ユーザを新規に作成し、
Kii Cloudへ登録を行う。 - chat_
usersバケットに自身の情報を登録し、 他のユーザから検索できるようにする。 - 他のユーザから通知を受け取るために自分専用の invite_
notify トピックをユーザスコープに作成する。ただしユーザスコープのトピックは、 デフォルトのACLで他のユーザからメッセージが送信できない設定となっているため、 追加でACLを設定し、 他のユーザからメッセージが送信できるように設定する。
こうすることでユーザの検索が可能になり、
友達追加

友達追加時には、
- アプリケーションに登録しているユーザ一覧がアプリケーションスコープの “chat_
users” バケットに格納されているため、 このバケットに対してユーザの検索を行う。 - 検索結果から追加したいユーザを選択し、
ユーザスコープの “chat_ friends” バケットに友達リストに表示する人として追加する。
こうすることで友人を検索し、
チャットルーム作成

チャットルーム作成時には、
- UserA
(チャットを開始する人) は、 まずグループを作成し、 UserB (チャットに招待された人) をグループのメンバーとして追加する。その後、 チャットメッセージを保存するためのバケットをKii Cloud上のグループスコープに作成する。 - UserAはこのバケットを購読し、
他のユーザからチャットメッセージが送信された場合にプッシュ通知を受信できるようにする。 - UserB
(チャットに招待された人) に対して、 invite_ notifyトピックを通じてチャットへ招待されたことを通知する。この通知には作成されたグループの情報を付加し、 どのチャットに招待されたか判別できるようにする。 - invite_
notifyに送信されたメッセージはプッシュ通知 (GCM) によりKii CloudからUserB (チャットに招待された人) に対して通知される。 - 招待通知メッセージに含まれているグループの情報より、
チャットを行うバケットを特定し購読を行う。これによって他のユーザからメッセージが送信された場合にプッシュ通知を受信できるようにする。
こうすることでチャットルームを作成することができ、
メッセージ送受信

メッセージ送受信時には、
- UserA
(メッセージ送信者) は、 チャットのメッセージをチャットルーム作成時に作成したグループスコープのバケットにオブジェクトとして保存する。 - UserB
(メッセージ受信者) は、 チャットルームへ招待された際にバケットを購読している。そのため、 バケットに新しいオブジェクトが追加されたタイミングでサーバーから通知が送られる。 - UserB
(メッセージ受信者) はプッシュ通知をトリガーとして、 新しいメッセージをバケットから取得する。
こうすることでメッセージを受信者・
このように今回実装するチャットアプリケーションの4つの機能についてデータフローの設計を行いましたが、
しかしながら、
アプリケーション初期化コードの実装
Android Cloud SDKの各機能を使用する前に、
チャットアプリケーションでは、
// Android Cloud SDKを初期化!
Kii.initialize(ApplicationConst.APP_ID, ApplicationConst.APP_KEY, Site.JP);
初期化メソッドには下記の引数を与えます。
- AppID
(アプリケーションID) - AppKey
(アプリケーションKEY) - Site
(サーバーロケーションを表すenum)
これらの情報は開発者ポータルから確認できます。作成したアプリケーション名をクリック後、


ここで注意しなくてはならないのは、
サインアップの実装
ユーザを利用するアプリケーションの要である

ユーザに入力してもらった値を元に、
- Email
(ユーザ識別子として入力。サインイン時、 ならびにユーザ検索時に利用する) - パスワード
(サインインで利用するパスワード) - ユーザネーム
(チャットで利用する名前)
またサインアップでは
- chat_
users バケットに自分自身を登録 - GCMのregistration IDをKii Cloudに登録
- invite_
notify トピックの作成 - invite_
notify トピックのACLの設定 - invite_
notify トピックの購読
これらを元にして、
なお、
private class SignupTask extends AsyncTask<Void, Void, Boolean> {
private final String username;
private final String email;
private final String password;
private SignupTask(String username, String email, String password) {
this.username = username;
this.email = email;
this.password = password;
}
@Override
protected void onPreExecute() {
ProgressDialogFragment.show(getFragmentManager(), "Signup", "Processing...");
}
@Override
protected Boolean doInBackground(Void... params) {
try {
// KiiUserのサインアップ処置
KiiUser.Builder builder = KiiUser.builderWithEmail(email);
KiiUser kiiUser = builder.build();
kiiUser.setDisplayname(username);
kiiUser.register(password);
Logger.i("registered user uri=" + kiiUser.toUri().toString());
// 登録したKiiUserをChatUserとしてAppスコープのバケツに保存しておく(検索用)
ChatUser user = new ChatUser(kiiUser.toUri().toString(), username, email);
user.getKiiObject().save();
// プッシュ通知で利用するGCM registration IDの送信
String registrationId = GCMUtils.register();
KiiUser.pushInstallation().install(registrationId);
// ユーザトピックの作成
KiiTopic topic = KiiUser.topic(ApplicationConst.TOPIC_INVITE_NOTIFICATION);
topic.save();
// ACL設定
KiiACL acl = topic.acl();
acl.putACLEntry(new KiiACLEntry(KiiAnyAuthenticatedUser.create(), TopicAction.SEND_MESSAGE_TO_TOPIC, true));
acl.save();
// トピックの購読
KiiPushSubscription subscription = kiiUser.pushSubscription();
subscription.subscribe(topic);
return true;
} catch (Exception e) {
Logger.e("failed to sign up", e);
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
ProgressDialogFragment.hide(getFragmentManager());
if (result) {
// サインアップ処理が正常に行われた場合は、コールバックメソッドで呼び出し元に通知
OnSignupListener listener = onSignupListener.get();
if (listener != null) {
listener.onSignupCompleted();
}
} else {
ToastUtils.showShort(getActivity(), "Unable to sign up");
}
dismiss();
}
}
実際のサインアップ処理はdoInBackgroundで実行しています。少し長いので1つずつ見ていきましょう。
1.ユーザサインアップ
// KiiUserのサインアップ処理
KiiUser.Builder builder = KiiUser.builderWithEmail(email);
KiiUser kiiUser = builder.build();
kiiUser.setDisplayname(username);
kiiUser.register(password);
ユーザに入力してもらった情報を元にユーザを作成し、
- KiiUser.
builderWithEmail(java. lang. String email):Emailを元にKiiUserを作成します。この時点ではインスタンスが作成されたのみで、 Kii Cloudへの保存はされていません。 - KiiUser#setDisplayname(java.
lang. String displayname):KiiUserのディスプレイネームの項目にUsernameを設定します。 - KiiUser#register(java.
lang. String password) :KiiUserをKii Cloudへ登録し、 サインアップします。
2.chat_users バケットに自分自身を登録
// 登録したKiiUserをChatUserとしてAppスコープのバケツに保存しておく(検索用)
ChatUser user = new ChatUser(kiiUser.toUri().toString(), username, email);
user.getKiiObject().save();
次は他のユーザから検索可能となるように自分自身の情報をアプリケーションスコープのバケットに登録します。
登録したKiiUserの情報、
この1・
3.GCMのregistration IDをKii Cloudに登録
// プッシュ通知で利用するGCM registration IDの送信
String registrationId = GCMUtils.register();
KiiUser.pushInstallation().install(registrationId);
次はプッシュ通知をKii Cloudから送信できるように、
4.invite_notify トピックの作成
// ユーザトピックの作成
KiiTopic topic = KiiUser.topic(ApplicationConst.TOPIC_INVITE_NOTIFICATION);
topic.save();
次は "invite_
まずは、
5.invite_notify トピックのACL設定
// ACL設定
KiiACL acl = topic.acl();
acl.putACLEntry(new KiiACLEntry(KiiAnyAuthenticatedUser.create(), TopicAction.SEND_MESSAGE_TO_TOPIC, true));
acl.save();
次にACL設定です。ACLはホワイトリスト形式のため、
今回はサインアップ済みのユーザ
6.invite_notify トピックの購読
// Topicの購読
KiiPushSubscription subscription = kiiUser.pushSubscription();
subscription.subscribe(topic);
最後に、
KiiUser#pushSubscription() でsubscriptionのインスタンスを作成し、
この3~6によって
ここでのポイントは、
Android Cloud SDKのAPIはブロッキングAPIとノンブロッキングAPIの双方を提供しています。実装する局面にあわせてこれらのAPIを上手にご活用ください。
サインインの実装
ここからは一度サインアップしたユーザが同じユーザで利用できるよう、
チャットアプリケーションでは2種類のログイン方法を提供します。
- サインアップ時に利用したユーザ識別子・
パスワードによる認証 - サインアップ・
サインイン時に取得したトークンによる認証
それぞれについて実装していきましょう。
・サインアップ時に利用したEmail・パスワードによる認証
サインアップ時に利用したEmail・
ユーザ識別子・
KiiUser.logIn(new KiiUserCallBack() {
@Override
public void onLoginCompleted(int token, KiiUser user, Exception e) {
if (e != null) {
// Something to do.
return;
}
if (checkRemember.isChecked()) {
// ログイン状態を保持する場合は、SharedPreferencesにAccessTokenを保存する
Logger.i(user.getAccessToken());
PreferencesManager.setStoredAccessToken(user.getAccessToken());
}
}
}, email, password);
AsyncTaskを利用していないため、
サインインが完了した場合、
もしサインインに成功している場合は、
・サインアップ・サインイン時に取得したアクセストークンによる認証
サインアップ・
アプリケーションをユーザが利用する際、
方法としては、
アクセストークンを用いてログインするメソッド:KiiUser.
KiiUser.loginWithToken(new KiiUserCallBack() {
@Override
public void onLoginCompleted(int token, KiiUser user, Exception e) {
if (e == null) {
// サインイン成功時はチャット画面に遷移
Intent intent = new Intent(MainActivity.this, ChatMainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
} else {
// サインイン失敗時はサインイン画面に遷移
PreferencesManager.setStoredAccessToken("");
Intent intent = new Intent(MainActivity.this, SigninActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
ProgressDialogFragment.hide(getSupportFragmentManager());
}
}, token);
AsyncTaskを利用していないため、
サインインが完了した場合、
もしサインインに成功した場合は、
これでサインインの機能は完成しました。アプリケーションを起動させて動作を確認してみてください。
以上で、
まとめ
ユーザサインアップ/サインインの実装を終えて、
ユーザ管理が必要なアプリケーションでは、
本連載ではAndroidを対象としていますが、
次回は主要機能の2つ目