Flutter SDK overview
The Flutter SDK adds IM to Flutter apps on Android and iOS, plus macOS, Windows and Linux desktops. The SDK handles sign-in, the long-lived connection and reconnects, foreground / background transitions, sending and receiving messages, conversation sync and the local database; you only display the data. Offline push (APNs, FCM and Chinese vendor channels) and audio / video calls (with the system incoming-call screen) come in separate packages that you add when you need them.
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))]),
),
));
}
| Item | Details |
|---|---|
| Current version | 1.0.0-alpha.4, pre-release (Versions and support) |
| Install | flutter pub add deeprespond_im_flutter |
| Platforms | Android 7.0, iOS 15, macOS 12, Windows 10, Linux (GTK 3) and later; not Flutter Web |
| Requirements | Flutter 3.38.1 and Dart 3.10 or later |
| API reference | The deeprespond_im API docs on pub.dev |
What you can build
The client object im (DRClient) is split by feature:
| Property | Purpose | Docs |
|---|---|---|
im.auth, im.connection, im.config | Sign-in, sign-out and password changes; connection state and diagnostics; the app's runtime configuration | Initialization, sign-in and connection |
im.conversations | Conversation list, unread counts, pinning, drafts, typing indicators | Conversations |
im.messages | Message lists, sending, recalling, reactions, pinning, read receipts, local search | Messages |
im.users, im.friends, im.presence, im.devices | Your own and other users' profiles, friends and block list, presence, your signed-in devices | Users, friends and presence |
im.groups | Groups, members, join requests and invitations, invite links | Groups |
im.files | Uploads, downloads, group files | Files and images |
im.chatrooms | Chat rooms | Chat rooms |
im.calls | One-to-one and group voice and video calls | Audio and video calls |
im.channels | Standalone RTC channels: join, resume, media, state and leave | Channels |
im.push, im.reports | New-message alerts, push settings, muting conversations; reports | Alerts, Do Not Disturb and reports |
im.events, im.on<T>(), DRException | Events, errors and message text | Events and errors |
Push registration, permissions and notification taps are covered in Offline push; Flutter widgets such as DRImage, LiveListBuilder and voice recording are in Using the SDK in Flutter UI. For your first integration, start with the Quickstart.
Packages
An app that only sends and receives messages needs just deeprespond_im_flutter. It re-exports the whole core API, so your code needs a single import. Offline push, calls and the Chinese vendor push channels bring large native dependencies, so they're optional packages you add when you use them.
| Package | Contents | When you need it |
|---|---|---|
deeprespond_im_flutter | The API for every module (DRClient), data types, events and errors; the platform implementation DRFlutterPlatform (foreground / background, network changes, secure storage, device info); native image and video processing; the VoiceRecorder; the DRImage and LiveListBuilder widgets; display helpers in package:deeprespond_im_flutter/render.dart | Always |
deeprespond_im_push | Offline push: APNs and FCM token registration, notification permission, notification taps, foreground display control, Android notification channels (DRPush). Depends on firebase_core and firebase_messaging | When users should be alerted to new messages while the app isn't in the foreground |
deeprespond_im_push_huawei, _honor, _xiaomi, _oppo, _vivo, _meizu | Chinese vendor push channels, Android only | When you ship in mainland China and need push on phones without Google services |
deeprespond_im_call | Audio and video calls: the media connection, call view widgets, the system incoming-call screen (CallKit and PushKit on iOS; full-screen incoming-call notifications and Core-Telecom on Android), busy detection. Depends on deeprespond_im_push | For voice and video calls |
The core API actually lives in the pure-Dart deeprespond_im package, which deeprespond_im_flutter pulls in and re-exports, so Flutter apps don't depend on it directly. Only Dart programs that don't use Flutter (command-line tools, tests on the Dart VM) depend on it directly.
The push and call packages take effect once added: they hook into the client when Flutter registers plugins, and you only pass the push and call options when creating the client (without them, those features stay off). Vendor channel packages need their registration functions called in main(), see Offline push.
Requirements
| Platform | Minimum version | Push | Incoming calls |
|---|---|---|---|
| Android | 7.0 (API 24) | FCM and Chinese vendor channels (Huawei, Honor, Xiaomi, OPPO, vivo, Meizu) | Full-screen incoming-call notifications and Core-Telecom |
| iOS | 15.0 | APNs, plus optional VoIP push (PushKit) | CallKit (not allowed for apps on the mainland China App Store, see Audio and video calls) |
| macOS | 12.0 | APNs (optional) | In-app UI |
| Windows | 10 | Not available | In-app UI |
| Linux | x64, Arm64, GTK 3 | Not available | In-app UI |
- Flutter and Dart: Flutter 3.38.1 or later, Dart 3.10 or later.
- Android: every package has
minSdk24, is compiled withcompileSdk36 and needs JDK 17. Your app'sminSdkcan't be lower than 24;compileSdk36 is recommended. - iOS and macOS: your app's deployment target can't be lower than iOS 15.0 or macOS 12.0 (set it in both the Xcode project and the
Podfile). The native parts support both CocoaPods and Swift Package Manager. - Desktop: on Windows and Linux, messaging, conversations, groups, files, chat rooms and the rest work as on mobile, but there's no system push, so users get no alerts once the app is closed. Voice recording (
VoiceRecorder) only works on Android and iOS and throwsunsupportedelsewhere. Desktop connections are always treated as foreground; minimizing or losing focus doesn't affect them. - No Flutter Web: for web pages, use the Web SDK.
Install
The packages are published under deeprespond.cn on pub.dev; the current version is the 1.0.0-alpha.4 pre-release, and each package page has a Changelog. From 1.0.0-alpha.4 on, depending on deeprespond_im_flutter is enough. When upgrading from an earlier version, you can remove the deeprespond_im dependency and change imports of package:deeprespond_im/deeprespond_im.dart and package:deeprespond_im/render.dart to package:deeprespond_im_flutter/deeprespond_im_flutter.dart and package:deeprespond_im_flutter/render.dart; the old imports still work. Add the dependencies to your app's pubspec.yaml:
dependencies:
deeprespond_im_flutter: ^1.0.0-alpha.4
# 需要离线推送时
deeprespond_im_push: ^1.0.0-alpha.4
# 需要音视频通话时
deeprespond_im_call: ^1.0.0-alpha.4Or add it from the command line:
flutter pub add deeprespond_im_flutterAll packages share one version number and are released together; keep them on the same version.
Permissions
| Platform | Permission | Declared by |
|---|---|---|
| Android | INTERNET, ACCESS_NETWORK_STATE, RECORD_AUDIO (voice recording) | Already in the deeprespond_im_flutter manifest and merged at build time; your app doesn't need to declare them |
| Android | POST_NOTIFICATIONS (the notification permission from Android 13) | Already in the deeprespond_im_push manifest; for requesting it at runtime see Offline push |
| Android | Call permissions such as CAMERA, MODIFY_AUDIO_SETTINGS, BLUETOOTH_CONNECT, MANAGE_OWN_CALLS, USE_FULL_SCREEN_INTENT and foreground services (FOREGROUND_SERVICE with the PHONE_CALL, MICROPHONE and CAMERA types) | Only in the deeprespond_im_call manifest, so apps without calls don't get them; see Audio and video calls |
| iOS | NSMicrophoneUsageDescription (why the app uses the microphone, for recording and calls) | Your app's Info.plist; required |
| iOS | Push and call capabilities and background modes (remote-notification, voip, audio) | Added by your app in Xcode; see Offline push and Audio and video calls |
| iOS | NSCameraUsageDescription (why the app uses the camera, for video calls) | Your app's Info.plist, if you use video calls |
| macOS | The network client (com.apple.security.network.client) and keychain (keychain-access-groups) entitlements; microphone and camera usage descriptions if you use recording or calls | Your app's entitlements and Info.plist |
The SDK requests microphone and camera access at runtime when recording or calling; if the user refuses, it throws permission_required (details['permissions'] lists what's missing). The full per-platform setup (deployment targets, backup rules, cleartext requests during development and so on) is in the Quickstart.
Display helpers and message text
deeprespond_im_flutter also has an optional library, package:deeprespond_im_flutter/render.dart:
| Contents | Details |
|---|---|
| Display helpers | displayName (a user's display name: the first non-empty of friend remark, group nickname, nickname and username), conversationTitle (conversation title), summarize (the last-message summary in the conversation list), renderTip (group notice text), renderCallRecord (call record text), renderRecall (recall notice). See Messages |
| Message text | zhCN (the Chinese string table, which you can replace wholesale with another language) and describeError (message text for an error code). See Events and errors |
import 'package:deeprespond_im_flutter/render.dart';Core concepts
The client object
DRClient.create() creates the client asynchronously, and the whole app shares it: a process has one client per AppKey, and calling it again returns the same object. The client lives as long as the process and has no dispose method. On creation it reads the saved sign-in state; if the user has signed in on this device before, the SDK restores the session immediately and you don't need to sign in again. See Initialization, sign-in and connection.
Subscribable lists
Data that keeps changing, such as the conversation list, message lists, the friend list and group members, comes as subscribable objects (LiveList, or MessageList for messages):
import 'package:deeprespond_im_flutter/deeprespond_im_flutter.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();snapshotis the current snapshot, read synchronously.streamemits the current snapshot on subscription, then a new one on every change, and closes afterdispose().- Unchanged items in a new snapshot are still the original objects, so
ListViewitems can compare by reference to decide whether to rebuild. Snapshots and their data are immutable. - Several changes in the same event loop turn produce one notification.
- In widgets, use
LiveListBuilderto subscribe and rebuild, see Using the SDK in Flutter UI. - Call
dispose()when the list is no longer shown. On sign-out or when switching users, the SDK clears the snapshots, notifies once, then disposes every list.
Single values such as sign-in state, connection state and the total unread count can be read synchronously (for example im.auth.state and im.conversations.getUnreadTotal()) and emit the matching events when they change.
Data objects
Server objects (messages, conversations, users, groups and so on) reach you as read-only typed objects. Common fields are camelCase properties (such as message.clientMsgId and conversation.unreadCount), times are DateTime in UTC, and IDs are String. Each object's raw holds the original JSON from the server (with the same field names as the server REST API, such as client_msg_id), so you can read fields the server adds later without waiting for an SDK update.
Local first, synced in the background
Conversations, messages, friends, groups and other data are stored in a local database in the app sandbox, and what you read is always local data: on launch the app shows the previous content immediately without waiting for the network. The SDK keeps the connection open and syncs changes in the background, writing them locally before notifying you. Messages sent while offline go into a send queue and are sent once the network is back; if the app is closed and reopened, the queue carries on.
Foreground, background and push
On Android and iOS, the SDK tracks whether the app is in the foreground. When the app goes to the background, the SDK tells the server, and new messages then arrive as push notifications (this needs Offline push). Back in the foreground, it reconnects and syncs right away. You don't need to handle these transitions; see Foreground, background and network changes.
How it works with your server
The Flutter SDK only calls the IM service's client APIs; your own server vouches for who the user is:
- Your server calls the IM REST API with an App Token to create an IM account for the user, and after the user signs in to your system, issues a sign-in ticket for them.
- The app gets the ticket from your server and passes it to the SDK to sign in to IM.
- From then on, the SDK talks to the IM service directly to send and receive messages and sync conversations.
The App Token and Client Secret are server credentials and must never appear in the app. The AppKey (org_name#app_name) is the app's public identifier and can be included in the app; find it in the app details in the console. Push certificates and keys are configured under Push credentials in the console; the app only contains the credential name.
Differences from the Web SDK
The Flutter SDK is a port of the Web SDK, with essentially the same modules, methods and behavior. The main differences:
| Web SDK | Flutter SDK |
|---|---|
createDRClient() creates synchronously; destroy() releases | DRClient.create() is async and lives as long as the process; repeated calls return the same client |
| Data objects use the server's snake_case field names | Typed objects with camelCase fields, plus raw |
im.on('message.received', fn) | im.on<MessageReceived>() returns a Stream; all events are on im.events |
list.getSnapshot(), list.subscribe() | list.snapshot, list.stream |
DRError, AbortSignal | DRException, DRCancelToken |
Data in IndexedDB, tokens in localStorage | Data in SQLite (optionally encrypted), tokens in the system's secure storage (Keychain, Keystore) |
| Multiple tabs share one connection | One client per process; background isolates use the lightweight DRBackgroundClient |
| Browser notifications | System push (APNs, FCM, Chinese vendor channels), badges, the system incoming-call screen |
Standalone RTC channels
im.channels handles audio and video channels for meetings, voice rooms and other uses without a group. See Channels for the API, media permissions and foreground / background handling, and Versions and support for platform support.
