Flutter即时通讯插件xmpp_client_web的使用
Flutter即时通讯插件xmpp_client_web的使用
轻量级的XMPP客户端库,完全用Dart编写。我的目的是为未来的基于Flutter的XMPP客户端编写一个易于使用的库。
支持的文档:
- RFC6120:可扩展的消息与存在协议(XMPP):核心
- RFC6121:可扩展的消息与存在协议(XMPP):即时消息与存在
- XEP-0198:流管理
- XEP-0085:聊天状态通知
- XEP-0318:客户端发起的存在探测最佳实践
- XEP-0280:消息碳副本
部分支持:
- XEP-0030:服务发现
- XEP-0313:消息归档管理
积极开发中:
- XEP-0059:结果集管理
- XEP-0004:数据表单
最新动态
- 2021-12-14:添加了对XEP-0016的支持:隐私列表
- 2020-10-30:添加了对XEP-0280的支持:消息碳副本
- 2020-10-30:初步支持XEP-0313:消息归档管理
- 2020-10-30:添加了日志机制
- 2020-07-23:添加了对XEP-0318的支持:客户端发起的存在探测最佳实践
- 2020-05-02:添加了对XEP-0198的初步支持:流管理
- 2020-05-02:添加了对XEP-0085的初步支持:聊天状态通知
- 2019-04-02:添加了对XEP-0054的支持:vcard-temp
- 2019-04-01:添加了SHA-1和SHA-256认证算法的支持
使用方法
import 'package:xmpp_client_web/xmpp_stone.dart' as xmpp;
void main() {
xmpp.XmppAccountSettings accountSettings = xmpp.XmppAccountSettings.fromJid('nick@damain.com/resource', 'password');
accountSettings.port = kIsWeb ? 5291 : 5222;
accountSettings.wsPath = 'xmpp-websocket'; // null 或者自定义的 xmpp 路径
accountSettings.wsProtocols = ['xmpp']; // 或者自定义的协议
xmpp.Connection connection = xmpp.Connection.getInstance(accountSettings);
connection.open();
}
功能特性
1. 日志记录
日志级别
客户端可以设置库的日志级别:
Log.logLevel = LogLevel.VERBOSE;
XMPP流量日志
可以启用或禁用XMPP流量日志:
Log.logXmpp = false;
2. 消息归档管理
此功能仍在开发中,API可能会发生变化。
模块获取
connection.getMamModule()
查询所有消息
mamManager.queryAll();
基于日期查询消息(所有参数都是可选的)
mamManager.queryByTime(start: startTime, end: endTime, jid: buddyJid);
基于消息ID查询消息(所有参数都是可选的)
mamManager.queryById(beforeId: beforeId, afterId: afterId, jid: buddyJid});
检查服务器功能
mamManager.isQueryByDateSupported
mamManager.isQueryByIdSupported
mamManager.isQueryByJidSupported
完整示例代码
以下是完整的示例代码,演示了如何使用 xmpp_client_web
插件进行基本的即时通讯。
import 'dart:async';
import 'package:xmpp_client_web/src/logger/Log.dart';
import 'package:xmpp_client_web/xmpp_stone.dart' as xmpp;
final String TAG = 'example';
void main(List<String> arguments) async {
Log.logLevel = LogLevel.DEBUG;
Log.logXmpp = false;
Log.d(TAG, 'Setting up XMPP connection...');
var userAtDomain = 'nemanja@127.0.0.1';
var password = '1';
var jid = xmpp.Jid.fromFullJid(userAtDomain);
var account = xmpp.XmppAccountSettings(
userAtDomain, jid.local, jid.domain, password, 5222,
resource: 'xmppstone');
var connection = xmpp.Connection(account);
// 注册监听器
connection.connectionStateStream.listen((state) {
Log.d(TAG, 'Connection state: $state');
if (state == xmpp.XmppConnectionState.ForcefullyClosed) {
Log.d(TAG, 'Connection lost. Attempting to reconnect...');
reconnect(connection);
}
});
var messagesListener = ExampleMessagesListener();
ExampleConnectionStateChangedListener(connection, messagesListener);
var presenceManager = xmpp.PresenceManager.getInstance(connection);
presenceManager.subscriptionStream.listen((streamEvent) {
if (streamEvent.type == xmpp.SubscriptionEventType.REQUEST) {
Log.d(TAG, 'Accepting presence request');
presenceManager.acceptSubscription(streamEvent.jid);
}
});
var receiver = 'nemanja2[@test](/user/test)';
var receiverJid = xmpp.Jid.fromFullJid(receiver);
var messageHandler = xmpp.MessageHandler.getInstance(connection);
// 等待连接就绪
await waitForConnectionReady(connection);
// 发送消息
sendMessageSafely(messageHandler, receiverJid, 'Hello from xmpp_stone!');
// 连接
connection.connect();
}
// 等待连接就绪
Future<void> waitForConnectionReady(xmpp.Connection connection) async {
while (connection.state != xmpp.XmppConnectionState.Ready) {
await Future.delayed(const Duration(milliseconds: 500));
}
}
// 重新连接
void reconnect(xmpp.Connection connection) async {
Log.d(TAG, 'Attempting to reconnect...');
await Future.delayed(const Duration(seconds: 2));
connection.connect();
}
// 安全发送消息
void sendMessageSafely(xmpp.MessageHandler handler, xmpp.Jid receiverJid, String message) {
try {
handler.sendMessage(receiverJid, message);
Log.d(TAG, 'Message sent: $message');
} catch (e) {
Log.d(TAG, 'Failed to send message: $e');
}
}
class ExampleConnectionStateChangedListener
implements xmpp.ConnectionStateChangedListener {
late xmpp.Connection _connection;
late xmpp.MessagesListener _messagesListener;
ExampleConnectionStateChangedListener(
xmpp.Connection connection, xmpp.MessagesListener messagesListener) {
_connection = connection;
_messagesListener = messagesListener;
_connection.connectionStateStream.listen(onConnectionStateChanged);
}
[@override](/user/override)
void onConnectionStateChanged(xmpp.XmppConnectionState state) {
if (state == xmpp.XmppConnectionState.Ready) {
Log.d(TAG, 'Connected');
setupXMPPFeatures();
}
}
Future<void> setupXMPPFeatures() async {
var vCardManager = xmpp.VCardManager(_connection);
var messageHandler = xmpp.MessageHandler.getInstance(_connection);
var rosterManager = xmpp.RosterManager.getInstance(_connection);
// 获取自己的VCard
var vCard = await vCardManager.getSelfVCard();
Log.d(TAG, 'Your info: ${vCard.buildXmlString()}');
// 添加联系人到通讯录
var receiver = 'nemanja2[@test](/user/test)';
var receiverJid = xmpp.Jid.fromFullJid(receiver);
var addResult = await rosterManager.addRosterItem(xmpp.Buddy(receiverJid));
if (addResult.description != null) {
Log.d(TAG, 'Roster added: ${addResult.description}');
}
// 获取联系人的VCard
var receiverVCard = await vCardManager.getVCardFor(receiverJid);
Log.d(TAG, 'Receiver info: ${receiverVCard.buildXmlString()}');
// 启动存在状态监听器
var presenceManager = xmpp.PresenceManager.getInstance(_connection);
presenceManager.presenceStream.listen(onPresence);
// 启动消息监听器
messageHandler.messagesStream.listen(_messagesListener.onNewMessage);
}
void onPresence(xmpp.PresenceData event) {
Log.d(TAG, 'Presence event from ${event.jid!.fullJid!}: ${event.showElement}');
}
}
class ExampleMessagesListener implements xmpp.MessagesListener {
[@override](/user/override)
void onNewMessage(xmpp.MessageStanza? message) {
if (message?.body != null) {
Log.d(TAG, 'New Message from ${message!.fromJid!.userAtDomain}: ${message.body}');
}
}
}
更多关于Flutter即时通讯插件xmpp_client_web的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Flutter即时通讯插件xmpp_client_web的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用xmpp_client_web
插件来实现即时通讯的示例代码。这个示例将展示如何连接到XMPP服务器、认证用户以及发送和接收消息。
首先,确保你的Flutter项目已经添加了xmpp_client_web
依赖。在pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
xmpp_client_web: ^x.y.z # 替换为最新版本号
然后运行flutter pub get
来安装依赖。
接下来是示例代码:
import 'package:flutter/material.dart';
import 'package:xmpp_client_web/xmpp_client_web.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
XmppClient? client;
String? status;
String? messageContent;
@override
void initState() {
super.initState();
connectAndAuthenticate();
}
Future<void> connectAndAuthenticate() async {
// 配置XMPP客户端
var options = XmppClientOptions(
jid:Jid('your-username@your-xmpp-server'),
password: 'your-password',
server: 'your-xmpp-server',
port: 5222,
useTls: true,
);
client = XmppClient(options);
// 监听连接状态
client!.connectionStatus!.listen((event) {
setState(() {
status = 'Connection Status: $event';
});
if (event == XmppConnectionStatus.connected) {
// 连接成功后发送在线状态
client!.sendPresence();
}
});
// 监听消息
client!.messageReceived!.listen((message) {
setState(() {
messageContent = message.body;
});
});
// 连接到服务器并认证
await client!.connect();
}
Future<void> sendMessage(String to, String body) async {
if (client!.isConnected!) {
var message = Message(
to: Jid(to),
body: body,
);
await client!.sendMessage(message);
} else {
print('Client is not connected');
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('XMPP Client Demo'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(status ?? 'Connecting...'),
SizedBox(height: 20),
TextField(
decoration: InputDecoration(labelText: 'To'),
onChanged: (value) async {
// 这里可以添加逻辑来选择或输入接收者JID
},
),
SizedBox(height: 10),
TextField(
decoration: InputDecoration(labelText: 'Message'),
onChanged: (value) {
// 输入消息内容
},
onEditingComplete: () async {
// 当用户完成输入时发送消息
await sendMessage('receiver-jid@your-xmpp-server', messageContent ?? '');
},
),
SizedBox(height: 20),
Text(messageContent ?? 'No message received yet'),
],
),
),
);
}
}
注意事项:
- 依赖版本:确保
xmpp_client_web
的版本是最新的,或者根据官方文档选择一个兼容的版本。 - JID格式:XMPP中的JID(Jabber Identifier)通常是
username@domain
格式。确保你使用的JID和服务器地址是正确的。 - 安全性:在实际应用中,不要在客户端代码中硬编码密码。考虑使用更安全的方法,如OAuth或其他认证机制。
- 错误处理:示例代码中没有包含详细的错误处理逻辑。在实际应用中,应该添加适当的错误处理来应对网络问题、认证失败等情况。
- UI优化:示例UI非常基础,你可以根据需要进行优化和美化。
这个示例展示了如何使用xmpp_client_web
插件进行基本的XMPP通信。根据你的需求,你可能需要扩展这个示例以支持更多功能,如群聊、文件传输等。