LoginSignup
11
15

More than 3 years have passed since last update.

FlutterでWebSocketのチャットアプリを作ってみる

Last updated at Posted at 2021-02-07

やりたいこと

Flutterを利用してiOS/Android/Desktopで動くWebSocketのチャット機能を作成する。

image.png

なぜやるのか

  1. Flutterの学習
  2. WebSocketでリアルタイム通信を利用した次のアプリを作成する足掛かり

利用するパッケージ

web_socket_channel

事前準備

  1. Flutterのインストール https://flutter.dev/docs/get-started/install
  2. flutter doctorコマンド正常終了
  3. flutter createコマンドでプロジェクト作成

実装

変更箇所だけ、先に紹介します。

pubspec.yaml
dependencies:
  # add start---------------------
  io: ^0.3.4
  html: ^0.14.0+4
  web_socket_channel: ^1.2.0
  # add end  ---------------------
  flutter:
    sdk: flutter
macos/Runner/DebugProfile.entitlements
    <key>com.apple.security.network.client</key>
    <true/>
macos/Runner/Release.entitlements
    <key>com.apple.security.network.client</key>
    <true/>
lib/main.dart
import 'package:flutter/material.dart';
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_socket_channel/status.dart' as status;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Chat app',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ChatPage(),
    );
  }
}

class ChatPage extends StatefulWidget {
  @override
  _ChatPageState createState() => _ChatPageState();
}

class _ChatPageState extends State<ChatPage> {
  List<String> messages = [];
  WebSocketChannel channel;

  @override
  void initState() {
    super.initState();
    // channel = IOWebSocketChannel.connect(Uri.parse('wss://echo.websocket.org'));
    channel = IOWebSocketChannel.connect(Uri.parse('ws://localhost:8081'));
    channel.stream.listen((message) {
      setState(() {
        messages.add(message);
      });
    });
  }

  @override
  void dispose() {
    super.dispose();
    channel.sink.close(status.goingAway);
  }

  @override
  Widget build(BuildContext context) {
    TextEditingController _controller = TextEditingController();
    void _sendMessage() {
      if (_controller.text.isNotEmpty) {
        channel.sink.add(_controller.text);
      }
    }

    return Scaffold(
      appBar: AppBar(
        title: Text('WebSocket chat app'),
      ),
      body: ListView(
        children: [
          ...messages.map((element) => ListTile(title: Text(element)))
        ],
      ),
      bottomNavigationBar: BottomAppBar(
        shape: const CircularNotchedRectangle(),
        child: Container(
          height: 100.0,
          child: Form(
            child: TextFormField(
              decoration: const InputDecoration(
                icon: Icon(Icons.message),
                labelText: 'Send message',
              ),
              textInputAction: TextInputAction.next,
              controller: _controller,
              validator: (String value) {
                return null;
              },
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _sendMessage,
        tooltip: 'Send message',
        child: Icon(Icons.send),
      ),
    );
  }
}

解説

WebSocket接続

    // channel = IOWebSocketChannel.connect(Uri.parse('wss://echo.websocket.org'));
    channel = IOWebSocketChannel.connect(Uri.parse('ws://localhost:8081'));

WebSocketサーバに接続して、チャンネルを取得します。

メッセージ取得

    channel.stream.listen((message) {
      setState(() {
        messages.add(message);
      });
    });
  }

受信したメッセージをStateに格納して、アプリに表示します。

メッセージ送信

    void _sendMessage() {
      if (_controller.text.isNotEmpty) {
        channel.sink.add(_controller.text);
      }
    }

入力されたメッセージを送信します。

WebSocket切断

    channel.sink.close(status.goingAway);

チャンネルを切断します。

やってみて感想

Flutterのドキュメントや参考サイトが少なく手が出せていませんでしたが、
今回アプリを開発してみようと調べてみると、公式ドキュメントや技術ページが想像以上に充実していてすぐ実装できました。

お恥ずかしながら、一番時間がかかったのはflutter doctorをクリアすることでした。

次は、WebSocketをシグナリングサーバとして、WebRTCにチャレンジしてみます。

リポジトリ公開しました

11
15
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
11
15