flutter/lib/IM/push_service.dart
2025-09-13 17:01:01 +08:00

211 lines
6.7 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:convert';
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:get/get.dart';
import 'package:logger/logger.dart';
import 'package:loopin/IM/im_service.dart';
import 'package:loopin/models/conversation_type.dart';
import 'package:loopin/utils/storage.dart';
import 'package:tencent_cloud_chat_push/common/tim_push_listener.dart';
import 'package:tencent_cloud_chat_push/common/tim_push_message.dart';
import 'package:tencent_cloud_chat_push/tencent_cloud_chat_push.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
final logger = Logger();
class PushService {
static late TIMPushListener _timPushListener;
Future<void> _registerPushInIsolate(Map<String, dynamic> args) async {
final sdkAppId = args['sdkAppId'] as int;
final appKey = args['appKey'] as String;
final apnsCertificateID = args['apnsCertificateID'] as int;
try {
await TencentCloudChatPush().registerPush(
sdkAppId: sdkAppId,
appKey: appKey,
apnsCertificateID: apnsCertificateID,
onNotificationClicked: _onNotificationClicked,
);
} catch (e) {
logger.e('注册推送失败: $e');
}
}
/// 初始化推送服务
Future<void> initPush({
required int sdkAppId,
required String appKey, // 客户端密钥
}) async {
int apnsCertificateID;
final devices = await _getDeviceBrand();
apnsCertificateID = _getApnsCertificateIDForBrand(devices);
if (apnsCertificateID == 0) {
logger.w('手机厂商:$devices, 未配置证书');
}
// 注册推送(初始化)
// if (Platform.isAndroid) {
// await compute(_registerPushInIsolate, {
// 'sdkAppId': sdkAppId,
// 'appKey': appKey,
// 'apnsCertificateID': apnsCertificateID,
// });
// } else {
await TencentCloudChatPush().registerPush(
onNotificationClicked: _onNotificationClicked,
sdkAppId: sdkAppId,
appKey: appKey,
apnsCertificateID: apnsCertificateID,
);
// }
// 关闭 App 在前台时弹出通知栏
await TencentCloudChatPush().disablePostNotificationInForeground(disable: true);
///处理安卓端异常问题;
if (Platform.isAndroid) {
await TencentImSDKPlugin.v2TIMManager.login(userID: Storage.read('userId'), userSig: Storage.read('userSig'));
}
logger.i('推送服务已注册,手机:$devices,证书ID:$apnsCertificateID');
// 添加在线时监听器
_addPushListener();
}
/// 注销推送(退出登录时调用)
static Future<void> unInitPush() async {
try {
await TencentCloudChatPush().unRegisterPush();
_removePushListener();
} catch (e) {
logger.i("注销推送失败: $e");
}
}
/// 添加监听器
static void _addPushListener() {
_timPushListener = TIMPushListener(
onRecvPushMessage: (TimPushMessage message) {
logger.i("[推送] 收到消息: ${message.toLogString()}");
},
onRevokePushMessage: (String messageId) {
logger.i("[推送] 消息被撤回: $messageId");
},
onNotificationClicked: (String ext) {
logger.i("[推送] 点击横幅 ext: $ext");
_handleNotificationClick(ext);
},
);
TencentCloudChatPush().addPushListener(listener: _timPushListener);
logger.i('推送服务在线监听器已注册');
}
/// 移除监听器
static void _removePushListener() {
TencentCloudChatPush().removePushListener(listener: _timPushListener);
}
/// 横幅点击事件处理
static void _onNotificationClicked({
required String ext,
String? userID,
String? groupID,
}) {
logger.i("[点击通知回调] ext: $ext, userID: $userID, groupID: $groupID");
_handleNotificationClick(ext, userID: userID, groupID: groupID);
}
/// 统一处理跳转逻辑
static void _handleNotificationClick(String ext, {String? userID, String? groupID}) async {
try {
// ext={id:对应业务ID,type:'newFocus',userID:发送人的idgroupID群ID}
// final ext = jsonEncode({
// "userID": "123456",
// "groupID": "654321",
// });
final data = jsonDecode(ext);
logger.i(data);
final type = data['type'];
final router = conversationTypeFromString(type);
logger.w(router);
if (router == null || router != '') {
// 聊天
if (data['userID'] != null) {
logger.w('有userID');
// 单聊,获取会话
final covRes = await ImService.instance.getConversation(conversationID: 'c2c_${data['userID']}');
final V2TimConversation conversation = covRes.data;
logger.w(conversation.toJson());
if (conversation.conversationGroupList?.contains(ConversationType.noFriend.name) ?? false) {
// nofriend会话,是否第一次聊天
conversation.showName = conversation.showName ?? data['title'];
Get.toNamed('/chatNoFriend', arguments: conversation);
} else {
// 去正常的会话
Get.toNamed('/chat', arguments: conversation);
}
} else {
logger.w('没有userID');
// 群聊消息
final groupRes = await ImService.instance.getConversation(conversationID: 'group_${data['groupID']}');
if (groupRes.success) {
final V2TimConversation groupConv = groupRes.data;
Get.toNamed('/chatGroup', arguments: groupConv);
}
}
} else {
// 通知类相关(这里的ID只在特定业务场景才有比如用户发起退款要推送给商家这里的id对应的就是订单id)
Get.toNamed('/$router', arguments: data['id'] ?? '');
}
} catch (e) {
logger.i("[推送点击] ext 解析失败: $e");
}
}
/// 获取手机品牌
static Future<String> _getDeviceBrand() async {
final deviceInfo = DeviceInfoPlugin();
try {
if (Platform.isAndroid) {
final androidInfo = await deviceInfo.androidInfo;
return androidInfo.brand.toLowerCase();
} else if (Platform.isIOS) {
return 'apple';
} else {
return 'unknown';
}
} catch (e, stack) {
logger.w("获取设备品牌失败: $e\n$stack");
return 'unknown';
}
}
/// 获取对应厂商的证书ID
static int _getApnsCertificateIDForBrand(String brand) {
switch (brand) {
case 'xiaomi':
case 'redmi':
return 41169;
case 'oppo':
return 41170;
case 'vivo':
return 41177;
case 'meizu':
return 41176;
case 'apple':
return 45356;
case 'huawei':
return 41171;
case 'honor':
return 41178;
default:
return 0;
}
}
}