集成说明.md 16 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 权限
  • 内容:网络权限声明

架构设计

  • 接口隔离:业务层只依赖接口,不依赖实现
  • 工厂模式:统一入口,隐藏创建逻辑
  • 单例模式:全局共享一个服务实例
  • 分层架构:api → factory → impl → 第三方SDK
  • 完全封装:使用透明代理 Activity 自动处理 onActivityResult,业务层无需关心实现细节

已完成的工作

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 调用
  • ShareServiceFactory 已创建

需要您配置的内容

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

app/src/main/AndroidManifest.xml 中添加权限声明(meta-data 配置已通过代码完成,无需在 Manifest 中配置):

<manifest>
    <!-- 友盟分享权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
    <application>
        <!-- 注意:友盟和各平台的配置已通过代码完成(见步骤4),无需在此配置 meta-data -->
    </application>
</manifest>

说明

  • ✅ 权限声明是必需的
  • ✅ AppKey 和平台配置通过代码完成(见步骤4),更灵活
  • ✅ 如果需要在 Manifest 中配置,也可以保留,代码配置会覆盖 Manifest 配置

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

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

<!-- app/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>
    
    <!-- 微博平台配置(可选) -->
    <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 类中初始化分享服务,支持三种方式

方式1:使用默认配置(从资源文件读取,最简单)

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

import android.app.Application
import com.narutohuo.xindazhou.share.factory.ShareServiceFactory

class XinDaZhouApplication : Application() {
    
    override fun onCreate() {
        super.onCreate()
        
        // ========== 初始化分享服务(最简单,从资源文件读取配置)==========
        ShareServiceFactory.init(context = this)
    }
}

优势

  • 最简单:只需一行代码,配置都在资源文件中
  • 统一入口:通过 ShareServiceFactory.init() 统一初始化,代码更清晰
  • ✅ 业务层不直接依赖友盟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() - 待实现

参考文档