分享基类:
package com.creatorsaijs.creatorai.ui
import android.annotation.SuppressLint
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.os.Bundle
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.creatorsaijs.creatorai.beans.product.AddAccount
import com.creatorsaijs.creatorai.beans.product.ProductInfo
import com.creatorsaijs.creatorai.handler.ShareHandler
import com.creatorsaijs.creatorai.request.product.CreateCountRequest
import com.creatorsaijs.creatorai.request.product.ShareCountRequest
import com.creatorsaijs.http.constants.ApiConstants
import com.creatorsaijs.http.utils.ToastyUtils
import com.creatorsaijs.zwzwidget.enums.ShareType
import com.creatorsaijs.zwzwidget.popup.SharePanelBottomPopup
import com.creatorsaijs.zwzwidget.utils.XPopupUtils
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX
/**
* 分享基类
*/
open class ShareBaseActivity :
BaseActivity() {
protected var productInfo: ProductInfo? = null
protected var url: String? = null
protected val createCountRequest = CreateCountRequest()
protected val shareCountRequest = ShareCountRequest()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
protected fun showShareDialog(showCreateBtn: Boolean?) {
val sharePanelBottomPopup = SharePanelBottomPopup(this)
sharePanelBottomPopup.setOnShareClick { shareType ->
if (shareType == ShareType.WeChat) {
//分享到朋友圈
share(SendMessageToWX.Req.WXSceneSession)
} else if (shareType == ShareType.WeChatMoments) {
//分享给好友
share(SendMessageToWX.Req.WXSceneTimeline)
} else if (shareType == ShareType.Copy) {
//复制链接
copyLink()
}
}
if (showCreateBtn == false) {
sharePanelBottomPopup.rootView.post {
// 此时弹窗视图已加载完成,控件可正常访问
sharePanelBottomPopup.showTip()
}
}
XPopupUtils.getInstance().showBottomDialog(this, sharePanelBottomPopup)
}
protected fun share(type: Int) {
if (productInfo?.attachmentList?.isEmpty() == true) {
ToastyUtils.show("没有任何图片可分享")
return
}
var loadUrl = productInfo?.attachmentList?.get(0)?.attachmentThumbnailUrl
if (loadUrl.isNullOrEmpty()) {
loadUrl = productInfo?.attachmentList?.get(0)?.attachmentUrl
}
Glide.with(this)
.asBitmap()
.load(loadUrl)
// 可选:指定尺寸,避免加载过大 Bitmap 导致 OOM
.override(500, 500) // 根据分享需求设置合适尺寸
.into(object : CustomTarget<Bitmap>
() {
override fun onLoadFailed(errorDrawable: Drawable?) {
super.onLoadFailed(errorDrawable)
ToastyUtils.show("分享失败:图片加载失败")
}
override fun onResourceReady(
resource: Bitmap,
transition: com.bumptech.glide.request.transition.Transition<
in Bitmap>
?
) {
// 关键修复:使用 ?: 提供默认 Config,处理可空问题
val config = resource.config ?: Bitmap.Config.ARGB_8888
val shareBitmap = resource.copy(config, true) ?: run {
ToastyUtils.show("图片处理失败")
return
}
if (shareBitmap.isRecycled) {
ToastyUtils.show("图片已失效")
return
}
// 执行分享逻辑
url = ApiConstants.shareURL + "${productInfo?.productId}"
ShareHandler.shareUrlToWechat(
shareBitmap,
url,
productInfo?.productTitle,
productInfo?.productContent,
type
)
countAfterShare()
}
override fun onLoadCleared(placeholder: Drawable?) {
// 当资源被清除时(如 Activity 销毁),此处可做额外清理
}
})
}
@SuppressLint("ServiceCast")
protected fun copyLink() {
// 1. 要复制的链接(替换为你的实际分享链接)
url =
ApiConstants.shareURL + "${productInfo?.productId}"
// 2. 获取系统剪贴板管理器
val clipboardManager =
getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
// 3. 创建剪贴板内容(可添加标签,方便区分不同来源的剪贴内容)
val clipData = ClipData.newPlainText(
"分享链接", // 标签(可选,用于标识剪贴内容的类型)
url // 实际要复制的文本(链接)
)
// 4. 将内容设置到剪贴板
clipboardManager.setPrimaryClip(clipData)
// 5. 给用户显示“复制成功”的反馈(提升用户体验)
ToastyUtils.show("链接已复制到剪贴板,可粘贴使用")
}
private fun countAfterShare() {
val params = AddAccount().apply {
productId = productInfo?.productId
}
shareCountRequest.create(this@ShareBaseActivity, this@ShareBaseActivity, params)
}
}
分享工具类封装
package com.creatorsaijs.creatorai.utils
import android.content.Context
import android.graphics.Bitmap
import com.creatorsaijs.creatorai.AIApplication
import com.creatorsaijs.http.utils.ToastyUtils
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX
import com.tencent.mm.opensdk.modelmsg.WXImageObject
import com.tencent.mm.opensdk.modelmsg.WXMediaMessage
import com.tencent.mm.opensdk.modelmsg.WXTextObject
import com.tencent.mm.opensdk.modelmsg.WXWebpageObject
import java.io.ByteArrayOutputStream
import java.io.IOException
class WxShareUtils private
constructor(context: Context){
fun shareTextAndImage(content: String?, url: String?) {
val textObj = WXTextObject()
textObj.text = content
val msg = WXMediaMessage()
msg.mediaObject = textObj
msg.description = "文本描述"
// 4. 构造请求
val req = SendMessageToWX.Req()
req.transaction = System.currentTimeMillis().toString()
req.message = msg
req.scene = SendMessageToWX.Req.WXSceneSession // 分享类型
// 5. 发送请求
AIApplication.Companion.instance.wxApi?.sendReq(req)
}
fun shareToFriendMoments(content: String?) {
val textObj = WXTextObject()
textObj.text = content
val msg = WXMediaMessage()
msg.mediaObject = textObj
msg.description = "文本描述"
// 4. 构造请求
val req = SendMessageToWX.Req()
req.transaction = System.currentTimeMillis().toString()
req.message = msg
req.scene = SendMessageToWX.Req.WXSceneTimeline // 分享类型
// 5. 发送请求
AIApplication.Companion.instance.wxApi?.sendReq(req)
}
fun shareImgToWechat(bmp: Bitmap?, scene: Int) {
if (null == bmp) {
ToastyUtils.show("图片为空")
return
}
//初始化一个WXImageObject对象
val imageObject = WXImageObject()
//设置缩略图
val thump = Bitmap.createScaledBitmap(bmp, 300, 300, true)
bmp.recycle()
val msg = WXMediaMessage(imageObject)
//构造一个Req
val req = SendMessageToWX.Req()
req.transaction = System.currentTimeMillis().toString()
req.message = msg
req.scene = scene
AIApplication.Companion.instance.wxApi?.sendReq(req)
}
fun shareUrlToWechat(
thumb: Bitmap?,
url: String?,
title: String?,
description: String?,
scene: Int
) {
//初试话一个WXWebpageObject对象,填写url
val webPage = WXWebpageObject()
webPage.webpageUrl = url
//设置缩略图
println("bmpToByteArray0: " + thumb?.getByteCount())
if(thumb == null){
ToastyUtils.show("缩略图为空")
return
}
val tmb = Bitmap.createScaledBitmap(thumb!!, 150, 150, true)
thumb.recycle()
val msg = WXMediaMessage(webPage)
msg.title = title
msg.description = description
msg.thumbData = bmpToByteArray(tmb)
// msg.setThumbImage(tmb);
//构造一个Req
val req = SendMessageToWX.Req()
req.transaction = System.currentTimeMillis().toString()
req.message = msg
req.scene = scene
AIApplication.Companion.instance.wxApi?.sendReq(req)
}
private fun bmpToByteArray(bitmap: Bitmap?): ByteArray? {
var output: ByteArrayOutputStream? = null
try {
if (bitmap == null) {
return null
}
output = ByteArrayOutputStream()
var quality = 100
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, output)
//循环判断压缩后图片是否超过限制大小
println("bmpToByteArray1: " + output.toByteArray().size)
while ((output.toByteArray().size / 1024) >
32) {
output.reset()
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, output)
quality -= 10
}
bitmap.recycle()
println("bmpToByteArray2: " + output.toByteArray().size)
return output.toByteArray()
} catch (e: Exception) {
return null
} catch (e: OutOfMemoryError) {
return null
} finally {
try {
if (output != null) output.close()
} catch (e: IOException) {
return null
}
}
}
private fun bmpToByteArray(bmp: Bitmap, needRecycle: Boolean): ByteArray {
val output = ByteArrayOutputStream()
bmp.compress(
Bitmap.CompressFormat.JPEG,
100,
output
) //CompressFormat.JPEG是图片格式,也可以选择CompressFormat.PNG; 90是压缩率
if (needRecycle) {
bmp.recycle()
}
println("bmpToByteArray3: " + output.toByteArray().size)
val result = output.toByteArray()
try {
output.close()
} catch (e: Exception) {
e.printStackTrace()
}
return result
}
companion object {
@Volatile
private var instance: WxShareUtils? = null
fun init(context: Context) {
instance = WxShareUtils(context.applicationContext)
}
fun getInstance(): WxShareUtils {
return instance ?: throw kotlin.IllegalStateException("WxShareUtils not initialized")
}
}
}