やりたいこと
Flutterを利用してiOS/Android/Desktopで動くWebSocketのチャット機能を作成する。
なぜやるのか
- Flutterの学習
- WebSocketでリアルタイム通信を利用した次のアプリを作成する足掛かり
利用するパッケージ
事前準備
- Flutterのインストール https://flutter.dev/docs/get-started/install
- flutter doctorコマンド正常終了
- 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にチャレンジしてみます。
リポジトリ公開しました