14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

and factoryAdvent Calendar 2018

Day 3

【第1回】何人が何十回やってるか分からないが、それでも俺はFirebaseでチャットアプリを作りたい

Last updated at Posted at 2018-12-03

はじめに

Firebaseって最高ですよね!サーバーサイドやインフラ周りのことを極力考えずにクライアント側の開発に集中できるのは、アプリ開発者にとってはこの上ない幸せだと思います。
今回はそんなFirebaseを使った簡単なチャットアプリの作り方を3回に渡って説明していきます。第一回目はFirebaseのセットアップとログイン処理を実装します。
全体のソースコードは以下です。
https://github.com/maru01/MyChat

やること

  • 何人が何十回やってるか分からない擦り倒されたネタ「Firebaseでチャットアプリを作る」をやります。
  • OSはAndroidです。
  • 使用するFirebaseのサービスはFirestoreのみです。

アプリの仕様

  • ユーザーは名前とパスワードを入力することによりログインできます。
  • 同じ名前のユーザーを作ることはできません。
  • 任意のユーザーには、パスワードを知っていれば誰でもログインできます。
  • ユーザーはチャット部屋を作ることができます。
  • チャット部屋内では自分のチャットと他人のチャットを区別できます。

やらないこと

  • Firebaseの説明
  • セキュリティ周り。無視して進めます。実際のプロダクトではセキュリティルールをしっかり定義してユーザーがRead/Writeできるデータを限定する必要があります。

    https://firebase.google.com/docs/firestore/security/get-started?hl=ja
  • アーキテクチャ周り。MVVMで綺麗に書きたいところですが本質ではないためこだわりません。

本題の前に

Qiita初投稿のため至らない点が数多くあるかと思います。温かく見守っていただけると幸いです。
では本題。

Firebaseのセットアップ

Firebaseのセットアップは簡単です。
FirebaseコンソールにログインしてFirebaseプロジェクトを作ります。完了したら「開始するにはアプリを追加してください」の上のドロイド君アイコンをクリックします。
スクリーンショット 2018-12-03 17.46.51.png
↓のような画面が表示されるので指示に従い入力項目を埋めていきます。
スクリーンショット 2018-12-03 17.50.39.png

アプリの追加が完了したらFirebaseコンソールの右側のメニューから「Database」をクリックし、表示された画面で「データベースの作成」をクリックします。
スクリーンショット 2018-12-03 18.25.28.png

セキュリティルールを設定するダイアログが表示されます。セキュリティ周りを無視するため「テストモード」を選択して「有効にする」をクリックします。実際のプロダクトでは必ず「ロックモード」を選択しましょう。
スクリーンショット 2018-12-03 19.33.21.png

以上!

何度も言いますが、今のセキュリティルールではあるユーザーが他のユーザーの情報を書き換えたり他のユーザーのチャットを書き換えたりできてしまうので実運用の時はセキュリティルールをしっかり定めましょう!

クライアントの実装

依存を追加

build.gradleにfirestoreライブラリの依存を追加します。


dependencies {
    implementation 'com.google.firebase:firebase-firestore:17.1.3'
}

dataBindingとRecyclerViewも使いたいので追加します。


apply plugin: 'kotlin-android'

android {
    dataBinding {
        enabled = true
    }
}
dependencies {
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
}

ログイン画面

  • ユーザー名を入力してもらう
  • 入力されたユーザー名が未登録の場合はパスワード作成を促し、入力が終わったら次の画面へ遷移する。
  • 入力されたユーザー名が既に登録済みの場合はパスワード入力を促し、登録済みのパスワードと比較し一致したら次の画面へ遷移する。一致しない場合は遷移せずToastを表示する。

を実装します。

以下、ログイン画面のソースコードです。

class LoginActivity : AppCompatActivity() {

    var users: List<User>? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding: ActivityLoginBinding =
                DataBindingUtil.setContentView(this, R.layout.activity_login)

        val db = FirebaseFirestore.getInstance()

        db.collection("users")
                .addSnapshotListener { querySnapshot, _ ->
                    users = querySnapshot?.toObjects(User::class.java)
                }

        binding.login.setOnClickListener {
            val userName = binding.userName.text.toString()
            if (!userName.isNullOrBlank()) {
                val result = users?.find {
                    it.name == userName
                }
                if (result == null) {
                    val layout = layoutInflater.inflate(R.layout.dialog_password, null, false)
                    AlertDialog.Builder(this)
                            .setTitle("パスワードを作成")
                            .setView(layout)
                            .setPositiveButton(android.R.string.ok) { _, _ ->
                                val password = layout.password.text.toString()
                                val user = User(userName, password)
                                db.collection("users")
                                        .add(user)
                                RoomActivity.start(this, userName)
                            }
                            .setNegativeButton(android.R.string.cancel, null)
                            .show()
                } else {
                    val layout = layoutInflater.inflate(R.layout.dialog_password, null, false)
                    AlertDialog.Builder(this)
                            .setTitle("パスワードを入力")
                            .setView(layout)
                            .setPositiveButton(android.R.string.ok) { _, _ ->
                                val password = layout.password.text.toString()
                                if (password == result.password) {
                                    RoomActivity.start(this, userName)
                                } else {
                                    Toast.makeText(this, "パスワードが違います", Toast.LENGTH_SHORT).show()
                                }
                            }
                            .setNegativeButton(android.R.string.cancel, null)
                            .show()
                }
            }
        }
    }
}

登録されたユーザーを管理するcollectionを作成し、"users"と名付けます。同時にユーザーの追加を監視します。

val db = FirebaseFirestore.getInstance()

// Firestore上の"users"collectionへの参照を取得する。
// "users"collectionが無ければ自動で作られる。
db.collection("users")
// "users"コレクションを監視する。変化があればメンバーのusersを更新する。
        .addSnapshotListener { querySnapshot, _ ->
            users = querySnapshot?.toObjects(User::class.java)
        }

// デフォルト引数に空文字を指定しています。引数なしのコンストラクタを用意するためです。
// 引数なしのコンストラクタがないとExceptionが発生するので注意してください。
data class User(var name: String = "",
                var password: String = "")

次にログイン処理です。"users"collectionにユーザーが入力した名前が無ければ、新たに追加します。

val user = User(userName, password)
db.collection("users")
    .add(user)

この処理を実行すると、Firebaseコンソール上の"users"collectionに新たにdocumentが追加されることが確認できます。さらにそのdocumentにはstring型の"name"フィールドとstring型の"password"フィールドがあり、それぞれにユーザーが入力した文字列が格納されていることが確認できます。
このようにdocumentと呼ばれる"フィールド"と"collection"を持ったファイルと、そのdocumentの集合であるcollectionによってデータを管理するのがFirestoreです。

これで、Firestore上にユーザーを追加していく準備が整いました。

次回は部屋一覧の取得/監視および、部屋の作成を実装します。

14
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?