# 极光推送集成说明 ## 目录结构 ``` capability-push/src/ └── main/ ├── AndroidManifest.xml # Android 清单文件(权限声明) └── java/ └── com/narutohuo/xindazhou/push/ ├── api/ # API 接口层 │ └── PushService.kt # 推送服务接口定义 ├── factory/ # 工厂类层 │ └── PushServiceFactory.kt # 服务工厂(统一入口,单例获取) ├── impl/ # 实现层 │ └── PushServiceImpl.kt # 推送服务具体实现(封装极光推送SDK) ├── receiver/ # 接收器层 │ └── JPushReceiver.kt # 推送消息接收器(完全封装在模块内部) ├── mapping/ # 页面映射层 │ └── ActivityMapping.kt # 静态页面映射配置(支持应用未启动时跳转) └── model/ # 数据模型层 ├── PushConfig.kt # 推送服务配置模型 └── PushResponse.kt # 推送相关的数据模型 ├── PushMessage # 推送消息模型 └── PushResponse # 推送响应模型 ``` ## 功能说明 ### 1. api/ 层 - 接口定义 - **职责**:定义推送服务的公共接口,业务层只依赖接口 - **内容**:`PushService` 接口,包含初始化、别名/标签设置、消息监听、注册/注销等方法 ### 2. factory/ 层 - 工厂类 - **职责**:提供统一的服务实例获取和初始化方式 - **内容**:`PushServiceFactory` 单例工厂 - **作用**:隐藏实现细节,统一入口,便于替换实现 ### 3. impl/ 层 - 具体实现 - **职责**:实现 `PushService` 接口的具体逻辑 - **内容**:`PushServiceImpl` 单例实现类 - **功能**:封装极光推送 SDK 调用,处理推送消息接收,错误处理和日志记录 ### 3.1 receiver/ 层 - 消息接收器 - **职责**:封装推送消息接收逻辑 - **内容**:`JPushReceiver` BroadcastReceiver - **功能**: - 自动接收极光推送的消息(自定义消息、通知消息、通知点击) - 自动解析消息内容 - **完全封装**:在模块的 `AndroidManifest.xml` 中自动注册,业务层无需处理 - **自动跳转**:优先使用静态配置(`ActivityMapping`)自动处理通知点击跳转,支持应用未启动场景 ### 3.2 mapping/ 层 - 页面映射配置 - **职责**:提供静态页面映射配置,支持应用未启动时的跳转 - **内容**:`ActivityMapping` 静态配置类 - **功能**: - **静态配置**:页面映射关系在编译时确定,不依赖运行时初始化 - **应用未启动支持**:即使应用从未启动过,点击通知也能正常跳转 - **向后兼容**:支持运行时动态配置(通过 `pageMappings` 参数) - **优先级**:静态配置优先,运行时配置作为补充 ### 4. model/ 层 - 数据模型 - **职责**:定义推送相关的数据模型 - **内容**: - `PushConfig` - 推送服务配置模型 - `PushMessage` - 推送消息模型(标题、内容、扩展数据等) - `PushResponse` - 推送响应模型(成功/失败、错误信息等) ## 架构设计 - **接口隔离**:业务层只依赖接口,不依赖实现 - **ARouter 依赖注入**:通过 ARouter 实现模块间解耦,base-core 定义接口,能力层实现接口 - **工厂模式**:统一入口,隐藏创建逻辑(内部使用 ARouter 获取服务) - **单例模式**:全局共享一个服务实例 - **分层架构**:base-core (接口) → capability-push (实现) → ARouter (注册) → Factory (获取) - **完全封装**:跳转逻辑封装在模块内部,外部只需配置页面映射规则 - **静态配置优先**:使用静态配置(`ActivityMapping`)确保应用未启动时也能正常跳转 ### ARouter 架构说明 - **base-core** 模块定义 `IPushService` 接口(位于 `com.narutohuo.xindazhou.core.push`) - **capability-push** 模块实现 `IPushService` 接口,并通过 `@Route(path = "/push/service")` 注册到 ARouter - **Factory** 内部使用 `ARouter.getInstance().navigation(IPushService::class.java)` 获取服务实例 - **业务层** 通过 Factory 获取服务,无需直接依赖实现模块 ## 已完成的工作 ✅ **SDK 依赖已添加** - `jpush-5.9.0.aar` - 极光推送SDK(本地 AAR) - `jcore-5.2.0.aar` - 极光推送核心库(本地 AAR) - `cn.jiguang.sdk.plugin:xiaomi:5.9.0` - 小米通道 - `cn.jiguang.sdk.plugin:huawei:5.9.0` - 华为通道 - `cn.jiguang.sdk.plugin:oppo:5.9.0` - OPPO通道 - `cn.jiguang.sdk.plugin:vivo:5.9.0` - vivo通道 - `cn.jiguang.sdk.plugin:meizu:5.9.0` - 魅族通道 ✅ **代码实现已完成** - `PushServiceImpl` 已实现极光推送 SDK 调用,并实现 `IPushService` 接口 - `PushServiceImpl` 已通过 ARouter 注册(`@Route(path = "/push/service")`) - `PushServiceFactory` 已创建,内部使用 ARouter 获取服务 - `IPushService` 接口已在 `base-core` 模块定义 - `PushConfig` 配置模型已创建 - `JPushReceiver` 消息接收器已封装 - **`ActivityMapping` 静态页面映射已实现**:支持应用未启动时的跳转 - **跳转逻辑已封装**:自动跳转功能已实现,优先使用静态配置 - **ARouter 集成完成**:模块间解耦,通过 ARouter 进行依赖注入 ✅ **配置已完成** - 所有配置都在 `capability-push` 模块中管理 - `AndroidManifest.xml` 已在 `capability-push/src/main/AndroidManifest.xml` 中配置 - `strings.xml` 已在 `capability-push/src/main/res/values/strings.xml` 中配置 ## 需要您配置的内容 ### 1. 在极光推送官网注册应用 1. 访问 [极光推送官网](https://www.jiguang.cn/) 2. 注册账号并创建应用 3. 获取 **AppKey** 和 **AppSecret** ### 2. 配置厂商通道参数(可选,但推荐) 在各厂商开放平台申请参数,并在 `capability-push/src/main/res/values/strings.xml` 中配置。 **详细步骤请参考**:[厂商通道接入说明.md](./厂商通道接入说明.md) ### 3. 配置资源文件 **所有配置都在 `capability-push/src/main/res/values/strings.xml` 中管理** 编辑 `capability-push/src/main/res/values/strings.xml`: ```xml 您的极光推送 AppKey developer-default ``` ### 3.5 配置静态页面映射(推荐,支持应用未启动场景) **方式1:使用静态配置(推荐)** 在 `capability-push/src/main/java/com/narutohuo/xindazhou/push/mapping/ActivityMapping.kt` 中配置: ```kotlin package com.narutohuo.xindazhou.push.mapping import com.narutohuo.xindazhou.core.log.ILog /** * 静态页面映射配置 * * 优势: * - 支持应用未启动时的跳转 * - 不依赖 Application.onCreate() 的执行顺序 * - 更可靠,避免初始化时序问题 */ object ActivityMapping { /** * 静态页面映射配置 * 页面名称 -> Activity 完整类名 */ private val pageToActivityMap = mapOf( "detail" to "com.narutohuo.xindazhou.ui.DetailActivity", "home" to "com.narutohuo.xindazhou.ui.MainActivity", "order" to "com.narutohuo.xindazhou.ui.OrderActivity", // 添加更多页面映射... ) /** * 根据页面名称获取 Activity Class * * @param page 页面名称(从推送的 extras["page"] 获取) * @return Activity Class,如果未找到返回 null */ fun getActivityClass(page: String): Class<*>? { val className = pageToActivityMap[page] ?: return null return try { Class.forName(className) } catch (e: ClassNotFoundException) { ILog.e("ActivityMapping", "找不到 Activity: $className", e) null } } } ``` **方式2:使用运行时配置(向后兼容)** 在 `Application.onCreate()` 中通过 `pageMappings` 参数配置(见下方"4. 在 Application 中初始化")。 **推荐使用方式1(静态配置)**,因为: - ✅ 支持应用未启动时的跳转 - ✅ 不依赖初始化顺序 - ✅ 更可靠 ### 4. 在 Application 中初始化(统一入口) 在您的 `XinDaZhouApplication` 类中初始化推送服务: ```kotlin // app/src/main/java/com/narutohuo/xindazhou/XinDaZhouApplication.kt package com.narutohuo.xindazhou import android.app.Application import com.narutohuo.xindazhou.push.factory.PushServiceFactory class XinDaZhouApplication : Application() { override fun onCreate() { super.onCreate() // ========== 初始化推送服务(从资源文件读取配置)========== // 方式1:只使用静态配置(推荐,已在 ActivityMapping 中配置) PushServiceFactory.init( context = this ) // 方式2:同时配置运行时映射(可选,作为静态配置的补充) PushServiceFactory.init( context = this, // 页面映射规则(用于自动跳转,作为静态配置的补充) // 注意:如果已在 ActivityMapping 中配置,这里可以不传 pageMappings = mapOf( "detail" to DetailActivity::class.java, // 详情页 "home" to MainActivity::class.java, // 首页 ) ) } } ``` **配置说明**: - ✅ **静态配置优先**:`ActivityMapping` 中的配置优先级最高,即使应用未启动也能使用 - ✅ **运行时配置补充**:`pageMappings` 参数作为补充,用于动态配置或覆盖静态配置 - ✅ **向后兼容**:如果只使用 `pageMappings`,也能正常工作(但应用未启动时可能失败) **优势**: - ✅ **最简单**:只需一行代码,配置都在资源文件和静态配置类中 - ✅ **统一入口**:通过 `PushServiceFactory.init()` 统一初始化 - ✅ **跳转逻辑封装**:跳转逻辑完全封装在模块内部,外部只需要配置页面映射规则 - ✅ **应用未启动支持**:静态配置确保即使应用从未启动过,点击通知也能正常跳转 - ✅ **容错处理**:初始化失败不会影响应用启动,只记录日志 - ✅ **自动识别设备**:极光推送 SDK 自动识别设备类型并选择对应厂商通道 - ✅ 业务层不直接依赖极光推送API - ✅ 如果更换SDK,只需修改实现层,业务层无需改动 ## 核心功能说明 ### 1. 通知展示(系统通知栏) ✅ **不需要我们处理,系统自动显示** - 极光推送 SDK 会自动在系统通知栏显示通知 - 系统会自动处理通知的展示、图标、声音等 ### 2. 通知点击跳转(已封装) ✅ **跳转逻辑已完全封装在模块内部!** **工作原理**: 1. 用户点击通知栏通知 2. 模块内部自动解析 `extras["page"]` 3. **优先使用静态配置**:从 `ActivityMapping` 获取 Activity Class(支持应用未启动场景) 4. **备选方案**:如果静态配置未找到,使用运行时配置的 `pageMappings` 5. 根据映射关系自动跳转到对应 Activity 6. 所有 `extras` 参数自动传递给目标 Activity **优势**: - ✅ **应用未启动支持**:即使应用从未启动过,点击通知也能正常跳转 - ✅ **不依赖初始化顺序**:静态配置在类加载时即可用,不依赖 `Application.onCreate()` - ✅ **更可靠**:避免因初始化时序问题导致的跳转失败 - ✅ **向后兼容**:仍支持运行时动态配置 `pageMappings` **服务器推送格式**: ```json { "notification": { "title": "新订单", "alert": "您有一个新订单待处理" }, "extras": { "page": "detail", // 必须匹配 ActivityMapping 或 pageMappings 中的 key "id": "12345" // 会自动传递给目标 Activity } } ``` ### 3. 厂商通道(自动识别) ✅ **极光推送 SDK 会自动识别设备类型,无需手动处理!** - ✅ **自动识别**:SDK 会自动检测设备品牌(小米、华为、OPPO、vivo、魅族等) - ✅ **自动选择通道**:根据设备类型自动选择对应的厂商通道 - ✅ **自动降级**:如果设备不是厂商手机,自动降级到极光通道 - ✅ **无需手动处理**:不需要判断手机品牌,不需要手动选择通道 ## 使用示例 ### 初始化(在 Application 中) ```kotlin // 方式1:只使用静态配置(推荐,支持应用未启动场景) // 页面映射已在 ActivityMapping 中配置 PushServiceFactory.init( context = this ) // 方式2:同时配置运行时映射(可选,作为静态配置的补充) PushServiceFactory.init( context = this, messageListener = { message -> // 处理自定义消息(透传消息) Timber.d("收到推送: ${message.title} - ${message.content}") }, notificationClickListener = { message -> // 处理通知点击事件(可选,用于统计、埋点等) Timber.d("用户点击通知,已自动跳转") }, pageMappings = mapOf( "detail" to DetailActivity::class.java, // 注意:如果已在 ActivityMapping 中配置,这里可以不传 ) ) ``` ### 配置静态页面映射(在 ActivityMapping.kt 中) ```kotlin // capability-push/src/main/java/com/narutohuo/xindazhou/push/mapping/ActivityMapping.kt package com.narutohuo.xindazhou.push.mapping import com.narutohuo.xindazhou.core.log.ILog object ActivityMapping { private val pageToActivityMap = mapOf( "detail" to "com.narutohuo.xindazhou.ui.DetailActivity", "home" to "com.narutohuo.xindazhou.ui.MainActivity", "order" to "com.narutohuo.xindazhou.ui.OrderActivity", // 添加更多页面映射... ) fun getActivityClass(page: String): Class<*>? { val className = pageToActivityMap[page] ?: return null return try { Class.forName(className) } catch (e: ClassNotFoundException) { ILog.e("ActivityMapping", "找不到 Activity: $className", e) null } } } ``` ### 后续使用(可选,按需调用) ```kotlin val pushService = PushServiceFactory.getInstance() pushService.setAlias("user123") // 设置别名(可选) pushService.setTags(listOf("vip", "premium")) // 设置标签(可选) val registrationId = pushService.getRegistrationId() // 获取注册ID(可选) val isEnabled = pushService.isPushEnabled() // 检查推送状态(可选) ``` ## 推送消息类型说明 1. **自定义消息(透传消息)**:`messageListener` - 不会显示在系统通知栏 - 需要在应用内自己处理并显示 - 适用于需要应用内自定义显示的推送 2. **通知消息(系统通知栏)**: - **展示**:由极光推送 SDK 和系统自动处理,自动显示在通知栏 - **点击**:优先使用静态配置(`ActivityMapping`)自动跳转,支持应用未启动场景(已封装) - 适用于需要系统通知栏显示的推送 ## 配置位置说明 **⚠️ 重要:所有配置都在 `capability-push` 模块中管理,`app` 模块不需要任何配置!** - ✅ **配置位置**:`capability-push/src/main/res/values/strings.xml` - ✅ **清单文件**:`capability-push/src/main/AndroidManifest.xml` - ✅ **app 模块**:只需要在 `Application` 中调用 `PushServiceFactory.init()` 即可 **❌ 禁止在 app 模块中配置:** - ❌ **禁止**在 `app/src/main/AndroidManifest.xml` 中配置极光推送的 `meta-data` - ❌ **禁止**在 `app/src/main/res/values/strings.xml` 中配置极光推送参数 - ❌ **禁止**在 `app/build.gradle` 中配置极光推送相关参数 - ✅ **所有配置都在 `capability-push` 模块中!** ## 常见问题 ### Q1: 应用从未启动过,点击通知能正常跳转吗? **A: 可以!** 使用静态配置(`ActivityMapping`)后,即使应用从未启动过,点击通知也能正常跳转。 **原理**: - `BroadcastReceiver` 是独立组件,系统会在应用未启动时启动应用进程 - 静态配置在类加载时即可用,不依赖 `Application.onCreate()` 的执行 - 跳转逻辑优先使用静态配置,确保可靠性 ### Q2: 静态配置和运行时配置(pageMappings)有什么区别? **A:** - **静态配置**(`ActivityMapping`): - ✅ 支持应用未启动时的跳转 - ✅ 不依赖初始化顺序 - ✅ 更可靠 - ❌ 需要修改代码并重新编译 - **运行时配置**(`pageMappings`): - ✅ 可以动态配置 - ✅ 不需要重新编译 - ❌ 依赖 `Application.onCreate()` 的执行 - ❌ 应用未启动时可能失败 **推荐**:优先使用静态配置,运行时配置作为补充。 ### Q3: 如何添加新的页面映射? **A:** 在 `ActivityMapping.kt` 的 `pageToActivityMap` 中添加新的映射关系: ```kotlin private val pageToActivityMap = mapOf( "detail" to "com.narutohuo.xindazhou.ui.DetailActivity", "newPage" to "com.narutohuo.xindazhou.ui.NewPageActivity", // 新增 ) ``` 注意:Activity 类名必须是完整的包名路径。 ### Q4: 如果静态配置和运行时配置都配置了同一个页面,会使用哪个? **A:** 静态配置(`ActivityMapping`)优先级更高。如果静态配置中找到了对应的 Activity,会优先使用静态配置;如果静态配置中未找到,才会使用运行时配置(`pageMappings`)。 ## 参考文档 - [极光推送官方文档](https://docs.jiguang.cn/jpush/client/android/android_guide/) - [厂商通道 SDK 集成指南](https://docs.jiguang.cn/jpush/client/Android/android_3rd_guide) - [厂商通道接入说明.md](./厂商通道接入说明.md) - 本项目厂商通道配置说明