LoginSignup
2
0

More than 1 year has passed since last update.

【Flutter/Dart】Firebase/Firestoreを使ったチャットアプリを作ろう

Last updated at Posted at 2023-03-25

1.はじめに

新たに6つのAndroidStudio&Flutter&Firebase記事を書いている。以下は内容、

今回はバックエンドにFirebaseを搭載したFlutterでわかりやすく複雑なチャットアプリケーションを作成する。

2. チャットアプリを作ろう

Firebaseのプロジェクトについては認証アプリで作成した。同じプロジェクトのページを開き、Cloud Firestoreを選択する。
step2_1_1.png

以下のページでデータベースの作成を押す。
step2_1_2.png

以下のページでテストモードを開始するを選択し、次へを押す。
step2_1_3.png

有効にするを押す。
step2_1_4.png

以下の画面が出たら暫く待つ。
step2_1_5.png

以下の画面が表示されたらクラウド側の準備は完了。
step2_1_6.png

AndroidStudioにて、チャットアプリを作るための新規プロジェクトを作成する。
step2_1_7.png

以下は認証アプリと同様に、classpathをandroid/build.gradleの中にコピーする。
step2_1_9.png

以下は認証アプリと同様に、android/app/build.gradleにidをペーストしてapply plugin: 'com.google.gms.google-services'の通りに書き換える。
step2_1_11.png

以下は認証アプリと同様に、dependenciesの中のimplementationの2行をコピーしてandroid/app/build.gradleにペーストする。
step2_1_14.png

以下は認証アプリと同様に、2つのパッケージをdart packageで検索、コピーしたバージョン情報をpubspec.yamlにペースト、右上のPub getを押す。
step2_1_8.png

applicationIdが"com.example.my_chat_app"になっていることを確認する。
step2_1_12.png

以下は認証アプリと同様に、android/app/build.gradleのminSdkVersionを23に、targetSdkVersionを30に変更する。applicationIdを"com.example.my_auth_app"に書き換える。これで、認証アプリと同じFirebaseプロジェクトのデータベースを利用できる様になる。
step2_1_13.png

lib/main.dartにチャット用のコードを記述。

.dart
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Chat App',
      theme: new ThemeData(
          primaryColor: Colors.red
      ),
      home: new UserPage(),
    );
  }
}

class UserPage extends StatefulWidget {

  @override
  _UserPageState createState() => new _UserPageState();
}

class _UserPageState extends State<UserPage> {

  final _controller = TextEditingController();
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("User Name Input Screen"),
          backgroundColor: Colors.red
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Container(
            margin: EdgeInsets.all(12.0),
            child: TextFormField(
              controller: _controller,
              decoration: InputDecoration(
                  labelText: 'User Name'
              ),
            ),
          ),
          ElevatedButton(
            onPressed: () {
              Navigator.push(
                  context, MaterialPageRoute(builder: (builder) => ChatPage(_controller.text)));
            },
            child: Text("Setup complete", style: TextStyle(color: Colors.white),),
          )
        ],
      ),
    );
  }
}


class ChatPage extends StatefulWidget {
  ChatPage(this._userName);

  final String _userName;

  @override
  _ChatPageState createState() => new _ChatPageState();
}

class _ChatPageState extends State<ChatPage> {
  final _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("chat page"),
            backgroundColor: Colors.red
        ),
        body: Container(
          margin: const EdgeInsets.symmetric(horizontal: 10.0),
          child: Column(
            children: <Widget>[
              Flexible(
                child: StreamBuilder<QuerySnapshot>(
                  stream: FirebaseFirestore.instance
                      .collection("ChatApp")
                      .orderBy("time", descending: true)
                      .snapshots(),
                  builder: (context, snapshot) {
                    if (!snapshot.hasData) return Container();
                    return new ListView.builder(
                      padding: new EdgeInsets.all(8.0),
                      reverse: true,
                      itemBuilder: (_, int index) {
                        DocumentSnapshot document =
                        snapshot.data!.docs[index];

                        bool isSelfText = false;
                        if (document['username'] == widget._userName) {
                          isSelfText = true;
                        }
                        return isSelfText
                            ? _SelfText(
                            document['sent_text'], document['username'])
                            : _OtherText(
                            document['sent_text'], document['username']);
                      },
                      itemCount: snapshot.data!.docs.length,
                    );
                  },
                ),
              ),
              new Divider(height: 1.0),
              Container(
                margin: EdgeInsets.only(bottom: 20.0, right: 10.0, left: 10.0),
                child: Row(
                  children: <Widget>[
                    new Flexible(
                      child: new TextField(
                        controller: _controller,
                        onSubmitted: _handleSubmit,
                        decoration:
                        new InputDecoration.collapsed(hintText: "send text"),
                      ),
                    ),
                    new Container(
                      child: new IconButton(
                          icon: new Icon(
                            Icons.chat,
                            color: Colors.red,
                          ),
                          onPressed: () {
                            _handleSubmit(_controller.text);
                          }),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ));
  }

  Widget _SelfText(String message, String userName) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.end,
      children: <Widget>[
        Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            SizedBox(height: 12.0,),
            Text(userName, style: TextStyle(color: Colors.red)),
            Text(message),
          ],
        ),
        Icon(Icons.person, color:Colors.red),
      ],
    );
  }

  Widget _OtherText(String message, String userName) {
    return Row(
      children: <Widget>[
        Icon(Icons.person_outline),
        Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            SizedBox(height: 12.0,),
            Text(userName),
            Text(message),
          ],
        )
      ],
    );
  }

  _handleSubmit(String message) {
    _controller.text = "";
    var db = FirebaseFirestore.instance;
    db.collection("ChatApp").add({
      "username": widget._userName,
      "sent_text": message,
      "time": DateTime.now()
    }).then((val) {
      print("Success");
    }).catchError((err) {
      print(err);
    });
  }
}

まずユーザー1の名前を入力する。
step2_1_15.png

次にユーザー1のままテキストを投稿する。
step2_1_16.png

次に前の画面に戻ってユーザー2の名前を入力し、ユーザー2のテキストを投稿する。
step2_1_17.png

ユーザー2名分のテキストが、Cloud Firestoreのデータベースに反映されていることが確認できる。
step2_1_18.png

以上で、FlutterとFirebaseを用いたチャットアプリが完成した。

3.まとめ

FlutterとFirebaseを用いたチャットアプリの作成方法を学んだ。

2
0
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
2
0