Global Chatと呼ばれている(?)形式で、誰でもあらかじめ登録しておけばChatに参加できるという単純なチャット・アプリ。もちろん、push notificationなんて便利なものは備わっていない。pullしに行かないとダメ。あらかじめ登録しておいたニックネームを入力すればChat Roomにログインできる。チャットのメッセージが左右に分かれることもなく、リスト形式で表示される。
パスワード登録もなく、2〜3人の仲間内で使う「おもちゃ」、または秘密の連絡ツール?(作成途中で、なかなかうまくいかず、何度も中断があり、作成し始めてから結構時間が経過しているが、当初は、「MySecretMemo」と呼んでいた)。
Chatの内容はFirebaseのRealtime DBに保存されるので、Firebaseを通じてのコミュニケーションということになる。
今回は、DBを扱う時の基本4機能(CRUD:Create,Read,Update,Delete)のうち、U(Update)の更新機能を除く3機能を備えたもの。
アプリ実行のビデオ:
スクリーンのデザイン:
メインスクリーンとChat Roomのスクリーン(右側)
ブロック・コード:
既にCR(U)Dの部分については、以前取り上げているので、復習も兼ねることになる。
=>Screen1(メイン画面)
参加者のニックネームをリスト形式で変数registeredNamesに格納。登録されていないニックネームを入力すると、Warningが表示される。
Chat Roomに遷移する際、データとしてニックネームを渡す。
=>postsScreen
変数ならびにLsitView1を初期化する関数を設定しておく。
まず、TagListを取得。(Firebase RESTでデータをpostした際に各データに自動的に与えられるIDのリスト)
本アプリ用にはFirebaseのRealtime DB内のproject endpoint URLに「MySecretMemo」というdirectoryが設定されており、通常、Firebaseの所定のURL + MySecretMemo + .json でGETリクエストを行うと、MySecretMemo以下の全てのデータが返される。
しかし、「?shallow=true」を付加しておくと、MySecretMemo直下のデータのみを返してくれる。直下のデータとは、postした際に自動的に付されたID。(以下図)なお、実際に返ってくるデータは、[["-01g1UHk4sG5pttoICpb", true],[......],.....]のようにBool値とペアーとなったリスト形式となっており、IDのみを抽出するために、index=1 のデータのみを取り出している。(「when Web2.GotText」のcomponentの通り)
実際には、(ちょっと古いデータだが)以下のように各IDの下に具体的なデータが、キー/値の形式で格納されており、?shallow=trueを付けなければこれら全てが返される。設定したキーは、Date、Message、Nameの3つ。
Firebase データベース REST API の使い方等については、以前にも紹介した以下を参考にした。
Firebase Database REST API (Google)
Firebase Demo: No Security with Web Component (by METRIC RAT AI2)
そして、データを取得する。Clockを使っている理由は、今回、Firebaseとのデータの受け渡しがスムーズにいかない場合が多かったので、それぞれのデータの受け渡し時にClockを使って時間的余裕(約1秒:500ms x 2)を作るため。何の役に立つの?という疑問が湧いてくるかもしれないが、このようにすると割とうまくデータの受け渡しができるようになったのも事実。今回はやたらと使った。
全てのデータを受け取るので、?shallow=true の設定はなし。
データ取得に成功すれば、データを抽出してMessage, Name, Dateのアイテムごとの変数にリスト形式で格納。
*************** 以下 makeNameList、makeDateListの各関数が同様に定義。省略。 *******************
それら抽出されたデータをListViewに表示するため、関数makeFinalDataを実行し、同関数により統合されたデータ(finalData)をListViewに表示させている。なお、extensionを利用して、表示の順番を新しいものから古いものへとdescending order(降順)に変更している
関数makeFinalDataの内容:
Message, Name, Dateごとにデータを抽出し、適宜体裁を整えて変数finalDataへ追加している。Nameについては、現在ログイン中のメンバーであれば、「赤丸+Me」 を、出なければ Youを頭に付加している。
メッセージをポストする「send」ボタンをタップした時の動作:
現在の時刻、ニックネーム、メッセージをDictionary形式で所定のFirebase URL + 所定のdirectory.jsonにPOST。
「サーバーと交信中...」のメッセージが表示され、若干時間(約1秒:500ms x 2)をおいて関数reloadを実行。関数reloadは、データ取得(GETリクエスト)=>データのListViewへの表示を行う。
なお、Realtime Databaseにまだメッセージがない場合は、Firebaseの所定のproject URL + /<アプリ用の任意のDirectory名> + .jsonに対し、dictionary形式のデータと共にPOSTすると、自動的に<アプリ用のDirectory名>を作成してくれる。(今回のDirectory名は、MySecretMemo)
ListViewのアイテムをタップして選択=>削除の可否を聞くメッセージが表示 =>削除の対象となるメッセージのID(tageList)を取得
「削除する」を選択=> 所定のFirebase の project URL + 所定のdirectory + /ID + .jsonに対しDeleteを実行
若干時間(約1秒:500ms x 2)をおいて、再度関数getTagList、関数getDataを実行する。(関数reloadを実行しても同じ)
Firebaseとのデータのやり取りがなかなかうまくいかない時もあるので、そのような時は、この「Reload」ボタンをタップ。
postするメッセージを書き込むmessageTextBoxに書き込んだテキストを削除する「delete」ボタン(X)の動作
「Log out」ボタン:ニックネームを入力する最初の画面に戻るボタン
<課題>
1. 誰でも誰のpostでも削除できるようになっているが、ログインした人の自分のpostしか削除できないようにしたい。
2. まだうまくデータを取得できないことがまれにあるので、Firebaseとの間のデータの受け渡しを100%安定させたい。
**************************************************
データベースに対するCRUD操作に関する以前のブログ:
MIT App Inventorで遊ぶ (Journal アプリ4 D / REST API)
MIT App Inventorで遊ぶ (Journal アプリ3 U / REST API)
MIT App Inventorで遊ぶ (Journal アプリ2)
MIT App Inventorで遊ぶ (Journal アプリ1C & R / REST API)