帮你快速理解、总结文档立即下载

Flutter

最近更新时间:2026-08-20 14:38:30
我的收藏
本文将介绍如何在 Flutter 工程中集成 TIMPush。

前提条件

开始接入前,请先完成目标平台的推送前提配置,并准备好注册所需参数。按平台查看:
Android
iOS
请确认已 开通 Push 服务,并按需完成 Android 厂商配置(小米 / 华为 / OPPO / vivo / 荣耀 / 魅族 / Google FCM)。Flutter Android 侧至少需要准备:
资源
用途
SDKAppID、客户端密钥(Push Key)
调用 registerPush
timpush-configs.json
放入 Android 应用模块 assets
目标厂商配置文件(如有)
华为、荣耀、Google FCM 等按厂商要求放入工程
工程 applicationId
与厂商平台应用包名一致
TIMPush 版本号 VERSION
厂商通道包依赖版本,见 更新日志
完整资源清单与获取路径见 Android 前提条件
请确认已 开通 Push 服务 并完成 iOS 厂商配置。Flutter iOS 侧至少需要准备:
资源
用途
SDKAppID、Push Key
调用 registerPush
证书 ID(businessID / apnsCertificateID
腾讯云控制台上传 APNs 证书后生成,经 registerPush 传入
App Group ID(可选)
仅触达统计需要,经 registerPushapplicationGroupID 传入
完整资源清单见 iOS 前提条件
本文示例中的 VERSIONSDKAppIDAppKey、证书 ID、App Group ID 均为占位符,请勿在代码仓库中提交真实密钥。

AI 集成

通过 npx 安装 @tencent-rtc/trtc-push-skill 到本地 AI IDE 中,辅助完成 TIMPush 离线推送集成。安装后,您可以直接向 AI 输入“集成 Flutter 离线推送”“帮我集成 Flutter TIMPush”等需求,AI 将根据项目类型引导您完成环境检测、厂商通道配置、凭据填写、代码接入和验证等步骤。详情可参考 AI Coding

手动集成

步骤1:集成 TIMPush SDK

如果您想手动集成,请按顺序完成下述步骤。

集成 Flutter 插件

Flutter 工程需要先引入推送插件。您可以在 pubspec.yaml 中添加依赖,也可以执行以下命令自动安装:
flutter pub add tencent_cloud_chat_push

配置原生工程

完成 Flutter 插件集成后,继续完成对应原生平台配置。
Android
iOS
请先按 Android TIMPush 公共集成Android 厂商通道集成 完成原生工程配置。
与原生 Android 的差异如下,请按下方完成:
1. 厂商通道包:Flutter 插件已处理 TIMPush 基础依赖,不要再添加 com.tencent.timpush:timpush / tuicore。只需按需引入目标厂商通道包。
2. 自定义 Application:必须继承 TencentCloudChatPushApplication
android/app/build.gradleandroid/app/build.gradle.kts 按需引入目标厂商的 TIMPush 通道包。只有引入对应厂商包,才能启用该厂商的原生推送能力。VERSION 请前往 更新日志 获取并替换为实际版本号。
小米
华为
OPPO
vivo
荣耀
魅族
Google FCM
Groovy DSL
Kotlin DSL
implementation 'com.tencent.timpush:xiaomi:VERSION'
implementation("com.tencent.timpush:xiaomi:VERSION")
Groovy DSL
Kotlin DSL
implementation 'com.tencent.timpush:huawei:VERSION'
implementation("com.tencent.timpush:huawei:VERSION")
Groovy DSL
Kotlin DSL
implementation 'com.tencent.timpush:oppo:VERSION'
implementation("com.tencent.timpush:oppo:VERSION")
Groovy DSL
Kotlin DSL
implementation 'com.tencent.timpush:vivo:VERSION'
implementation("com.tencent.timpush:vivo:VERSION")
Groovy DSL
Kotlin DSL
implementation 'com.tencent.timpush:honor:VERSION'
implementation("com.tencent.timpush:honor:VERSION")
Groovy DSL
Kotlin DSL
implementation 'com.tencent.timpush:meizu:VERSION'
implementation("com.tencent.timpush:meizu:VERSION")
Groovy DSL
Kotlin DSL
implementation 'com.tencent.timpush:fcm:VERSION'
implementation("com.tencent.timpush:fcm:VERSION")
Android 端还需要创建或复用自定义 Application 类,并继承 TencentCloudChatPushApplication。如果工程中已存在自定义 Application,直接改为继承该类,并确保 onCreate() 中调用 super.onCreate()
package com.example.pushdemo

import com.tencent.chat.flutter.push.tencent_cloud_chat_push.application.TencentCloudChatPushApplication

class MyApplication : TencentCloudChatPushApplication() {
override fun onCreate() {
super.onCreate()
}
}
然后在 android/app/src/main/AndroidManifest.xml<application> 标签中配置 android:name,指向上述自定义 Application 类。
<application
android:name=".MyApplication"
...>
</application>
Flutter 插件会处理 TIMPush 相关依赖,不需要执行原生 iOS 文档中“主 App target 集成”步骤。您只需要在 ios/Runner/AppDelegate.swift 中补充 TIMPush 相关配置,用于返回推送证书 ID、App Group ID,以及转发离线推送点击事件。证书 ID 与 App Group ID 由 registerPush 传入,再经下列桥接方法返回给 TIMPush。
import UIKit
import Flutter

// Add these two import lines
import TIMPush
import tencent_cloud_chat_push

// Add `, TIMPushDelegate` to the following line
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate, TIMPushDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

// Add this function
@objc func businessID() -> Int32 {
return TencentCloudChatPushFlutterModal.shared.businessID();
}

// Add this function
@objc func applicationGroupID() -> String {
return TencentCloudChatPushFlutterModal.shared.applicationGroupID()
}
// Add this function
@objc func onRemoteNotificationReceived(_ notice: String?) -> Bool {
TencentCloudChatPushPlugin.shared.tryNotifyDartOnNotificationClickEvent(notice)
return true
}
}

步骤2:注册推送服务

registerPush 用于向 TIMPush 注册当前设备的推送 token。注册成功后,TIMPush 会为当前设备建立一个推送目标标识 registrationID;服务端、控制台接入测试和排查工具可以使用该标识向这台设备下发离线推送。若 App 同时接入 IM 并完成登录,也可以使用 userID 向该用户已建立推送关系的设备下发离线推送。
appKey 的取值会影响注册方式和可用的推送标识:
appKey = Push Key:注册 TIMPush 独立推送能力。Push Key 客户端密钥。
appKey = null:复用 IM 登录态注册推送,必须在 IM login 成功后调用。
请先根据业务场景确认调用顺序。注册时机、参数含义和不同接入场景的说明,也可参考 Android 注册推送iOS 注册推送
注意:
如果用户退出 IM SDK,同时集成了 IM SDK + TIMPush 的场景下已建立的 userIDregistrationID 推送关系都会失效,需要重新完成对应注册。
Chat 应用的密钥仅用于 IM 登录,不能作为 registerPushappKey
请注意,不要在 Flutter 程序入口的 main 方法中调用。建议在用户同意隐私政策后,并在业务侧合适时机调用。
App 冷启动注册 TIMPush(appKey 传 Push Key)
IM 登录后注册推送(appKey 传 null)
Future<void> registerTIMPush() async {
final push = TencentCloudChatPush();

final registerRes = await push.registerPush(
// TODO: 替换为您的 SDKAppID。
sdkAppId: 0,
// TODO: 替换为 Push 客户端密钥。
appKey: '<#YOUR_PUSH_APP_KEY#>',
// iOS:替换为在腾讯云控制台生成的证书 ID;Android 不用传。
apnsCertificateID: 0,
// iOS 可选:如需统计推送触达,请替换为 Apple Developer Center 或 Xcode 中配置的 App Group ID;Android 不用传。
// applicationGroupID: 'group.<#YOUR_APP_GROUP_ID#>',
// 当前 Flutter API 仍要求传入该参数,但该回调待废弃。
// 请不要在这里处理通知点击,统一使用 addPushListener。
onNotificationClicked:
({required String ext, String? userID, String? groupID}) {},
);

if (registerRes.code != 0) {
debugPrint(
'registerPush failed: code=${registerRes.code}, '
'msg=${registerRes.errorMessage}, deviceToken=${registerRes.data}',
);
return;
}

final ridRes = await push.getRegistrationID();
debugPrint(
'registerPush success, registrationID=${ridRes.data}, '
'code=${ridRes.code}, msg=${ridRes.errorMessage}',
);
}
Future<void> loginIMAndRegisterPush() async {
final int sdkAppId = 0; // TODO: 替换为您的 SDKAppID。
final String userID = '<#YOUR_USER_ID#>';
final String userSig = '<#YOUR_USER_SIG#>';

final initRes = await TencentImSDKPlugin.v2TIMManager.initSDK(
sdkAppID: sdkAppId,
);
if (initRes.code != 0) {
debugPrint('initSDK failed: code=${initRes.code}, desc=${initRes.desc}');
return;
}

final loginRes = await TencentImSDKPlugin.v2TIMManager.login(
userID: userID,
userSig: userSig,
);
if (loginRes.code != 0) {
debugPrint('login failed: code=${loginRes.code}, desc=${loginRes.desc}');
return;
}

final push = TencentCloudChatPush();
final registerRes = await push.registerPush(
sdkAppId: sdkAppId,
// iOS:替换为在腾讯云控制台生成的证书 ID;Android 不用传。
apnsCertificateID: 0,
// iOS 可选:如需统计推送触达,请替换为 Apple Developer Center 或 Xcode 中配置的 App Group ID;Android 不用传。
// applicationGroupID: 'group.<#YOUR_APP_GROUP_ID#>',
// 当前 Flutter API 仍要求传入该参数,但该回调待废弃。
// 请不要在这里处理通知点击,后续章节会介绍推荐的监听方式。
onNotificationClicked:
({required String ext, String? userID, String? groupID}) {},
);

if (registerRes.code != 0) {
debugPrint(
'registerPush failed: code=${registerRes.code}, '
'msg=${registerRes.errorMessage}, deviceToken=${registerRes.data}',
);
return;
}

final ridRes = await push.getRegistrationID();
debugPrint(
'registerPush after login success, registrationID=${ridRes.data}, '
'code=${ridRes.code}, msg=${ridRes.errorMessage}',
);
}
警告:
如果您的业务仅使用即时通信 IM 聊天能力,请勿在 IM 登录前先调用 registerPush。否则 SDK 可能会按独立推送场景注册 Push 类型账号,并产生对应的 Push DAU。Push DAU 超出套餐额度后,可能会产生额外费用。

步骤3:配置消息触达统计(可选)

触达统计主要涉及厂商控制台、回执地址、APNs Notification Service Extension、App Group 等平台专属配置。按平台完成:
Android
iOS
请按 Android 厂商通道集成 中对应厂商 Tab 的触达统计说明完成配置。Flutter 侧无额外 Dart 代码。
请按 iOS 配置消息触达统计 完成 Notification Service Extension、mutable-content 与 App Group 等配置。
Flutter 额外确认两点:
1. 调用 registerPush 时传入 applicationGroupID
2. ios/Runner/AppDelegate.swift 中已实现 applicationGroupID()

步骤4:测试推送链路

完成上述集成步骤后,需要通过发送测试消息验证链路是否打通。
运行 App 后,过滤 TIMPush 关键字查看注册日志。注册成功后,调用 getRegistrationID() 获取当前设备推送标识。控制台或服务端发送测试消息时,可使用该值定位设备。
发送消息前请确认:
1. App 已获得系统通知权限(含横幅、锁屏、声音等开关)。
2. App 已置于后台或杀掉进程(前台时离线推送可能不触发)。
发送测试消息可以采用下面几种方法:
控制台发送
REST API 发送
SDK API 发送
仅集成 TIMPush 的用户,建议优先使用腾讯云控制台接入测试能力验证离线推送。
操作路径:腾讯云控制台 > 推送服务 Push > 接入测试。在接入测试页面,可以指定 registrationIDuserID 发送离线推送测试。
如果需要通过服务端发送推送,可参考 全员/标签推送
如果您的项目已接入 IM SDK,可通过 SDK API 发送一条带离线推送参数的消息进行验证。Flutter 侧示例如下:
Future<void> sendTestPushMessage({
required String targetUserID,
}) async {
final createRes = await TencentImSDKPlugin
.v2TIMManager.v2TIMMessageManager
.createTextMessage(text: 'Hello TIMPush');

final message = createRes.data?.messageInfo;
if (createRes.code != 0 || message == null) {
debugPrint('createTextMessage failed: code=${createRes.code}');
return;
}

final sendRes = await TencentImSDKPlugin
.v2TIMManager.v2TIMMessageManager
.sendMessage(
message: message,
receiver: targetUserID,
groupID: '',
priority: MessagePriorityEnum.V2TIM_PRIORITY_NORMAL,
onlineUserOnly: false,
offlinePushInfo: OfflinePushInfo(
title: '推送标题',
desc: '推送内容',
ext: '{"action":"open_chat","conversationID":"c2c_$targetUserID"}',
),
);

debugPrint(
'sendMessage result: code=${sendRes.code}, desc=${sendRes.desc}, '
'msgID=${sendRes.data?.msgID}',
);
}
验证:App 置于后台后发送测试消息,设备能收到离线推送通知。如果手机通知栏开启权限,通知栏会弹出离线推送消息弹框。

步骤5:处理通知点击跳转

通知点击跳转完整流程请参考 Android 处理通知点击跳转iOS 处理通知点击跳转 文档。Flutter 侧的配置控制台点击动作跟原生平台一致,但要关注另外两个步骤差异。

发送推送时携带 ext

如果您的项目已接入 IM SDK,可在发送消息时通过 OfflinePushInfo.ext 携带跳转参数。示例代码如下:
Future<void> sendMessageWithPushExt({
required String targetUserID,
}) async {
final createRes = await TencentImSDKPlugin
.v2TIMManager.v2TIMMessageManager
.createTextMessage(text: 'Hello TIMPush');

final message = createRes.data?.messageInfo;
if (createRes.code != 0 || message == null) {
debugPrint('createTextMessage failed: code=${createRes.code}');
return;
}

final sendRes = await TencentImSDKPlugin
.v2TIMManager.v2TIMMessageManager
.sendMessage(
message: message,
receiver: targetUserID,
groupID: '',
priority: MessagePriorityEnum.V2TIM_PRIORITY_NORMAL,
onlineUserOnly: false,
offlinePushInfo: OfflinePushInfo(
title: '推送标题',
desc: '推送内容',
ext: '{"conversationID":"$targetUserID","conversationType":1}',
),
);

debugPrint(
'sendMessage result: code=${sendRes.code}, desc=${sendRes.desc}, '
'msgID=${sendRes.data?.msgID}',
);
}

客户端注册监听并解析 ext

Flutter 客户端推荐使用 TencentCloudChatPush().addPushListener 监听通知点击事件,并在 onNotificationClicked 中解析 ext。示例代码如下:
final TIMPushListener timPushListener = TIMPushListener(
onRecvPushMessage: (TimPushMessage msg) {
debugPrint(
'onRecvPushMessage: title=${msg.title}, desc=${msg.desc}, '
'ext=${msg.ext}, msgID=${msg.messageID}',
);
},
onRevokePushMessage: (String msgID) {
debugPrint('onRevokePushMessage: msgID=$msgID');
},
onNotificationClicked: (String ext) {
debugPrint('onNotificationClicked: ext=$ext');

// 1. 解析 ext。JSON 结构由业务自定义,需与发送端约定一致。
Map<String, dynamic>? extJson;
try {
extJson = jsonDecode(ext) as Map<String, dynamic>;
} catch (e) {
debugPrint('parse ext failed: $e');
return;
}

final String? conversationID = extJson['conversationID'] as String?;
final int? conversationType = extJson['conversationType'] as int?;

if (conversationID == null || conversationType == null) {
return;
}


// 2. TODO: 根据业务字段跳转到目标页面。
// 若使用了 Chat / TUIKit,建议在用户登录成功后再跳转;
// 冷启动场景可先把参数缓存起来,登录回调中再跳转。
},
);

Future<void> addTIMPushListener() async {
await TencentCloudChatPush().addPushListener(listener: timPushListener);
}

Future<void> removeTIMPushListener() async {
await TencentCloudChatPush().removePushListener(listener: timPushListener);
}
注意:
TencentCloudChatPush().registerPush 当前仍要求传入 onNotificationClicked 参数,但该参数待废弃。新接入业务请不要在 registerPushonNotificationClicked 中处理跳转,统一使用 addPushListener
ext 是发送方写入的业务透传字段,建议使用 JSON 字符串,例如 {"conversationID":"user_A","conversationType":1}
若 App 冷启动后需要立即处理点击事件,建议尽早注册 listener,例如在登录流程完成后、业务首页初始化前完成注册。
发送离线推送时如需设置 Android 厂商消息分类或通知渠道 ID,可通过 Flutter Chat SDK 的 OfflinePushInfo 设置;具体字段含义与厂商规则见 Android 厂商通道集成

接入排查

如果接入完成收不到推送,请使用 排查工具 查看具体原因。排查后依然异常,请 联系我们 提交反馈。