前回は、チャットルームの実装について解説しました。第8回となる今回は、チャットアプリケーションのメイン機能であるメッセージの送受信機能を実装していきます。テキストメッセージのやりとりだけでは少し寂しいので、最近流行りのスタンプを送信できる機能も追加で実装したいと思います。
今回使用したソースコードについては、GitHubで公開しています。こちらもあわせてご覧ください。
メッセージ送受信機能の実装
実装に入る前に、第5回で説明したメッセージ送受信機能について簡単に確認してみましょう。新たにスタンプを送信する機能を追加することになったので、第5回で説明したデータフローにスタンプを保存するchat_stampsバケットが追加されています。
- 新規スタンプのアップロード:ユーザは好きな画像を“chat_stamps”バケットにアップロードすることでスタンプとして利用できます。アップロードされたスタンプはチャットを利用するすべてのユーザが使用することができます。
- スタンプ一覧の取得:スタンプを送信する場合は、まず、“chat_stamps”バケットを検索して利用可能なスタンプの一覧を取得します。その後、1件ずつスタンプの画像をダウンロードして画面に表示します。
- メッセージの送信:メッセージの送信は“chat_room”バケットにKiiObjectを保存することで実現できます。チャットの相手は対象の”chat_room”バケットを購読しているはずなので、新しいKiiObjectを保存するだけで、自動的にプッシュ通知が相手に届きます。
- メッセージの受信:メッセージの受信はプッシュ通知を契機におこないます。プッシュ通知を受信したら、対象の“chat_room”バケットを検索しメッセージを取得して画面に表示します。受信したメッセージがスタンプを含んでいる場合は、スタンプの画像をダウンロードします。同じ画像を何回もダウンロードする必要がないように、画像は端末にキャッシュとして保存しておきます。
この4つのフローの実装について、以下で説明していきます。
①新規スタンプのアップロード
スタンプはアプリケーションスコープの”chat_stamp”バケットに保存されるKiiObjectとして実装します。今まで説明してきたKiiObjectと異なる点は、Object Bodyとして画像ファイルを保持するところです。アップロード処理のフローは以下になります。
スタンプに関係する処理は基本的にChatStampクラスに実装されています。さっそく実際のコードを見ていきましょう。
ChatStampクラスは大きく2種類のコンストラクタを提供しています。新たにスタンプを追加する場合は、ファイルを指定するコンストラクタを使用します。スタンプをKiiObjectとして保存した後は、そのKiiObjectのURIを指定するコンストラクタを使用します。
ChatStamp#save()メソッドでKiiObjectの保存と、画像ファイルのアップロードを行っています。
まずKiiObject#save() でKiiObjectを保存します。このタイミングでこのスタンプのURIが割り当てられます。次にKiiObject#uploader(Context, File) でKiiUploaderのインスタンスを生成し、KiiUploader#transfer(KiiRTransferProgressCallback)で画像ファイルをアップロードしています。実際にアップロードしているファイルはユーザがギャラリーアプリケーションから選択した画像ファイルを適切なサイズに縮小したファイルになります。
また、今回のケースではアップロードの進捗状況を管理する必要がないのでKiiRTransferProgressCallbackにはnullを指定していますが、サイズの大きいファイルなどをアップロードする場合はKiiRTransferProgressCallbackを使ってユーザに進捗状況を通知したほうがいいでしょう。
最後に、アップロードした画像ファイルをキャッシュに移動しています。こうすることでこのスタンプを再度表示する際にKiiCloudからダウンロードしないですみます。
②スタンプ一覧の取得
スタンプ一覧の取得は、大きく2つの処理に分割されます。
- “chat_stamps”バケット内のすべてのオブジェクトを検索する(画像は含まない)
- 取得したKiiObject全てに対して画像を取得する
“chat_stamps”バケットを検索しただけでは、スタンプの画像(Object Body)は取得できません。表示する必要が生じたタイミングでそれぞれ個別に画像をダウンロードする必要があります。
実際のソースコードは、画像のキャッシュ処理や、ダウンロードのキャンセル処理などを実装しているため、少々複雑になっていますが、ここではKiiCloudとのやりとりの部分に絞って説明します。興味のある方は是非、ソースコードをダウンロードして他の部分も読んでみてください。
まず、ChatStampクラスに実装されているスタンプ一覧を取得する処理を見ていきます。
スタンプ一覧の取得には第6回でも登場したKiiQueryを使用します。今回は、"chat_stamps"バケット内の全てのスタンプを取得して、“_created”プロパティの値によりソートします。
これはスタンプの表示順が毎回変わってしまうのを防止するためです。
“_created”はKiiObjectを保存するとKiiCloudが自動的に追加するプロパティでKiiObjectが保存された日時が保存されています。同様に更新日時が保存される"_modified"もあります。
これらのプロパティは一覧を時系列でソートしたい場合にとても役に立ちます。
つづいて画像をダウンロードする処理を見ていきましょう。アップロード処理のコードと非常に似ていて簡単に理解できるかと思います。
KiiObject#downloader(Context, File) KiiDownloaderのインスタンスを生成しKiiDownloader#transfer(KiiRTransferProgressCallback)で画像ファイルをダウンロードしています。
③メッセージの送信
メッセージの送信処理はChatActivityクラスに実装されています。メッセージはテキストとスタンプの2種類があり、どちらも“chat_room”バケットにKiiObjectとしてテキストを保存することで実現しています。
通常のテキストとスタンプの違いは、メッセージに“$STAMP:”というプリフィックスがついているかどうかです。スタンプの場合はこのプリフィックスの後にスタンプ画像を表すKiiObjectのURIが続きます。
コードは下記のようにChatMessageのインスタンスを生成して、KiiObject#save() メソッドで保存しているだけのシンプルな実装になっています。
④メッセージの受信
メッセージの受信処理は、プッシュ通知を契機に実行されます。
前回のチャットルームの実装で説明したのと同様にGCMPushReceiver#onReceiveにプッシュ通知を受け取った処理を記述します。今回はバケット内のオブジェクト作成を契機に、プッシュメッセージが通知されます。その場合のプッシュメッセージのメッセージタイプはPUSH_TO_APPになります。
受信したメッセージを表すReceivedMessageインスタンスは、メッセージタイプによってキャストするクラスが異なることに注意してください。
今回はメッセージタイプがPUSH_TO_APPなのでPushToAppMessageクラスにキャストしてメッセージからKiiObjectを取り出しています。
受信したメッセージが自身が所属するグループ(ChatRoom)宛のメッセージか確認した後にBroadcast Intentを使ってChatActivityに新規メッセージを受信したことを伝えます。
ChatActivityクラスでは、Broadcast Intentを受信した時にKiiCloudからメッセージの取得処理を実装します。具体的にはchat_roomバケットを検索して結果をListViewに表示します。検索の方法は2種類あり、条件無しで全件取得する方法と、最後にメッセージを取得した日時を検索条件にして、最新のメッセージのみを取得する方法です。最新のメッセージのみを取得する方法では、“_created” プロパティにKiiClause#greaterThan()メソッドを使って“◯◯より大きい”という条件を作成しています。
また、自身が送信したメッセージについてもサーバから取得して表示しているのは、一見すると無駄に思えますがメッセージの前後関係をメッセージがサーバーに保存された時間でソートするために必要な処理になります。
メッセージをListViewに表示する処理はChatActivityクラスのインナークラスであるMessageListAdapterに実装されています。
具体的にはメッセージが自分自身が送信したメッセージかどうかによって表示レイアウトを変更して、メッセージがスタンプの場合はバックグラウンドでスタンプの画像を取得して表示します。画像のダウンロード処理は「 2. スタンプ一覧の取得」で説明したコードと同じです。
以上で、メッセージ送受信機能についての解説を終えます。
今回の実装で簡単ではありますがメッセージのやりとりを行えるアプリケーションが完成しました。チャットアプリケーションのような通信アプリを作成する場合、サーバーサイドの実装が必要不可欠であり、実装、デプロイ、運用と様々なコストが発生します。
MBaaSの登場により、これらのコストを抑えて簡単にアプリケーションを実装することが可能になっています。無料プランから始められますので是非一度サインアップしてMBaaSの力を体験してみてください。
次回の第9回はチャットアプリケーションを拡張して、FacebookやTwitterと連携する方法を解説していきます。