友盟分享集成说明

目录结构

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/ 层 - 接口定义

2. factory/ 层 - 工厂类

3. impl/ 层 - 具体实现

3.1 ui/ 层 - UI组件

4. model/ 层 - 数据模型

5. AndroidManifest.xml - 权限配置

架构设计

ARouter 架构说明

核心功能说明

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 -> ... } 被调用 ✅

关键点

已完成的工作

SDK 依赖已添加

代码实现已完成

需要您配置的内容

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 模块无需配置。

说明

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)
        }
    }
}

优势

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()
            }
        }
    }
}

说明

支持的分享平台

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

部分支持(待实现)

使用示例

在 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()
            }
        }
    }
}

关键点

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 模式优势

扩展平台支持

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

参考文档