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

Flutter

最近更新时间:2026-07-30 15:01:08
我的收藏

前提条件

开始接入前,请先完成对应原生平台的推送前提配置:请参见 iOS 前提条件Android 前提条件

AI 集成

通过 npx 安装 @tencent-rtc/trtc-push-skill 到本地 AI IDE 中,辅助完成 TIMPush 离线推送集成。安装后,你可以直接向 AI 输入“集成 Flutter 离线推送”“帮我集成 Flutter TIMPush”等需求,AI 将根据项目类型引导你完成环境检测、厂商通道配置、凭据填写、代码接入和验证等步骤。
注意:
使用 Push Skill AI 集成不是全自动流程,依然需要开发者在厂商配置控制台、腾讯云控制台等配置 Push 相关信息。具体的配置方法请参考下文相关章节。

集成 TIMPush

如果你想手动集成,请按顺序完成下文配置。
Flutter 工程需要先引入推送插件,您可以在 pubspec.yaml 中添加依赖,也可以执行以下命令自动安装:
flutter pub add tencent_cloud_chat_push
完成 Flutter 插件集成后,还需要继续完成对应原生平台侧配置。
Android 端请参考 Android 集成 TIMPush 章节,完成各项配置;其中“集成 TIMPush 依赖”步骤与原生 Android 工程不同,请按下方 Flutter 方式处理。
android/app/build.gradleandroid/app/build.gradle.kts 按需引入目标厂商的 TIMPush 通道包。只有引入对应厂商包,才能启用该厂商的原生推送能力。VERSION 请前往 更新日志 获取并替换为实际版本号。
Groovy DSL
Kotlin DSL
dependencies {
implementation 'com.tencent.timpush:huawei:VERSION'
implementation 'com.tencent.timpush:xiaomi:VERSION'
implementation 'com.tencent.timpush:oppo:VERSION'
implementation 'com.tencent.timpush:vivo:VERSION'
implementation 'com.tencent.timpush:honor:VERSION'
implementation 'com.tencent.timpush:meizu:VERSION'
implementation 'com.tencent.timpush:fcm:VERSION'
}
dependencies {
implementation("com.tencent.timpush:huawei:VERSION")
implementation("com.tencent.timpush:xiaomi:VERSION")
implementation("com.tencent.timpush:oppo:VERSION")
implementation("com.tencent.timpush:vivo:VERSION")
implementation("com.tencent.timpush:honor:VERSION")
implementation("com.tencent.timpush:meizu: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>
iOS 端不需要执行原生 iOS 文档中“主 App target 集成”步骤,Flutter 插件会处理相关依赖。您只需要在 ios/Runner/AppDelegate.swift 中补充 TIMPush 相关配置,用于返回推送证书 ID、App Group ID,以及转发离线推送点击事件。
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
}
}

注册推送

registerPush 用于注册当前设备的推送 token。注册时机、参数含义和不同接入场景的说明,请参考 Android 注册推送iOS 注册推送 章节。
请注意,不要在 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}',
);
}

配置消息触达统计(可选)

触达统计主要涉及厂商控制台、回执地址、APNs Notification Service Extension、App Group 等平台专属配置,请参考 Android 配置消息触达统计iOS 配置消息触达统计 文档。
iOS 如需统计推送触达数据,请在 registerPush 时传入 applicationGroupID,并确认 ios/Runner/AppDelegate.swift 中已实现 applicationGroupID()

测试推送

运行 App 后,过滤 TIMPush 关键字查看注册日志。注册成功后,调用 getRegistrationID() 获取当前设备推送标识。控制台或服务端发送测试消息时,可使用该值定位设备。
测试流程请参考 Android 测试推送iOS 测试推送 文档。仅集成 TIMPush 的用户,建议优先使用腾讯云控制台接入测试能力验证离线推送。
如果您的项目已接入 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}',
);
}

处理通知点击跳转

通知点击跳转完整流程请参考 Android 处理通知点击跳转iOS 处理通知点击跳转 文档。Flutter 侧主要关注两处差异:通过 IM SDK API 发送消息时写入 ext,以及在客户端注册监听并解析 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}',
);
}
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 厂商通道策略,Flutter 侧没有额外的接入操作,请参考 Android 配置消息分类 文档,API 请参考 Flutter 消息分类 API 文档。

收不到推送排障流程

步骤1:原生侧排查

如果发送测试消息后设备没有收到推送,请先按平台文档 Android 收不到推送排障流程iOS 收不到推送排障流程 完成原生侧排查。

步骤2:Flutter 侧可按以下顺序补充检查

1. 确认 registerPush 返回 code = 0。如果返回非 0,请先根据错误码和 errorMessage 排查,不要只看 App 是否启动成功。
2. 注册成功后调用 getRegistrationID(),确认返回值非空。控制台或服务端发送测试消息时,使用的 RegistrationID / userID 应与这里返回的值一致。
3. 确认 registerPush 的调用时机正确。仅使用 Push 能力时,可在 App 完成必要初始化、用户同意隐私政策并获得通知权限后调用;Chat / TUIKit 离线推送场景下,应在 IM 登录成功后调用。
4. 确认通知点击逻辑已通过 TencentCloudChatPush().addPushListener 注册。registerPush 中的 onNotificationClicked 参数当前仅作为必填空实现保留,不建议继续在其中处理跳转。
5. 如果通过 Chat SDK 发送测试消息,确认 OfflinePushInfo 中已设置 titledesc,并按业务需要设置 ext。如需点击跳转,ext 中应包含客户端可解析的页面或会话参数。

仍无法解决

如果按上述流程仍无法定位问题,请 联系我们 提交反馈。