Flutter SDK 概述
Flutter SDK 让你在 Flutter App(Android、iOS,另支持 macOS、Windows、Linux 桌面端)中接入 IM 服务:登录、长连接与断线重连、前后台切换、消息收发、会话同步和本地数据库都由 SDK 完成,你只需要把数据显示出来。离线推送(APNs、FCM 和国内厂商通道)和音视频通话(系统来电界面)由单独的包提供,按需依赖。
import 'package:deeprespond_im/deeprespond_im.dart';
import 'package:deeprespond_im_flutter/deeprespond_im_flutter.dart';
import 'package:flutter/material.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// 接入推送时,Firebase.initializeApp()、FCM 的后台处理函数和厂商通道的注册放在这里,见“离线推送”
final im = await DRClient.create(DRClientOptions(
appKey: '1575529652#demo',
apiUrl: Uri.parse('https://im.example.com'),
platform: DRFlutterPlatform.instance,
));
if (im.auth.currentUser == null) {
await im.auth.loginWithTicket(ticket: await fetchTicketFromYourServer()); // 已登录过的,创建后自动恢复
}
final list = im.conversations.list(); // 会话列表:先显示本地数据,后台同步
runApp(MaterialApp(
home: LiveListBuilder<ConversationView>(
list: list,
builder: (context, snapshot) => ListView(children: [for (final c in snapshot.items) ListTile(title: Text(c.conversationKey))]),
),
));
}能做什么
客户端对象 im(DRClient)按功能分为以下几个部分:
| 属性 | 功能 | 文档 |
|---|---|---|
im.auth、im.connection、im.config | 登录、退出、修改密码;连接状态与诊断;应用的运行配置 | 初始化、登录与连接 |
im.conversations | 会话列表、未读数、置顶、草稿、正在输入 | 会话 |
im.messages | 消息列表、发送、撤回、表情回应、置顶、已读回执、本地搜索 | 消息 |
im.users、im.friends、im.presence、im.devices | 本人与其他用户的资料、好友与黑名单、在线状态、本人的登录设备 | 用户、好友与在线状态 |
im.groups | 群、群成员、入群申请与邀请、入群链接 | 群组 |
im.files | 上传、下载、群文件 | 文件与图片 |
im.chatrooms | 聊天室 | 聊天室 |
im.calls | 一对一和群组的语音、视频通话 | 音视频通话 |
im.channels | 独立 RTC 频道:加入、恢复、媒体、状态与退出 | 频道接入 |
im.push、im.reports | 新消息提醒、推送设置、会话免打扰;举报 | 提醒、免打扰与举报 |
im.events、im.on<T>()、DRException | 事件、错误与提示文案 | 事件与错误处理 |
另外,离线推送的登记、权限和通知点击见离线推送;DRImage、LiveListBuilder、录音等 Flutter 组件见在 Flutter 界面中使用。第一次接入请先看快速集成。
包的组成
Flutter SDK 拆成几个包,App 按需要依赖。只收发文字和图片、不需要推送和通话的 App 只依赖前两个。
| 包 | 内容 | 什么时候需要 |
|---|---|---|
deeprespond_im | 核心:全部模块的 API(DRClient)、数据类型、事件、错误,显示辅助 package:deeprespond_im/render.dart。纯 Dart | 总是需要 |
deeprespond_im_flutter | Flutter 接入:平台实现 DRFlutterPlatform(前后台、网络变化、安全存储、设备信息)、原生的图片和视频处理、录音 VoiceRecorder、组件 DRImage、LiveListBuilder | 总是需要 |
deeprespond_im_push | 离线推送:APNs、FCM 的令牌登记,通知权限,通知的点击,前台时的显示控制,Android 通知渠道(DRPush)。依赖 firebase_core、firebase_messaging | 需要 App 不在前台时收到新消息提醒 |
deeprespond_im_push_huawei、_honor、_xiaomi、_oppo、_vivo、_meizu | 国内厂商的推送通道,只有 Android | 在中国大陆发布、需要在没有 Google 服务的手机上收到推送 |
deeprespond_im_call | 音视频通话:媒体连接、通话画面组件、系统来电界面(iOS 的 CallKit 与 PushKit,Android 的全屏来电通知与 Core-Telecom)、忙线检测。依赖 deeprespond_im_push | 需要语音、视频通话 |
推送包和来电包依赖了即生效:它们在 Flutter 注册插件时自动接入客户端,你只需在创建客户端时给出 push、call 选项(不给时对应的功能不启用)。厂商通道的包要在 main() 中调用各自的注册函数,见离线推送。
运行环境
| 平台 | 最低版本 | 推送 | 来电 |
|---|---|---|---|
| Android | 7.0(API 24) | FCM 和国内厂商通道(华为、荣耀、小米、OPPO、vivo、魅族) | 全屏来电通知和 Core-Telecom |
| iOS | 15.0 | APNs,另可登记 VoIP 推送(PushKit) | CallKit(在中国大陆 App Store 上架的版本不能使用,见音视频通话) |
| macOS | 12.0 | APNs(可选) | 应用内的界面 |
| Windows | 10 | 不提供 | 应用内的界面 |
| Linux | x64、Arm64,GTK 3 | 不提供 | 应用内的界面 |
- Flutter 和 Dart:Flutter 3.38.1 以上,Dart 3.10 以上。
- Android:各包的
minSdk为 24,以compileSdk36 编译,需要 JDK 17。App 的minSdk不能低于 24,compileSdk建议使用 36。 - iOS、macOS:App 的部署目标不能低于 iOS 15.0、macOS 12.0(Xcode 工程和
Podfile中都要设置)。原生部分同时提供 CocoaPods 和 Swift Package Manager 的配置,两种方式都可以使用。 - 桌面端:Windows、Linux 上收发消息、会话、群组、文件、聊天室等功能与移动端相同,但没有系统推送,App 关闭后收不到提醒;录音(
VoiceRecorder)只支持 Android 和 iOS,其他平台抛出unsupported。桌面端的连接一直按前台处理,最小化或失去焦点不影响连接。 - 不支持 Flutter Web:网页请使用 Web SDK。
- 鸿蒙:仍能运行 Android 应用的华为机型按 Android 处理(推送使用华为通道);HarmonyOS NEXT 原生应用不能使用本 SDK。
安装
在 App 的 pubspec.yaml 中加入依赖:
dependencies:
deeprespond_im: ^2.0.0
deeprespond_im_flutter: ^2.0.0
# 需要离线推送时
deeprespond_im_push: ^2.0.0
# 需要音视频通话时
deeprespond_im_call: ^2.0.0或者用命令添加:
flutter pub add deeprespond_im deeprespond_im_flutter所有包使用同一个版本号,一起发布,请让它们保持相同的版本。
权限
| 平台 | 权限 | 由谁声明 |
|---|---|---|
| Android | INTERNET、ACCESS_NETWORK_STATE、RECORD_AUDIO(录音) | deeprespond_im_flutter 的清单已声明,构建时自动合并,App 不需要再写 |
| Android | POST_NOTIFICATIONS(Android 13 起的通知权限) | deeprespond_im_push 的清单已声明;运行时的授权请求见离线推送 |
| Android | CAMERA、MODIFY_AUDIO_SETTINGS、BLUETOOTH_CONNECT、MANAGE_OWN_CALLS、USE_FULL_SCREEN_INTENT、前台服务(FOREGROUND_SERVICE 及 PHONE_CALL、MICROPHONE、CAMERA 类型)等通话所需的权限 | 只在 deeprespond_im_call 的清单中声明,不用通话的 App 不会带上它们,见音视频通话 |
| iOS | NSMicrophoneUsageDescription(麦克风的用途说明,录音和通话) | App 在 Info.plist 中写入,必需 |
| iOS | 推送、来电的能力和后台模式(remote-notification、voip、audio) | App 在 Xcode 中添加,见离线推送、音视频通话 |
| iOS | NSCameraUsageDescription(摄像头的用途说明,视频通话) | 使用视频通话的 App 在 Info.plist 中写入 |
| macOS | 网络访问(com.apple.security.network.client)和钥匙串(keychain-access-groups)的权利;使用录音、通话时另需麦克风、摄像头的用途说明 | App 在 entitlements 和 Info.plist 中写入 |
运行时的麦克风、摄像头授权由 SDK 在录音、通话时请求,用户拒绝时抛出 permission_required(details['permissions'] 列出缺少的权限)。各平台的完整配置(部署目标、备份规则、开发时的明文请求等)见快速集成。
显示辅助与提示文案
deeprespond_im 包中另有一个按需导入的库 package:deeprespond_im/render.dart:
| 内容 | 说明 |
|---|---|
| 显示辅助 | displayName(用户的显示名,按好友备注、群昵称、昵称、用户名取第一个非空的)、conversationTitle(会话标题)、summarize(会话列表中最后一条消息的摘要)、renderTip(群提示的文字)、renderCallRecord(通话记录的文字)、renderRecall(撤回提示),用法见消息 |
| 提示文案 | zhCN(中文文案表,可以整体替换为其他语言)、describeError(按错误码给出提示文字),见事件与错误处理 |
import 'package:deeprespond_im/render.dart';基本概念
客户端对象
DRClient.create() 创建客户端(异步),整个 App 共用这一个:同一进程中同一个 AppKey 只有一个客户端,再次调用返回同一个对象。客户端与进程同生命周期,没有释放的方法。创建时读取本地保存的登录状态,这台设备上已经登录过的,SDK 立即恢复登录,你不必再调用登录。详见初始化、登录与连接。
可订阅的列表
会话列表、消息列表、好友列表、群成员列表等会持续变化的数据,以可订阅的对象(LiveList,消息列表为 MessageList)提供:
import 'package:deeprespond_im/deeprespond_im.dart';
final list = im.conversations.list();
final sub = list.stream.listen((snapshot) {
// 订阅时先收到当前快照,之后每次变化收到新快照
print('${snapshot.items.length} 个会话,loading=${snapshot.loading},hasMore=${snapshot.hasMore}');
});
// 不再显示时
await sub.cancel();
list.dispose();snapshot是当前的快照,同步读取;stream在订阅时先发出当前快照,之后每次变化发出新快照,dispose()后结束。- 新快照中没有变化的条目仍是原来的对象,
ListView的条目可以按引用判断是否需要重建。快照和其中的数据都不可修改。 - 同一轮事件循环中的多次变化合并为一次通知。
- 在 Widget 中用
LiveListBuilder订阅并重建界面,见在 Flutter 界面中使用。 - 不再显示时调用
dispose()释放。退出登录、切换用户时 SDK 先把快照清空并通知一次,再释放全部列表。
登录状态、连接状态、未读总数等单个的值可以同步读取(如 im.auth.state、im.conversations.getUnreadTotal()),变化时发出对应的事件。
数据对象
服务端的对象(消息、会话、用户、群等)以只读的类型化对象交给你:常用字段为 camelCase 的属性(如 message.clientMsgId、conversation.unreadCount),时间为 DateTime(UTC),ID 为 String。每个对象的 raw 保存服务端返回的原始 JSON(字段名与服务端 REST API 相同,如 client_msg_id),服务端以后新增的字段不必等 SDK 升级,就可以从 raw 中读取。
本地优先,后台同步
会话列表、消息、好友、群等数据都保存在 App 沙盒中的本地数据库里,你读到的总是本地的数据:App 启动后立即显示上次的内容,不必等待网络。SDK 在后台连接长连接、同步变化,写入本地后再通知你。离线时发送的消息进入发送队列,网络恢复后自动发出;App 被关闭后再次打开,队列中的消息继续发送。
前后台与推送
在 Android 和 iOS 上,SDK 自动跟踪 App 的前后台状态:App 切到后台时 SDK 通知服务端,之后的新消息由服务端以推送送达(需要接入离线推送);回到前台时立即恢复连接并同步。你不需要处理前后台切换,详见前后台与网络变化。
与服务端的关系
Flutter SDK 只调用 IM 服务的客户端接口,用户的身份由你的业务服务端担保:
- 你的业务服务端用 App Token 调用 IM 服务的 REST API,为用户创建 IM 账号,并在用户登录你的业务系统后为他签发登录凭证;
- App 从你的业务服务端取得凭证,交给 SDK 登录 IM;
- 之后收发消息、同步会话都由 SDK 直接与 IM 服务通信。
App Token 和 Client Secret 是服务端凭据,不能出现在 App 中。AppKey(org_name#app_name)是应用的公开标识,可以写在 App 中,在控制台的应用详情中查看。推送使用的证书和密钥在控制台的推送凭据中配置,App 中只写凭据的名称。
与 Web SDK 的区别
Flutter SDK 由 Web SDK 移植而来,模块、方法和行为基本相同,主要的区别是:
| Web SDK | Flutter SDK |
|---|---|
createDRClient() 同步创建;destroy() 释放 | DRClient.create() 异步创建,与进程同生命周期,重复调用返回同一个客户端 |
| 数据对象的字段为服务端的 snake_case 字段名 | 类型化的对象,字段为 camelCase,另有 raw |
im.on('message.received', fn) | im.on<MessageReceived>() 返回 Stream;全部事件为 im.events |
list.getSnapshot()、list.subscribe() | list.snapshot、list.stream |
DRError、AbortSignal | DRException、DRCancelToken |
数据保存在 IndexedDB,令牌保存在 localStorage | 数据保存在 SQLite(可选加密),令牌保存在系统的安全存储(钥匙串、Keystore) |
| 多个标签页共用一个连接 | 一个进程一个客户端;后台 isolate 中使用轻量的 DRBackgroundClient |
| 浏览器通知 | 系统推送(APNs、FCM、国内厂商通道)、角标、系统来电界面 |
独立 RTC 频道
已提供独立频道接入源码,调用 API、媒体权限与前后台边界见频道接入。频道版本制品尚未发布,实际支持和验收范围见平台表。
