瀏覽代碼

极光推送插件封装。

PC\19500 2 周之前
父節點
當前提交
ae4b5ffed6

+ 7 - 0
lib/core/constants/app_enum.dart

@@ -23,4 +23,11 @@ enum PermissionType {
   gallery,
   gallery,
   microphone,
   microphone,
   bluetooth,
   bluetooth,
+}
+
+/// 推送事件类型
+enum PushEventType {
+  receiveNotification, // 收到通知
+  openNotification, // 点击通知
+  receiveMessage, // 自定义消息
 }
 }

+ 74 - 0
lib/push/jpush_service.dart

@@ -0,0 +1,74 @@
+import 'dart:async';
+import 'package:jpush_flutter/jpush_flutter.dart';
+import 'package:sino_med_cloud/push/push_message.dart';
+import 'package:sino_med_cloud/push/push_service.dart';
+
+import '../core/constants/app_enum.dart';
+
+class JPushService implements PushService {
+  final _jpush = JPush.newJPush();
+  final _receiveController = StreamController<PushMessage>.broadcast();
+  final _openController = StreamController<PushMessage>.broadcast();
+  final _messageController = StreamController<PushMessage>.broadcast();
+
+  @override
+  Future<void> init() async {
+    // 初始化 JPush
+    _jpush.setup(
+      appKey: '', // 从配置中获取
+      channel: '', // 从配置中获取
+      production: false, // 根据环境设置
+    );
+
+    // 添加事件处理器
+    _jpush.addEventHandler(
+      onReceiveNotification: (Map<String, dynamic> message) async {
+        _receiveController.add(PushMessage.fromJson(message));
+      },
+      onOpenNotification: (Map<String, dynamic> message) async {
+        _openController.add(PushMessage.fromJson(message));
+      },
+      onReceiveMessage: (Map<String, dynamic> message) async {
+        _messageController.add(PushMessage.fromJson(message));
+      },
+    );
+  }
+
+  @override
+  Stream<PushMessage> onMessage(PushEventType type) {
+    switch (type) {
+      case PushEventType.receiveNotification:
+        return _receiveController.stream;
+      case PushEventType.openNotification:
+        return _openController.stream;
+      case PushEventType.receiveMessage:
+        return _messageController.stream;
+    }
+  }
+
+  @override
+  Future<void> setAlias(String alias) async {
+    await _jpush.setAlias(alias);
+  }
+
+  @override
+  Future<void> deleteAlias() async {
+    await _jpush.deleteAlias();
+  }
+
+  @override
+  Future<void> addTags(List<String> tags) async {
+    await _jpush.addTags(tags);
+  }
+
+  @override
+  Future<void> cleanTags() async {
+    await _jpush.cleanTags();
+  }
+
+  void dispose() {
+    _receiveController.close();
+    _openController.close();
+    _messageController.close();
+  }
+}

+ 33 - 0
lib/push/push_manager.dart

@@ -0,0 +1,33 @@
+import 'package:sino_med_cloud/core/constants/app_enum.dart';
+import 'package:sino_med_cloud/push/push_message.dart';
+import 'package:sino_med_cloud/push/push_service.dart';
+
+import 'jpush_service.dart';
+
+/// 对外统一入口(业务只用这个)
+class PushManager {
+  PushManager._internal();
+
+  static final PushManager instance = PushManager._internal();
+
+  late final PushService _service;
+
+  void init() {
+    _service = JPushService();
+    _service.init();
+  }
+
+  Stream<PushMessage> onReceive() => _service.onMessage(PushEventType.receiveNotification);
+
+  Stream<PushMessage> onOpen() => _service.onMessage(PushEventType.openNotification);
+
+  Stream<PushMessage> onMessage() => _service.onMessage(PushEventType.receiveMessage);
+
+  Future<void> bindUser(String userId) {
+    return _service.setAlias(userId);
+  }
+
+  Future<void> unbindUser() {
+    return _service.deleteAlias();
+  }
+}

+ 38 - 0
lib/push/push_message.dart

@@ -0,0 +1,38 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'push_message.g.dart';
+
+/// 推送消息模型
+@JsonSerializable(createFactory: false)
+class PushMessage {
+  final String? title;
+  
+  final String? content;
+  
+  @JsonKey(defaultValue: {})
+  final Map<String, dynamic> extras;
+
+  PushMessage({
+    this.title,
+    this.content,
+    required this.extras,
+  });
+
+  /// 从 JSON 创建 PushMessage
+  /// 支持 'alert' 或 'content' 字段作为内容
+  factory PushMessage.fromJson(Map<String, dynamic> json) {
+    // 处理 content 字段:优先使用 'alert',如果没有则使用 'content'
+    final content = json['alert'] ?? json['content'];
+    
+    return PushMessage(
+      title: json['title'] as String?,
+      content: content as String?,
+      extras: json['extras'] != null
+          ? Map<String, dynamic>.from(json['extras'] as Map)
+          : <String, dynamic>{},
+    );
+  }
+
+  /// 转换为 JSON
+  Map<String, dynamic> toJson() => _$PushMessageToJson(this);
+}

+ 14 - 0
lib/push/push_message.g.dart

@@ -0,0 +1,14 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'push_message.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+Map<String, dynamic> _$PushMessageToJson(PushMessage instance) =>
+    <String, dynamic>{
+      'title': instance.title,
+      'content': instance.content,
+      'extras': instance.extras,
+    };

+ 72 - 0
lib/push/push_service.dart

@@ -0,0 +1,72 @@
+import 'package:sino_med_cloud/push/push_message.dart';
+
+import '../core/constants/app_enum.dart';
+
+/// 推送服务接口
+/// 
+/// 定义了推送服务的核心功能,包括初始化、别名管理、标签管理和消息监听等
+abstract class PushService {
+  /// 初始化推送服务
+  /// 
+  /// 在应用启动时调用,用于初始化推送 SDK 和注册事件处理器
+  /// 
+  /// 抛出异常:
+  /// - 如果初始化失败,会抛出相应的异常
+  Future<void> init();
+
+  /// 设置用户别名
+  /// 
+  /// 别名是用于标识用户的唯一标识符,可以用来向特定用户推送消息
+  /// 
+  /// 参数:
+  /// - [alias] 用户别名,不能为空
+  /// 
+  /// 抛出异常:
+  /// - 如果设置失败,会抛出相应的异常
+  Future<void> setAlias(String alias);
+
+  /// 删除用户别名
+  /// 
+  /// 删除当前用户已设置的别名
+  /// 
+  /// 抛出异常:
+  /// - 如果删除失败,会抛出相应的异常
+  Future<void> deleteAlias();
+
+  /// 添加标签
+  /// 
+  /// 在原有标签的基础上添加新的标签,用于对用户进行分组推送
+  /// 
+  /// 参数:
+  /// - [tags] 要添加的标签列表,不能为空
+  /// 
+  /// 抛出异常:
+  /// - 如果添加失败,会抛出相应的异常
+  Future<void> addTags(List<String> tags);
+
+  /// 清空所有标签
+  /// 
+  /// 删除当前用户的所有标签
+  /// 
+  /// 抛出异常:
+  /// - 如果清空失败,会抛出相应的异常
+  Future<void> cleanTags();
+
+  /// 监听推送消息
+  /// 
+  /// 根据指定的消息类型返回对应的消息流,用于接收推送消息
+  /// 
+  /// 参数:
+  /// - [type] 消息类型,可以是:
+  ///   - [PushEventType.receiveNotification] 接收到的通知
+  ///   - [PushEventType.openNotification] 点击打开的通知
+  ///   - [PushEventType.receiveMessage] 接收到的自定义消息
+  /// 
+  /// 返回:
+  /// - 返回对应类型的推送消息流
+  /// 
+  /// 抛出异常:
+  /// - 如果类型无效,会抛出异常
+  Stream<PushMessage> onMessage(PushEventType type);
+}
+