集成说明.md 20 KB

友盟分享集成说明

目录结构

capability-share/src/
└── main/
    ├── AndroidManifest.xml          # Android 清单文件(权限声明)
    └── java/
        └── com/narutohuo/xindazhou/share/
            ├── api/                  # API 接口层
            │   └── ShareService.kt   # 分享服务接口定义(统一 share() 方法 + 9个平台方法)
            ├── factory/              # 工厂类层
            │   └── ShareServiceFactory.kt  # 服务工厂(统一入口,单例获取)
            ├── impl/                 # 实现层
            │   └── ShareServiceImpl.kt     # 分享服务具体实现(封装友盟SDK)
            ├── ui/                   # UI层
            │   ├── ShareDialogFragment.kt   # 分享弹窗(封装在模块内部)
            │   └── ShareProxyActivity.kt    # 透明代理 Activity(自动处理 onActivityResult)
            └── model/                # 数据模型层
                ├── ShareResponse.kt        # 分享相关的数据模型
                │   ├── ShareContent        # 分享内容模型
                │   ├── ShareResponse       # 分享响应模型
                │   └── SharePlatform       # 分享平台枚举
                └── ShareConfig.kt          # 分享服务配置模型
                    ├── ShareConfig         # 主配置类
                    ├── WeChatConfig        # 微信平台配置
                    ├── QQConfig            # QQ平台配置
                    └── WeiboConfig         # 微博平台配置

功能说明

1. api/ 层 - 接口定义

  • 职责:定义分享服务的公共接口,业务层只依赖接口
  • 内容ShareService 接口
    • share() - 统一分享方法(推荐使用,业务层调用)
    • 自动处理 onActivityResult,业务层不需要在 Activity 中处理回调
    • 如果 ShareContent.platform 已指定,直接分享到该平台
    • 如果 ShareContent.platform 为 null,显示分享弹窗让用户选择
    • 内部使用透明代理 Activity 封装所有实现细节
    • shareManual() - 手动分享方法(内部使用,避免递归调用)
    • ShareProxyActivity 内部调用,业务层不应直接使用
    • 如果指定了平台,直接分享到该平台;否则显示分享弹窗
    • showShareDialog() - 显示分享弹窗(底部弹出)

2. factory/ 层 - 工厂类

  • 职责:提供统一的服务实例获取和初始化方式
  • 内容ShareServiceFactory 单例工厂
  • 作用
    • 隐藏实现细节,统一入口,便于替换实现
    • 提供 init() 方法统一初始化,避免在 Application 中直接调用服务方法
    • 提供 getInstance() 方法获取服务实例

3. impl/ 层 - 具体实现

  • 职责:实现 ShareService 接口的具体逻辑
  • 内容ShareServiceImpl 单例实现类
  • 功能
    • 封装友盟分享 SDK 调用
    • 封装友盟初始化逻辑(initialize()
    • 封装分享回调处理(onActivityResult())- 通过透明代理 Activity 自动处理
    • 封装资源释放(release()
    • 实现统一的 share() 方法,自动使用透明代理 Activity,业务层无需处理回调
    • 实现 shareManual() 方法(内部使用,避免递归调用),供 ShareProxyActivity 调用
    • 实现 showShareDialog() 方法,显示分享弹窗
    • 处理分享回调(成功/失败/取消)
    • 错误处理和日志记录
    • 支持网页、图片、文本等多种分享类型

3.1 ui/ 层 - UI组件

  • 职责:封装分享相关的 UI 组件
  • 内容
    • ShareDialogFragment - 分享弹窗(底部弹出)
    • 底部弹出(Material Design BottomSheet)
    • 显示所有可用分享平台(微信、朋友圈、QQ、QQ空间、微博、更多)
    • 用户选择平台后自动执行分享
    • 弹窗逻辑完全封装在模块内部,主工程无需关心
    • ShareProxyActivity - 透明代理 Activity(自动处理 onActivityResult)
    • 继承自 FragmentActivity,支持显示 ShareDialogFragment
    • 完全封装在模块内部,业务层不需要知道它的存在
    • 自动处理分享回调,业务层不需要在 Activity 中处理 onActivityResult
    • 内部使用 shareManual() 方法避免递归调用
    • 透明主题,用户看不到
    • 分享完成后自动关闭

4. model/ 层 - 数据模型

  • 职责:定义分享相关的数据模型
  • 内容
    • ShareContent - 分享内容模型(标题、描述、URL、图片等)
    • Builder 模式ShareContent.builder() 链式调用构建,支持灵活的参数组合
    • 平台类型platform: SharePlatform? 字段
      • 如果指定,直接分享到该平台(不显示弹窗)
      • 如果为 null,显示分享弹窗让用户选择
    • ShareResponse - 分享响应模型(成功/失败、错误信息等)
    • SharePlatform - 分享平台枚举(9个平台)
    • ShareConfig - 分享服务配置模型(封装友盟和各平台配置)
    • WeChatConfig - 微信平台配置
    • QQConfig - QQ平台配置
    • WeiboConfig - 微博平台配置

5. AndroidManifest.xml - 权限配置

  • 职责:声明模块所需的 Android 权限
  • 内容:网络权限声明

架构设计

  • 接口隔离:业务层只依赖接口,不依赖实现
  • ARouter 依赖注入:通过 ARouter 实现模块间解耦,base-core 定义接口,能力层实现接口
  • 工厂模式:统一入口,隐藏创建逻辑(内部使用 ARouter 获取服务)
  • 单例模式:全局共享一个服务实例
  • 分层架构:base-core (接口) → capability-share (实现) → ARouter (注册) → Factory (获取)
  • 完全封装:使用透明代理 Activity 自动处理 onActivityResult,业务层无需关心实现细节

ARouter 架构说明

  • base-core 模块定义 IShareService 接口(位于 com.narutohuo.xindazhou.core.share
  • capability-share 模块实现 IShareService 接口,并通过 @Route(path = "/share/service") 注册到 ARouter
  • base-core 模块中的 WXEntryActivity 通过 ARouter 注入 IShareCallback 实现(@Route(path = "/share/callback")
  • Factory 内部使用 ARouter.getInstance().navigation(IShareService::class.java) 获取服务实例
  • 业务层 通过 Factory 获取服务,无需直接依赖实现模块

核心功能说明

1. 分享回调流程(完全封装,统一处理所有平台)

完整回调链路

业务层调用 shareService.share(activity, content, callback)
    ↓
ShareServiceImpl.share() 自动启动 ShareProxyActivity
    ↓
ShareProxyActivity.onCreate() 调用 shareService.shareManual()
    ↓
ShareServiceImpl.shareManual() 调用友盟 SDK 进行分享(或显示分享弹窗)
    ↓
用户在第三方应用(如微信、QQ、微博)完成分享操作
    ↓
第三方应用回调到各自的回调 Activity:
  - 微信 → WXEntryActivity(base-core 模块,通过 ARouter 注入 IShareCallback)
    ↓ WXEntryActivity.onWeChatCallback() 调用 shareCallback.onWeChatCallback()
    ↓ ShareCallbackImpl.onWeChatCallback() 处理回调
  - QQ → AuthActivity(QQ SDK 自带,友盟自动处理)
  - 微博 → WBShareTransActivity(微博 SDK 自带,友盟自动处理)
    ↓
友盟 SDK 通过 onActivityResult 回调到 ShareProxyActivity.onActivityResult()
    ↓
ShareProxyActivity.onActivityResult() 调用 shareService.onActivityResult()
    ↓
ShareServiceImpl.onActivityResult() 调用 UMShareAPI.get(activity).onActivityResult()
    ↓
友盟 SDK 触发 ShareServiceImpl 中设置的 UMShareListener.onResult() / onError() / onCancel()
    ↓
UMShareListener 调用业务层传入的 callback 函数
    ↓
ShareProxyActivity 收到回调结果,调用业务层的 callback,并自动关闭自身
    ↓
业务层的 callback { response -> ... } 被调用 ✅

关键点

  • 统一入口share() 方法自动启动 ShareProxyActivity,所有平台的分享都通过它处理
  • 统一回调:所有平台(微信、QQ、微博等)的回调都统一回到 ShareProxyActivity.onActivityResult()
  • ARouter 解耦WXEntryActivitybase-core 模块,通过 ARouter 注入 IShareCallback 实现,实现模块间解耦
  • 业务层透明:业务层不需要在 Activity 中处理 onActivityResult,完全封装在模块内部
  • 自动关闭ShareProxyActivity 收到回调后自动关闭,用户无感知

已完成的工作

SDK 依赖已添加

  • com.umeng.umsdk:common:9.6.8 - 友盟基础库
  • com.umeng.umsdk:share-core:7.3.2 - 友盟分享核心库
  • com.umeng.umsdk:share-board:7.3.2 - 友盟分享面板
  • com.umeng.umsdk:share-wx:7.3.2 - 微信分享
  • com.umeng.umsdk:share-qq:7.3.2 - QQ分享
  • com.umeng.umsdk:share-sina:7.3.2 - 新浪微博分享

代码实现已完成

  • ShareServiceImpl 已实现友盟分享 SDK 调用,并实现 IShareService 接口
  • ShareServiceImpl 已通过 ARouter 注册(@Route(path = "/share/service")
  • ShareCallbackImpl 已实现 IShareCallback 接口,并通过 ARouter 注册(@Route(path = "/share/callback")
  • ShareServiceFactory 已创建,内部使用 ARouter 获取服务
  • IShareService 接口已在 base-core 模块定义
  • IShareCallback 接口已在 base-core 模块定义
  • WXEntryActivity 已移至 base-core 模块,通过 ARouter 注入回调实现
  • ARouter 集成完成:模块间解耦,通过 ARouter 进行依赖注入

需要您配置的内容

1. 在友盟官网注册应用

  1. 访问 友盟+官网
  2. 注册账号并创建应用
  3. 获取 AppKeyAppSecret

2. 配置第三方平台

2.1 微信平台配置

  1. 访问 微信开放平台
  2. 创建移动应用,获取 AppIDAppSecret

2.2 QQ平台配置

  1. 访问 QQ开放平台
  2. 创建移动应用,获取 AppIDAppKey

2.3 新浪微博配置

  1. 访问 新浪微博开放平台
  2. 创建移动应用,获取 AppKeyAppSecret

3. 配置 AndroidManifest.xml

注意:权限声明和回调 Activity 配置已在各模块的 AndroidManifest.xml 中完成,app 模块无需配置。

  • 权限声明:已在 capability-share/src/main/AndroidManifest.xml 中配置
  • 回调 Activity
    • WXEntryActivity 已在 base-core/src/main/AndroidManifest.xml 中配置
    • AuthActivity(QQ)、WBShareTransActivity(微博)已在 capability-share/src/main/AndroidManifest.xml 中配置
  • ARouter 初始化:已在 XinDaZhouApplication 中完成(见步骤5)

说明

  • ✅ 所有配置都在各模块内部管理,app 模块无需配置
  • ✅ AppKey 和平台配置通过代码完成(见步骤4),更灵活

4. 配置资源文件(推荐方式)

注意:配置位置已改为 capability-share/src/main/res/values/strings.xmlapp 模块无需配置。

capability-share/src/main/res/values/strings.xml 中配置分享参数(推荐方式,配置统一管理):

<!-- capability-share/src/main/res/values/strings.xml -->
<resources>
    <!-- 友盟配置(必填) -->
    <string name="share_umeng_app_key">您的友盟 AppKey</string>
    <string name="share_umeng_channel">developer-default</string>
    
    <!-- 微信平台配置(可选) -->
    <string name="share_wechat_app_id">您的微信 AppID</string>
    <string name="share_wechat_app_secret">您的微信 AppSecret</string>
    
    <!-- QQ平台配置(可选) -->
    <string name="share_qq_app_id">您的QQ AppID</string>
    <string name="share_qq_app_key">您的QQ AppKey</string>
    <!-- QQ AppID Scheme(用于回调,格式:tencent + AppID) -->
    <string name="qq_app_id_scheme">tencent您的QQ AppID</string>
    
    <!-- 微博平台配置(可选) -->
    <string name="share_weibo_app_key">您的新浪微博 AppKey</string>
    <string name="share_weibo_app_secret">您的新浪微博 AppSecret</string>
    <string name="share_weibo_redirect_url">您的新浪微博回调地址</string>
</resources>

5. 在 Application 中初始化(统一入口)

在您的 XinDaZhouApplication 类中初始化分享服务:

// app/src/main/java/com/narutohuo/xindazhou/XinDaZhouApplication.kt
package com.narutohuo.xindazhou

import android.app.Application
import com.alibaba.android.arouter.launcher.ARouter
import com.narutohuo.xindazhou.share.factory.ShareServiceFactory

class XinDaZhouApplication : Application() {
    
    override fun onCreate() {
        super.onCreate()
        
        // ========== 初始化 ARouter(必须在其他初始化之前)==========
        if (BuildConfig.DEBUG) {
            ARouter.openLog()
            ARouter.openDebug()
        }
        ARouter.init(this)
        
        // ========== 初始化分享服务(从资源文件读取配置)==========
        try {
            ShareServiceFactory.init(context = this)
        } catch (e: Exception) {
            // 分享服务初始化失败不影响应用运行,但分享功能将不可用
            android.util.Log.e("XinDaZhouApplication", "分享服务初始化失败", e)
        }
    }
}

优势

  • 最简单:只需一行代码,配置都在资源文件中
  • 统一入口:通过 ShareServiceFactory.init() 统一初始化,代码更清晰
  • ARouter 解耦:通过 ARouter 实现模块间解耦,base-core 与 share 模块完全解耦
  • ✅ 业务层不直接依赖友盟API
  • ✅ 如果更换SDK,只需修改实现层,业务层无需改动
  • ✅ 配置统一管理,代码更清晰

6. 使用分享功能(完全封装,无需处理回调)

重要更新:分享功能已完全封装,业务层不需要MainActivity 中处理 onActivityResult

分享组件内部使用透明代理 Activity 自动处理所有回调,业务层只需要调用 share() 方法即可:

// app/src/main/java/com/narutohuo/xindazhou/user/ui/profile/UserFragment.kt
class UserFragment : Fragment() {
    
    private val shareService = ShareServiceFactory.getInstance()
    
    private fun shareContent() {
        val content = ShareContent.builder()
            .setTitle("分享标题")
            .setDescription("分享描述")
            .setUrl("https://example.com")
            .build()
        
        // 直接调用 share() 方法,自动处理所有回调
        shareService.share(requireActivity(), content) { response ->
            if (response.success) {
                Toast.makeText(requireContext(), "分享成功", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

说明

  • 完全封装:业务层不需要处理 onActivityResult,所有回调都在组件内部处理
  • 使用简单:只需调用 share() 方法,传入分享内容和回调即可
  • 透明代理:组件内部使用透明 Activity 处理回调,用户看不到
  • 自动关闭:分享完成后,透明 Activity 自动关闭,回到原界面

支持的分享平台

已完整支持(通过友盟SDK)

  • 微信 - shareToWeChat()
  • 微信朋友圈 - shareToWeChatMoments()
  • QQ - shareToQQ()
  • QQ空间 - shareToQZone()
  • 新浪微博 - shareToWeibo()

部分支持(待实现)

  • ⚠️ 抖音 - shareToDouyin() - 待实现
  • ⚠️ 小红书 - shareToXiaohongshu() - 待实现
  • ⚠️ 快手 - shareToKuaishou() - 待实现
  • 系统分享 - shareToSystem() - 调用系统分享菜单

使用示例

在 Fragment 中使用分享(实际项目示例)

分享功能在 Fragment 中使用:

// app/src/main/java/com/narutohuo/xindazhou/user/ui/profile/UserFragment.kt
package com.narutohuo.xindazhou.user.ui.profile

import android.view.View
import android.widget.Button
import android.widget.Toast
import androidx.fragment.app.Fragment
import com.narutohuo.xindazhou.R
import com.narutohuo.xindazhou.share.factory.ShareServiceFactory
import com.narutohuo.xindazhou.share.model.ShareContent
import com.narutohuo.xindazhou.share.model.ShareResponse
import timber.log.Timber

class UserFragment : Fragment() {
    
    // 获取分享服务实例(单例)
    private val shareService = ShareServiceFactory.getInstance()
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // 示例:分享按钮点击
        view.findViewById<Button>(R.id.btnShare)?.setOnClickListener {
            shareContent()
        }
    }
    
    /**
     * 分享内容示例(推荐:使用统一的 share() 方法)
     */
    private fun shareContent() {
        // 创建分享内容(使用 Builder 模式)
        val content = ShareContent.builder()
            .setTitle("新大洲智能车控")
            .setDescription("分享给您一个有趣的内容")
            .setUrl("https://example.com/share/123")
            .setImageUrl("https://example.com/image.jpg")
            .setThumbImageUrl("https://example.com/thumb.jpg")
            // 不设置 platform,会显示分享弹窗
            .build()
        
        // 方式1:统一方法(推荐)- 显示分享弹窗,用户选择平台
        shareService.share(requireActivity(), content) { response: ShareResponse ->
            if (response.success) {
                // response.data 就是用户选择的平台(SharePlatform)
                val platform = response.data  // 例如:SharePlatform.WECHAT、SharePlatform.QQ 等
                Timber.d("分享成功: 平台=${platform}")
                Toast.makeText(requireContext(), "分享成功到:${platform}", Toast.LENGTH_SHORT).show()
            } else {
                Timber.e("分享失败: ${response.errorMessage}")
                Toast.makeText(requireContext(), "分享失败: ${response.errorMessage}", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

关键点

  • ✅ Fragment 中使用 requireActivity() 获取 Activity 实例
  • 完全封装:分享回调在组件内部的透明代理 Activity 中自动处理
  • 无需配置:业务层不需要在 MainActivity 中处理 onActivityResult
  • 使用简单:只需调用 share() 方法,传入分享内容和回调即可

ShareContent Builder 模式使用示例

// 方式1:完整参数(网页分享)
val content1 = ShareContent.builder()
    .setTitle("分享标题")
    .setDescription("分享描述")
    .setUrl("https://example.com")
    .setImageUrl("https://example.com/image.jpg")
    .setThumbImageUrl("https://example.com/thumb.jpg")
    .build()

// 方式2:仅文本(纯文本分享)
val content2 = ShareContent.builder()
    .setTitle("分享标题")
    .setDescription("分享描述")
    .build()

// 方式3:图片分享(无链接)
val content3 = ShareContent.builder()
    .setTitle("图片分享")
    .setDescription("这是一张图片")
    .setImageUrl("https://example.com/image.jpg")
    .build()

// 方式4:链式调用,灵活组合
val content4 = ShareContent.builder()
    .setTitle("标题")
    .setDescription("描述")
    .setUrl("https://example.com")
    .build()  // 只设置必填项,其他可选参数不设置

Builder 模式优势

  • ✅ 参数灵活,不需要创建多个构造函数
  • ✅ 代码可读性强,链式调用清晰
  • ✅ 参数验证在 build() 时统一检查
  • ✅ 支持必填参数验证(title 和 description 不能为空)

扩展平台支持

以下平台接口已暴露,具体实现待完成:

  • 抖音 - shareToDouyin() - 待实现
  • 小红书 - shareToXiaohongshu() - 待实现
  • 快手 - shareToKuaishou() - 待实现

参考文档