使用Laravel Echo和Laravel Echo Server在Flutter应用程序中进行双向通信
前段时间,我在业务中使用了Laravel Echo,将未读通知的功能实现在Flutter应用中。
我想要一并发布一个备忘录。
版本
$ php artisan --version
Laravel Framework 7.30.6
$ flutter --version
Flutter 3.0.4 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 85684f9300 (3 weeks ago) • 2022-06-30 13:22:47 -0700
Engine • revision 6ba2af10bb
Tools • Dart 2.17.5 • DevTools 2.12.2
Laravel的配置
首先让我们在Laravel端进行Laravel Echo的设置。
这次我们想要使用laravel-echo-server来实现,而不是使用Pusher。
安装Redis
首先要安装Redis。由于我使用的是Mac操作系统,所以可以使用以下命令进行安装。
如果本地已经安装了Redis,则当然不需要再次进行安装。
// インストール
$ brew install redis
让我们在redis-server上启动Redis服务。尝试启动一次。
$ redis-server
42978:C 24 Jul 2022 16:23:49.242 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
42978:C 24 Jul 2022 16:23:49.242 # Redis version=7.0.3, bits=64, commit=00000000, modified=0, pid=42978, just started
42978:C 24 Jul 2022 16:23:49.242 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
42978:M 24 Jul 2022 16:23:49.243 * Increased maximum number of open files to 10032 (it was originally set to 2560).
42978:M 24 Jul 2022 16:23:49.243 * monotonic clock: POSIX clock_gettime
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 7.0.3 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 42978
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | https://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
42978:M 24 Jul 2022 16:23:49.244 # WARNING: The TCP backlog setting of 511 cannot be enforced because kern.ipc.somaxconn is set to the lower value of 128.
42978:M 24 Jul 2022 16:23:49.244 # Server initialized
42978:M 24 Jul 2022 16:23:49.244 * Ready to accept connections
请记住在此处显示的端口号(在上述示例中为6379),稍后将用于配置。
Laravel Echo 的安装
接下来,请转到项目根目录并执行以下命令,安装 Laravel Echo 等工具。
// laravel Echoに必要なライブラリのインストール
$ composer require predis/predis
$ npm install --save laravel-echo socket.io-client
// laravel-echo-serverをインストール
$ npm install -g laravel-echo-server
// laravel echoの初期設定を行いlaravel-echo-server.jsonを作成する
$ laravel-echo-server init
// ローカル環境の時のものです。参考にしてください
? Do you want to run this server in development mode? Yes
? Which port would you like to serve from? 6001
atomu@okunoMacBook-Pro mygolf % laravel-echo-server init
? Do you want to run this server in development mode? Yes
? Which port would you like to serve from? 6001
? Which database would you like to use to store presence channel members? redis
? Enter the host of your Laravel authentication server. http://localhost
? Will you be serving on http or https? http
? Do you want to generate a client ID/Key for HTTP API? Yes
? Do you want to setup cross domain access to the API? Yes
? Specify the URI that may access the API: http://localhost:8000
? Enter the HTTP methods that are allowed for CORS: GET, POST
? Enter the HTTP headers that are allowed for CORS: Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id
? What do you want this config to be saved as? laravel-echo-server.json
appId: f526a01938a20971
key: 7e9ec298b4b10e8dccc0e5c930bb8c94
Configuration file saved. Run laravel-echo-server start to run server.
当查看创建的laravel-echo-server.json时,我认为其中的”redis”部分是{}。
我将对此部分进行以下编辑。
{
"databaseConfig": {
// この部分を記入する
"redis": {
"scheme" : "tls",
"host" : "localhost",
// redisを起動した時に表示されたポート
"port" : "6379"
// config/database.phpのredis.options.prefixの値
"keyPrefix": "laravel_database_"
},
},
}
请注意的是keyPrefix的部分。
请将该部分设置为config/database.php中redis.options.prefix的值。
<?php
use Illuminate\Support\Str;
return [
・・・
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
// ここに入る
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],
・・・
];
这可能有点复杂,但这就是完成的版本。
顺便提一下,在这里创建的laravel-echo-server.json文件因为每个环境不同,建议将其添加到.gitignore中。
Laravel的设置
接下来我们来进行Laravel框架的设置。
首先,你需要取消注释config/app.php中的App\Providers\BroadcastServiceProvider::class。
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// ここのコメントアウトを外す
App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
SimpleSoftwareIO\QrCode\QrCodeServiceProvider::class,
App\Providers\ViewComposerServiceProvider::class,
然后编辑.env文件。
// 両方とも既にある場合はredisに変更、そもそも記載ない場合は追記
BROADCAST_DRIVER=redis
QUEUE_CONNECTION=redis
REDIS_CLIENT=predis
请确保记得及时更新缓存哦。
$ php artisan config:cache
创建通知活动
当你达到这一步,接下来要创建一个能够通知Flutter应用程序的事件。你可以使用php artisan make:event命令以事件的类名来创建事件,请随意选择一个名称进行创建。
由于我想发送关于通知的公告,我选择了NewInformationEvent。
$ php artisan make:event NewInformationEvent
Event created successfully.
通知するチャンネル名と送信する値をこのファイルに記述していきます。
今回は
-
- チャンネル名:test-channel
- 送信する値:message
我們將按照這樣的設置方式進行設定。
在类名之后,再添加 implements ShouldBroadcast。
完成形将呈现如下形式。
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
// implements以降を追加
class NewInformationEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
// チャンネル名
return new Channel('test-channel');
}
public function broadcastWith()
{
return [
// 送信する値
'message' => 'テストです!',
];
}
}
现在Laravel的设置已经完成了!
Flutter的配置
让我们接下来进行Flutter的设置。
在Flutter中,要监听从Laravel发送的广播,需要使用以下包。
引入软件包
首先,我们需要引入软件包。
$ flutter pub add socket_io_client
$ flutter pub add laravel_echo
$ flutter pub get
接收通知的设置
我会在main.dart文件中添加以下记录。
import 'package:laravel_echo/laravel_echo.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;
void main() async {
・・・
// 追記
Echo echo = Echo({
'broadcaster': 'socket.io',
// laravel-echo-server initで設定したホスト:ポート
'client': IO.io('http://localhost:6001'),
});
// php artisan make:event イベントのクラス名で作成したイベント名とチャンネル名
echo.channel('test-channel').listen('NewInformationEvent', (e) {
print(e);
});
・・・
}
按照公式文件的要求,是这样结束的!
测试
那我们马上进行测试吧。我本来以为只需要运行flutter run就可以了,但遗憾的是,据说Laravel Echo包还不支持Null Safety。
我在查看公式时发现,只有测试版支持Null Safety,所以我只能安装了测试版。
另外,我安装了不同的版本,因为如果安装最新版本的socket_io_client的话,它无法运行。
dependencies:
// 変更
laravel_echo: ^1.0.0-beta.1
// 変更
socket_io_client: ^1.0.1
$ flutter pub get
随之而来,main.dart也会进行一些微调。
void main() async {
・・・
IO.Socket socket = IO.io(
'http://localhost:6001',
IO.OptionBuilder()
.disableAutoConnect()
.setTransports(['websocket']).build(),
);
Echo echo = Echo(
broadcaster: EchoBroadcasterType.SocketIO,
client: socket,
);
・・・
}
再次执行flutter run
$ flutter run
Launching lib/main.dart on iPhone 13 in debug mode...
Running Xcode build...
└─Compiling, linking and signing... 10.0s
Xcode build done. 43.7s
好的!!
尝试通过Laravel发送通知
既然成功构建了,让我们尝试从Laravel发送通知。
首先,在Laravel端启动Redis、Laravel Echo Server和队列。
redisの起動
$ redis-server
启动Laravel Echo Server
$ laravel-echo-server start
L A R A V E L E C H O S E R V E R
version 1.6.3
⚠ Starting server in DEV mode...
✔ Running at localhost on port 6001
✔ Channels are ready.
✔ Listening for http events...
✔ Listening for redis events...
Server ready!
启动队列工作者
$ php artisan queue:work
只要没有发生错误,就可以了。
可以使用event(new PublicEvent())在想要通知的地方通过Laravel进行通知。
由于这次是考试,我想试试从Tinker通知。
$ php artisan tinker
Psy Shell v0.11.5 (PHP 7.4.24 — cli) by Justin Hileman
>>> use App\Events\NewInformationEvent;
>>> event(new NewInformationEvent());
=> []
Flutter的控制台
flutter: {message: テストです!, socket: null}
完成了!
最后
第一次尝试使用Laravel-echo-server真的很麻烦呢…
我觉得还是直接使用Pusher比较好。
如果有任何不顺利或者不理解的地方,请在评论中告诉我。
非常感谢你!