flutter/lib/IM/push_service.dart

211 lines
6.7 KiB
Dart
Raw Normal View History

2025-08-21 10:50:38 +08:00
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 {
2025-09-03 11:56:14 +08:00
// ext={id:对应业务ID,type:'newFocus',userID:发送人的idgroupID群ID}
2025-08-21 10:50:38 +08:00
// 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 != '') {
// 聊天
2025-09-13 17:01:01 +08:00
if (data['userID'] != null) {
2025-08-21 10:50:38 +08:00
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']}');
2025-09-13 17:01:01 +08:00
if (groupRes.success) {
final V2TimConversation groupConv = groupRes.data;
Get.toNamed('/chatGroup', arguments: groupConv);
}
2025-08-21 10:50:38 +08:00
}
} else {
2025-09-13 17:01:01 +08:00
// 通知类相关(这里的ID只在特定业务场景才有比如用户发起退款要推送给商家这里的id对应的就是订单id)
2025-08-21 10:50:38 +08:00
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;
}
}
}