Files
assistant-android/app/src/main/java/com/gh/common/util/DownloadItemUtils.kt

1273 lines
55 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.gh.common.util
import android.content.Context
import android.os.Message
import android.text.TextUtils
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.collection.ArrayMap
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.chain.*
import com.gh.common.constant.Config
import com.gh.common.dialog.DeviceRemindDialog
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.history.HistoryHelper
import com.gh.common.repository.ReservationRepository
import com.gh.common.simulator.NewSimulatorGameManager
import com.gh.common.simulator.SimulatorDownloadManager
import com.gh.common.simulator.SimulatorGameManager
import com.gh.common.xapk.XapkInstaller
import com.gh.common.xapk.XapkInstaller.cancelUnzipTask
import com.gh.common.xapk.XapkInstaller.isInstalling
import com.gh.common.xapk.XapkUnzipStatus
import com.gh.download.DownloadManager
import com.gh.download.dialog.DownloadDialog
import com.gh.download.server.BrowserInstallHelper
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.common.callback.CancelListener
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PluginLocation
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.view.DownloadButton
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
import com.gh.gamecenter.manager.PackagesManager
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.teenagermode.TeenagerModeActivity
import com.gh.vspace.VHelper
import com.lightgame.download.DownloadConfig
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import com.lightgame.utils.Utils
import java.io.File
import java.util.concurrent.LinkedBlockingQueue
/**
* todo 下载判断不能以按钮文案为判断条件,否则按钮文案修改时又要修改判断逻辑
*/
object DownloadItemUtils {
// 更新下载进度条
fun processDate(
gameEntity: GameEntity,
downloadEntity: DownloadEntity,
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
index: Int
) {
if (gameEntity.id != downloadEntity.gameId) {
adapter?.notifyItemChanged(index)
return
}
var queue = DownloadManager.getInstance().getQueue(downloadEntity.name)
if (queue == null) {
queue = LinkedBlockingQueue()
DownloadManager.getInstance().putQueue(downloadEntity.name, queue)
}
val platform = downloadEntity.platform
val entryMap: ArrayMap<String, DownloadEntity>
val status = downloadEntity.status
if (status == DownloadStatus.pause || status == DownloadStatus.cancel || status == DownloadStatus.done) {
queue.remove(platform)
entryMap = ArrayMap()
gameEntity.setEntryMap(entryMap)
entryMap[platform] = downloadEntity
adapter?.notifyItemChanged(index)
} else {
if (!queue.contains(platform) && !TextUtils.isEmpty(platform)) {
queue.offer(platform)
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodWithParams(
DownloadItemUtils::class.java,
queue.size,
gameEntity.brief,
downloadEntity.platform,
index
)
}
// 有两个平台同时下载的时候启用
if (queue.size == 2) {
//TODO fuck this
val msg = Message.obtain()
msg.obj = downloadEntity.name
msg.what = DownloadConfig.DOWNLOAD_ROLL
DownloadManager.getInstance().sendMessageDelayed(msg, 3000)
}
}
if (platform != null && platform == queue.peek()) {
entryMap = ArrayMap()
gameEntity.setEntryMap(entryMap)
entryMap[platform] = downloadEntity
if (DownloadStatus.pause != DownloadManager.getInstance().getStatus(downloadEntity.url)) {
adapter?.notifyItemChanged(index)
}
}
}
}
// 下载按钮显示为查看,并且不提供下载功能
fun updateItemWithViewOnlyStyle(holder: GameViewHolder) {
holder.gameDownloadBtn.visibility = View.VISIBLE
holder.gameDownloadBtn.text = "查看"
holder.gameDownloadBtn.isClickable = false
}
// 根据预约状态更新下载按钮
fun updateItemWithReserveStatus(holder: GameViewHolder, gameEntity: GameEntity) {
if ("download" == gameEntity.reserveStatus) {
// 已上线
updateItem(holder.gameDownloadBtn.context, gameEntity, holder)
} else if ("appointment" == gameEntity.reserveStatus) {
// 已预约
holder.gameDownloadBtn.text = "已预约"
holder.gameDownloadBtn.visibility = View.VISIBLE
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.RESERVED
updateItemViewStatus(holder, null, null)
}
}
fun updateItem(
context: Context,
gameEntity: GameEntity,
holder: GameViewHolder,
hideDownloadBtnIfNoAvailableContent: Boolean
) {
updateItem(
context = context,
gameEntity = gameEntity,
holder = holder,
pluginLocation = PluginLocation.only_game,
hideDownloadBtnIfNoAvailableContent = hideDownloadBtnIfNoAvailableContent,
briefStyle = null
)
}
fun updateItem(
context: Context,
gameEntity: GameEntity,
holder: GameViewHolder,
briefStyle: String?
) {
updateItem(
context = context,
gameEntity = gameEntity,
holder = holder,
pluginLocation = PluginLocation.only_game,
hideDownloadBtnIfNoAvailableContent = false,
briefStyle = briefStyle
)
}
@JvmStatic
@JvmOverloads
fun updateItem(
context: Context,
gameEntity: GameEntity,
holder: GameViewHolder,
pluginLocation: PluginLocation? = PluginLocation.only_game,
hideDownloadBtnIfNoAvailableContent: Boolean = false,
briefStyle: String? = null,
isShowRecommendStar: Boolean = false
) {
holder.gameDownloadBtn.putObject(gameEntity)
// 显示预约
if (gameEntity.isReservable) {
holder.multiVersionDownloadTv?.visibility = View.GONE
updateItemViewStatus(holder, briefStyle, gameEntity.columnRecommend, isShowRecommendStar)
updateDownloadButton(
context,
holder.gameDownloadBtn,
gameEntity,
hideDownloadBtnIfNoAvailableContent,
pluginLocation
)
return
}
if (gameEntity.getApk().isEmpty() || gameEntity.downloadOffStatus != null) {
holder.multiVersionDownloadTv?.visibility = View.GONE
holder.gameDownloadTips?.visibility = View.GONE
updateItemViewStatus(holder, briefStyle, gameEntity.columnRecommend, isShowRecommendStar)
} else if (gameEntity.getApk().size == 1) {
holder.multiVersionDownloadTv?.visibility = View.GONE
holder.gameDownloadTips?.visibility = View.GONE
updateNormalItem(context, holder, gameEntity, briefStyle, isShowRecommendStar)
} else {
holder.multiVersionDownloadTv?.isVisible = !SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)
updatePluginItem(context, holder, gameEntity, briefStyle, isShowRecommendStar)
}
updateDownloadButton(
context,
holder.gameDownloadBtn,
gameEntity,
hideDownloadBtnIfNoAvailableContent,
pluginLocation
)
}
fun updateDownloadButton(
context: Context,
downloadBtn: DownloadButton,
gameEntity: GameEntity,
hideDownloadBtnIfNoAvailableContent: Boolean = false,
pluginLocation: PluginLocation? = PluginLocation.only_game
) {
// 控制是否显示下载按钮
downloadBtn.goneIf(context.getString(R.string.app_name) == gameEntity.name)
// 青少年模式或者需要特殊处理显示查看
if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE) || gameEntity.isSpecialDownload()) {
downloadBtn.text = "查看"
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.TEENAGER_MODE
return
}
if (gameEntity.isReservable) {
downloadBtn.apply {
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.id)) {
text = "预约"
buttonStyle = DownloadButton.ButtonStyle.RESERVABLE
} else {
text = "已预约"
buttonStyle = DownloadButton.ButtonStyle.RESERVED
}
}
return
}
if (RegionSettingHelper.getGameH5DownloadByGameId(gameEntity.id) != null) {
downloadBtn.apply {
isClickable = true
text = context.getString(R.string.check)
setBackgroundResource(R.drawable.download_button_normal_style)
setTextColor(R.color.white.toColor(context))
}
return
}
if (gameEntity.isMiniGame()) {
if (gameEntity.isMiniGameOffShelve()) {
downloadBtn.apply {
isClickable = false
text = context.getString(R.string.off_shelve)
buttonStyle = DownloadButton.ButtonStyle.NONE
}
} else {
downloadBtn.apply {
isClickable = true
setBackgroundResource(R.drawable.download_button_normal_style)
setTextColor(R.color.white.toColor(context))
text = context.getString(R.string.quick_play)
}
}
return
}
if (gameEntity.getApk().isEmpty() || gameEntity.downloadOffStatus != null) {
val h5LinkEntity = gameEntity.h5Link
val offStatus = gameEntity.downloadOffStatus
downloadBtn.apply {
if (h5LinkEntity != null) {
text = if ("play" == h5LinkEntity.type) {
context.getString(R.string.start_playing)
} else {
context.getString(R.string.check)
}
isClickable = true
buttonStyle = DownloadButton.ButtonStyle.NORMAL
} else {
if ("dialog" == offStatus) {
text = context.getString(R.string.check)
buttonStyle = DownloadButton.ButtonStyle.NORMAL
} else if ("updating" == offStatus) {
text = context.getString(R.string.updating)
buttonStyle = DownloadButton.ButtonStyle.UPDATING
} else {
text = context.getString(R.string.none)
buttonStyle = DownloadButton.ButtonStyle.NONE
if (hideDownloadBtnIfNoAvailableContent) {
visibility = View.GONE
}
}
downloadBtn.isClickable = false
}
}
} else if (gameEntity.getApk().size == 1) {
// 来自于下载管理的实体快照
val entityFromDownloadManager = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
// 是否正在下载中
val isDownloading = entityFromDownloadManager != null && entityFromDownloadManager.status != DownloadStatus.done
// 是否已安装至本地
val isInstalledLocally = PackagesManager.isInstalled(gameEntity.getUniquePackageName())
// 来自于畅玩安装列表的实体快照,若存在,代表游戏已下载并成功安装
val entityFromInstalledVGame = VHelper.getVDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
// 是否已安装至畅玩
val isInstalledToVSpace = entityFromInstalledVGame != null
// 是否处于待安装状态 (仅本地安装有这个状态)
val isPendingToInstall = if (entityFromDownloadManager?.status != DownloadStatus.done) {
false
} else {
entityFromDownloadManager.isLocalDownloadInDualDownloadMode()
&& (!isInstalledLocally || entityFromDownloadManager.isUpdate)
}
// 列表按钮显示的优先级
// 1. 都未安装,且不存在下载任务,按后台配置显示的状态优先
// 2. 存在未完成的下载任务时,下载任务优先
// 3. 存在待安装任务时,待安装任务优先
// 4. 存在一个已安装,已安装的显示优先
// 5. 都已安装,按后台配置显示的状态优先
val isVGamePreferred = if (!isInstalledLocally && !isInstalledToVSpace && entityFromDownloadManager == null) {
gameEntity.isVGamePreferred()
} else if (isDownloading || isPendingToInstall) {
entityFromDownloadManager?.isVGameDownloadInDualDownloadMode() == true
} else if (isInstalledLocally && isInstalledToVSpace) {
gameEntity.isVGamePreferred()
} else if (isInstalledLocally) {
false
} else if (isInstalledToVSpace) {
true
} else {
gameEntity.isVGamePreferred()
}
val downloadEntity: DownloadEntity? = if (isDownloading) {
entityFromDownloadManager
} else if (isPendingToInstall) {
entityFromDownloadManager
} else {
if (isVGamePreferred) {
entityFromInstalledVGame ?: entityFromDownloadManager
} else {
entityFromDownloadManager
}
}
if (downloadEntity != null) {
downloadBtn.apply {
when (downloadEntity.status) {
DownloadStatus.done -> {
if (downloadEntity.isSimulatorGame() && gameEntity.simulator != null) {
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation)
} else if (isVGamePreferred) {
buttonStyle =
if (PackagesManager.isCanUpdate(
downloadEntity.gameId,
downloadEntity.packageName,
asVGame = true
)
) {
setText(R.string.update)
DownloadButton.ButtonStyle.NORMAL
} else {
setText(R.string.launch)
DownloadButton.ButtonStyle.LAUNCH_OR_OPEN
}
} else {
val xapkStatus = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
if (XapkUnzipStatus.SUCCESS.name == xapkStatus && isInstalling(downloadEntity.path)) {
progress = 100
setText(R.string.installing)
buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
return
}
if (XapkUnzipStatus.UNZIPPING.name == xapkStatus) {
val percent = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_PERCENT]
progress = (java.lang.Float.valueOf(percent) * 10).toInt()
text = "$percent%"
buttonStyle = DownloadButton.ButtonStyle.XAPK_UNZIPPING
return
} else if (XapkUnzipStatus.FAILURE.name == xapkStatus) {
setText(R.string.install)
buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
return
}
if (PackagesManager.isInstalled(downloadEntity.packageName) && !downloadEntity.isUpdate) {
// 双下载按钮快速安装时存在已下载的安装包过时,需要重新下载的情况
if (PackagesManager.isCanUpdate(downloadEntity.gameId, downloadEntity.packageName)) {
buttonStyle = DownloadButton.ButtonStyle.NORMAL
setText(R.string.update)
} else {
buttonStyle = DownloadButton.ButtonStyle.LAUNCH_OR_OPEN
setText(R.string.launch)
}
} else {
buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
setText(R.string.install)
}
}
buttonStyle =
if (downloadEntity.isPluggable && PackagesManager.isInstalled(downloadEntity.packageName)) {
DownloadButton.ButtonStyle.PLUGIN
} else {
DownloadButton.ButtonStyle.NORMAL
}
}
DownloadStatus.pause,
DownloadStatus.timeout,
DownloadStatus.neterror,
DownloadStatus.subscribe,
DownloadStatus.diskisfull,
DownloadStatus.diskioerror,
DownloadStatus.overflow -> {
buttonStyle = DownloadButton.ButtonStyle.NORMAL
setText(R.string.resume)
}
DownloadStatus.cancel -> {
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation)
}
else -> {
// do nothing
}
}
}
} else {
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation)
}
} else {
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation)
}
}
// 更新正常的条目只有一个apk包
private fun updateNormalItem(
context: Context,
holder: GameViewHolder,
gameEntity: GameEntity,
briefStyle: String?,
isShowRecommendStar: Boolean = false
) {
updateItemViewStatus(holder, briefStyle, gameEntity.columnRecommend, isShowRecommendStar)
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
if (downloadEntity != null) {
if (downloadEntity.isSimulatorGame()) {
if (downloadEntity.status != DownloadStatus.done) {
// 更改进度条和提示文本的状态
changeStatus(context, holder, downloadEntity)
return
}
} else {
// 更改进度条和提示文本的状态
changeStatus(context, holder, downloadEntity)
return
}
}
}
// 更新插件的条目有多个apk包
private fun updatePluginItem(
context: Context,
holder: GameViewHolder,
gameEntity: GameEntity,
briefStyle: String?,
isShowRecommendStar: Boolean = false
) {
val entryMap = gameEntity.getEntryMap()
var downloadEntity: DownloadEntity? = null
if (entryMap.isNotEmpty()) {
val queue = DownloadManager.getInstance().getQueue(gameEntity.name)
downloadEntity = if (queue != null && !queue.isEmpty()) {
entryMap[queue.peek()]
} else {
entryMap[entryMap.keyAt(0)]
}
}
if (downloadEntity == null) {
downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
}
if (downloadEntity != null) {
// 更改进度条和提示文本的状态
changeStatus(context, holder, downloadEntity, gameEntity.getApk().size > 1)
return
}
updateItemViewStatus(holder, briefStyle, gameEntity.columnRecommend, isShowRecommendStar)
}
// 更改进度条和提示文本的状态
private fun changeStatus(
context: Context,
holder: GameViewHolder,
downloadEntity: DownloadEntity,
isMultiVersion: Boolean = false
) {
when (downloadEntity.status) {
DownloadStatus.redirected,
DownloadStatus.downloading -> {
if (isMultiVersion) {
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
val darkMode = (holder.gameDownloadTips?.getTag(R.string.is_dark_mode_on_id) as? Boolean) ?: false
val isDarkModeChanged = DarkModeUtils.isDarkModeOn(context) != darkMode
if (holder.gameDownloadTips?.visibility == View.GONE || holder.gameDownloadTips?.isAnimating == false || isDarkModeChanged) {
holder.gameDownloadTips?.visibility = View.VISIBLE
holder.gameDownloadTips?.setDownloadTipsAnimation(true)
}
holder.gameDownloadTips?.setTag(R.string.is_dark_mode_on_id, DarkModeUtils.isDarkModeOn(context))
} else {
holder.gameDownloadTips?.visibility = View.GONE
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
holder.gameDownloadBtn.progress = (downloadEntity.percent * 10).toInt()
holder.gameDownloadBtn.text = downloadEntity.percent.toString() + "%"
}
}
DownloadStatus.waiting -> {
if (isMultiVersion) {
holder.gameDownloadTips?.visibility = View.VISIBLE
holder.gameDownloadTips?.setDownloadTipsAnimation(false)
}
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.WAITING
holder.gameDownloadBtn.text = context.getString(R.string.waiting)
}
DownloadStatus.pause,
DownloadStatus.timeout,
DownloadStatus.neterror,
DownloadStatus.diskioerror,
DownloadStatus.diskisfull,
DownloadStatus.subscribe,
DownloadStatus.overflow -> {
if (isMultiVersion) {
holder.gameDownloadTips?.visibility = View.VISIBLE
holder.gameDownloadTips?.setDownloadTipsAnimation(false)
}
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
holder.gameDownloadBtn.text = context.getString(R.string.resume)
}
DownloadStatus.done -> {
if (isMultiVersion) {
holder.gameDownloadTips?.visibility = View.VISIBLE
holder.gameDownloadTips?.setDownloadTipsAnimation(false)
}
val xapkStatus = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
if (XapkUnzipStatus.UNZIPPING.name == xapkStatus) {
val percent = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_PERCENT]
holder.gameDownloadBtn.progress = (java.lang.Float.valueOf(percent) * 10).toInt()
holder.gameDownloadBtn.text = "$percent%"
return
} else if (XapkUnzipStatus.FAILURE.name == xapkStatus) {
holder.gameDownloadBtn.setText(R.string.install)
holder.gameDownloadBtn.buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
return
}
holder.gameDownloadBtn.progress = 1000
holder.gameDownloadBtn.setText(R.string.hundred_percent)
}
else -> {
holder.gameDownloadTips?.visibility = View.GONE
}
}
}
private fun updateItemViewStatus(
holder: GameViewHolder,
briefStyle: String?,
recommendStyle: LinkEntity?,
isShowRecommendStar: Boolean = false
) {
holder.gameDownloadTips?.visibility = View.GONE
// 推荐指数优先,现暂时为游戏单详情列表游戏使用
if (isShowRecommendStar && holder.recommendStarInfo != null) {
holder.recommendStarInfo!!.visibility = View.VISIBLE
if (holder.gameRating != null) holder.gameRating!!.visibility = View.GONE
holder.gameDes?.visibility = View.GONE
return
}
// 推荐优先,有推荐内容时不执行下面的 star 和 brief 代码块
if (briefStyle != null && recommendStyle != null && briefStyle.contains("recommend")) {
if (holder.recommendContainer != null) {
holder.recommendContainer!!.visibility = View.VISIBLE
}
if (holder.gameRating != null) holder.gameRating!!.visibility = View.GONE
holder.gameDes?.visibility = View.GONE
holder.recommendTv?.text = recommendStyle.text
if (TextUtils.isEmpty(recommendStyle.icon)) {
holder.recommendIv?.visibility = View.GONE
holder.recommendContainer?.setPadding(6F.dip2px(), 0, 8F.dip2px(), 0)
} else {
holder.recommendIv?.visibility = View.VISIBLE
ImageUtils.display(holder.recommendIv, recommendStyle.icon)
}
return
} else {
if (holder.recommendContainer != null) {
holder.recommendContainer!!.visibility = View.GONE
}
}
if (briefStyle != null && briefStyle.contains("star")) {
if (holder.gameRating != null) holder.gameRating!!.visibility = View.VISIBLE
} else {
if (holder.gameRating != null) holder.gameRating!!.visibility = View.GONE
}
// 缺省情况下回落到游戏简介
if (TextUtils.isEmpty(briefStyle) || briefStyle!!.contains("brief") || briefStyle.contains("recommend")) {
holder.gameDes?.visibility = View.VISIBLE
} else {
holder.gameDes?.visibility = View.GONE
}
}
@JvmStatic
fun setOnClickListener(
context: Context,
downloadBtn: DownloadButton,
gameEntity: GameEntity,
position: Int,
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
entrance: String,
location: String,
sourceEntrance: String = "其他"
) {
setOnClickListener(context, downloadBtn, gameEntity, position, adapter, entrance, sourceEntrance, location, null)
}
@JvmStatic
fun setOnClickListener(
context: Context,
downloadBtn: DownloadButton,
gameEntity: GameEntity,
position: Int,
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
entrance: String,
sourceEntrance: String = "其他",
location: String,
traceEvent: ExposureEvent?,
) {
setOnClickListener(context, downloadBtn, gameEntity, position, adapter, entrance, sourceEntrance, location, traceEvent, null)
}
/**
* @param clickCallback 供那些需要知道点击回调的地方使用,触发具体响应才会回调
*/
@JvmStatic
fun setOnClickListener(
context: Context,
downloadBtn: DownloadButton,
gameEntity: GameEntity,
position: Int,
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
entrance: String,
sourceEntrance: String = "其他",
location: String,
traceEvent: ExposureEvent?,
clickCallback: EmptyCallback?,
) {
setOnClickListener(
context,
downloadBtn,
gameEntity,
position,
adapter,
entrance,
sourceEntrance,
location,
traceEvent,
clickCallback,
null,
null
)
}
/**
* @param allStateClickCallback 供那些需要知道点击回调的地方使用,只要触发点击动作就会回调
*/
@JvmStatic
fun setOnClickListener(
context: Context,
downloadBtn: View,
gameEntity: GameEntity,
position: Int,
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
entrance: String,
sourceEntrance: String = "其他",
location: String,
traceEvent: ExposureEvent?,
clickCallback: EmptyCallback?,
refreshCallback: EmptyCallback?,
allStateClickCallback: EmptyCallback?
) {
// 为 downloadButton 添加游戏实体,供点击的时候上报用
downloadBtn.putObject(gameEntity)
val gamePermissionDialogFragment = (context as AppCompatActivity).supportFragmentManager.findFragmentByTag(
GamePermissionDialogFragment::class.java.name
) as GamePermissionDialogFragment?
gamePermissionDialogFragment?.dismissAllowingStateLoss()
if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) {
downloadBtn.setOnClickListener {
SensorsBridge.trackAdolescentModeDialogShow(
gameId = gameEntity.id,
gameName = gameEntity.name ?: "",
gameType = gameEntity.categoryChinese
)
DialogHelper.showDialog(
context,
"提示",
"当前处于儿童/青少年模式, \n暂不提供游戏下载",
"退出青少年模式",
"关闭",
confirmClickCallback = {
context.startActivity(TeenagerModeActivity.getIntent(context))
SensorsBridge.trackAdolescentModeDialogClick(
buttonName = "退出青少年模式",
gameId = gameEntity.id,
gameName = gameEntity.name ?: "",
gameType = gameEntity.categoryChinese
)
},
cancelClickCallback = {
SensorsBridge.trackAdolescentModeDialogClick(
buttonName = "关闭",
gameId = gameEntity.id,
gameName = gameEntity.name ?: "",
gameType = gameEntity.categoryChinese
)
},
touchOutsideCallback = {
SensorsBridge.trackAdolescentModeDialogClick(
buttonName = "关闭弹窗",
gameId = gameEntity.id,
gameName = gameEntity.name ?: "",
gameType = gameEntity.categoryChinese
)
},
extraConfig = DialogHelper.Config(
centerTitle = true,
centerContent = true
)
)
}
return
}
if (gameEntity.isSpecialDownload()) {
val info = RegionSettingHelper.getGameSpecialDownloadInfo(gameEntity.id) ?: return
downloadBtn.setOnClickListener {
DialogHelper.showDialog(
context,
"提示",
info.hintText,
"前往论坛",
"",
{
if (info.bbsId.isNotBlank()) {
if (info.topId.isNotBlank()) {
val data = hashMapOf(EntranceConsts.KEY_TOP_ID to info.topId)
PageSwitchDataHelper.pushCurrentPageData(data)
}
DirectUtils.directForumDetail(context, info.bbsId, entrance)
}
},
{},
extraConfig = DialogHelper.Config(
centerTitle = true,
centerContent = true
)
)
}
return
}
if (gameEntity.isReservable) {
downloadBtn.setOnClickListener {
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.id)) {
SensorsBridge.trackEvent(
"AppointmentGame",
"game_name",
gameEntity.name ?: "",
"game_id",
gameEntity.id,
"game_type",
gameEntity.categoryChinese,
"source_entrance",
sourceEntrance
)
allStateClickCallback?.onCallback()
CheckLoginUtils.checkLogin(context, entrance) {
clickCallback?.onCallback()
ReservationHelper.reserve(
context,
gameEntity,
sourceEntrance
) {
LogUtils.logReservation(gameEntity, traceEvent)
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}
}
} else {
allStateClickCallback?.onCallback()
clickCallback?.onCallback()
if ("download" == gameEntity.reserveStatus) {
ReservationHelper.showDeleteReservationDialog(context) {
ReservationHelper.deleteReservation(gameEntity) {
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}
}
} else {
ReservationHelper.showCancelReservationDialog(context, {
NewFlatLogUtils.logMyGameCancelReserveDialogClick(
"确定取消",
gameEntity.id,
gameEntity.name ?: ""
)
ReservationHelper.cancelReservation(gameEntity) {
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}
}, object : CancelListener {
override fun onCancel() {
NewFlatLogUtils.logMyGameCancelReserveDialogClick(
"关闭弹窗",
gameEntity.id,
gameEntity.name ?: ""
)
}
})
}
}
}
return
}
val gameH5Download = RegionSettingHelper.getGameH5DownloadByGameId(gameEntity.id)
if (gameH5Download != null) {
downloadBtn.setOnClickListener {
DialogUtils.showGameH5DownloadDialog(context, gameEntity, gameH5Download)
}
return
}
if (gameEntity.isMiniGame()) {
downloadBtn.setOnClickListener {
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
clickCallback?.onCallback()
allStateClickCallback?.onCallback()
}
return
}
if (gameEntity.getApk().size == 0 && gameEntity.h5Link != null) {
downloadBtn.setOnClickListener {
allStateClickCallback?.onCallback()
val linkEntity = gameEntity.h5Link
val isPlay = "play" == linkEntity!!.type // 是否为开始玩
if (isPlay) {
HistoryHelper.insertGameEntity(gameEntity)
}
val i = WebActivity.getIntentForWebGame(
context,
gameEntity.h5Link!!.link,
gameEntity.name,
isPlay,
linkEntity.closeButton
)
context.startActivity(i)
}
} else if (gameEntity.getApk().size == 1) {
downloadBtn.setOnClickListener {
val clickRunnable = EmptyCallback {
allStateClickCallback?.onCallback()
clickCallback?.onCallback()
onNormalClick(
context,
downloadBtn,
gameEntity,
position,
adapter,
entrance,
location,
traceEvent,
refreshCallback
)
}
// 启动不需要请求存储权限
if (downloadBtn is DownloadButton && downloadBtn.text == context.getString(R.string.launch)) {
clickRunnable.onCallback()
} else {
PermissionHelper.checkStoragePermissionBeforeAction(
context,
gameEntity.id,
gameEntity.name ?: "",
gameEntity.categoryChinese,
gameEntity.getApk().firstOrNull()?.format,
clickRunnable
)
}
}
} else {
downloadBtn.setOnClickListener { view: View ->
allStateClickCallback?.onCallback()
clickCallback?.onCallback()
DownloadChainBuilder().apply {
addHandler(GamePermissionHandler())
addHandler(CheckStoragePermissionHandler())
addHandler(VersionNumberHandler())
}
.setProcessEndCallback { _, _ ->
DownloadDialog.showDownloadDialog(view.context, gameEntity, traceEvent, entrance, location)
}
.buildHandlerChain()
?.handleRequest(
context,
gameEntity,
GameUtils.shouldPerformAsVGame(gameEntity)
)
}
}
}
@JvmOverloads
fun onNormalClick(
context: Context,
downloadBtn: View?,
gameEntity: GameEntity,
position: Int,
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
entrance: String,
location: String,
traceEvent: ExposureEvent? = null,
refreshCallback: EmptyCallback? = null
) {
val str = if (downloadBtn is DownloadButton) downloadBtn.text else context.getString(R.string.download)
if (gameEntity.getApk().isEmpty()) return
val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return
val shouldPerformAsVGame = GameUtils.shouldPerformAsVGame(gameEntity)
if (str == context.getString(R.string.download)) {
DownloadChainBuilder().apply {
addHandler(UnsupportedFeatureHandler())
addHandler(UpdateNewSimulatorHandler())
addHandler(GamePermissionHandler())
addHandler(BrowserInstallHandler())
addHandler(PackageCheckHandler())
addHandler(DownloadDialogHelperHandler())
addHandler(OverseaDownloadHandler())
addHandler(LandPageAddressHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback { asVGame, isSubscribe ->
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
?.handleRequest(context, gameEntity, shouldPerformAsVGame)
DataLogUtils.uploadGameLog(context, gameEntity.id, gameEntity.name, entrance)
} else if (str == context.getString(R.string.attempt)) {
DownloadChainBuilder().apply {
addHandler(UnsupportedFeatureHandler())
addHandler(UpdateNewSimulatorHandler())
addHandler(GamePermissionHandler())
addHandler(BrowserInstallHandler())
addHandler(PackageCheckHandler())
addHandler(DownloadDialogHelperHandler())
addHandler(VersionNumberHandler())
addHandler(LandPageAddressHandler())
addHandler(OverseaDownloadHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback { asVGame, isSubscribe ->
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
?.handleRequest(context, gameEntity, shouldPerformAsVGame)
DataLogUtils.uploadGameLog(context, gameEntity.id, gameEntity.name, entrance)
} else if (str == context.getString(R.string.smooth)) {
DownloadChainBuilder().apply {
addHandler(UnsupportedFeatureHandler())
addHandler(GamePermissionHandler())
addHandler(PackageCheckHandler())
addHandler(DownloadDialogHelperHandler())
addHandler(VersionNumberHandler())
addHandler(LandPageAddressHandler())
addHandler(OverseaDownloadHandler())
addHandler(CheckStoragePermissionHandler())
addHandler(ValidateVSpaceHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback { asVGame, isSubscribe ->
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
?.handleRequest(context, gameEntity, shouldPerformAsVGame)
} else if (str.contains("")) {
if (gameEntity.pluggableCollection != null) {
DownloadDialog.showDownloadDialog(context, gameEntity, traceEvent, entrance, location)
} else {
DownloadChainBuilder().apply {
addHandler(DownloadDialogHelperHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback { _, isSubscribe ->
plugin(context, gameEntity, downloadBtn, entrance, location, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
?.handleRequest(context, gameEntity, shouldPerformAsVGame)
}
} else if (str == context.getString(R.string.install)) {
val downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apk.url)
com.gh.gamecenter.common.utils.NewFlatLogUtils.logGameInstall(
gameId = downloadEntity?.gameId ?: "",
gameName = downloadEntity?.name ?: "",
trigger = "主动安装"
)
SensorsBridge.trackInstallGameClick(
gameId = downloadEntity?.gameId ?: "",
gameName = downloadEntity?.name ?: "",
action = "主动安装"
)
if (gameEntity.simulator != null) {
val isInstalled =
PackageUtils.isInstalledFromAllPackage(context, gameEntity.simulator!!.apk!!.packageName)
val isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(context)
val isInstalledOldSimulator = SimulatorGameManager.isOldSimulatorInstalled(context)
var simulator = gameEntity.simulator
val newSimulator = Config.getNewSimulatorEntitySetting()
if (!isInstalledOldSimulator && newSimulator != null && newSimulator.active) {//在没有安装旧的模拟器且有配置新版模拟器 才使用新版模拟器 否则还是用以前旧的
simulator = newSimulator
}
if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(gameEntity) && !isInstalled && !isInstalledNewSimulator) {
SimulatorDownloadManager.getInstance().showDownloadDialog(
context,
simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH,
gameEntity.id,
gameEntity.name!!,
gameEntity.categoryChinese,
null
)
return
}
}
install(context, gameEntity, position, adapter, refreshCallback)
} else if (str == context.getString(R.string.launch)) {
//启动模拟器游戏
if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
if (NewSimulatorGameManager.shouldShowUpdateNewSimulatorAlert(context)) {
NewSimulatorGameManager.showUpdateNewsSimulator(context, gameEntity, null)
return
}
val downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk().firstOrNull()?.url)
if (downloadEntity != null) {
val file = File(downloadEntity.path)
if (!file.exists()) {
download(
context = context,
gameEntity = gameEntity,
downloadBtn = downloadBtn,
entrance = entrance,
location = location,
asVGame = false,
isSubscribe = false,
traceEvent = traceEvent
)
return
}
NewFlatLogUtils.logSimulatorGameCardClick("启动")
SimulatorGameManager.launchSimulatorGame(downloadEntity, gameEntity)
}
return
}
PackageLauncher.launch(context, gameEntity)
} else if (str == context.getString(R.string.update)) {
if (shouldPerformAsVGame) {
VHelper.updateOrReDownload(gameEntity)
return
}
DownloadChainBuilder()
.apply {
addHandler(LandPageAddressHandler())
}.setProcessEndCallback { asVGame, _ ->
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk) {
DialogUtils.checkDownload(
context,
apk.size,
gameEntity.id,
gameEntity.name,
gameEntity.categoryChinese
) { isSubscribe: Boolean ->
update(context, gameEntity, entrance, location, asVGame, isSubscribe, traceEvent)
}
}
}
.buildHandlerChain()
?.handleRequest(context, gameEntity, false)
} else {
var downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
// 尝试从 gameEntity 里找已绑定的 downloadEntity
if (downloadEntity == null) {
downloadEntity = gameEntity.getEntryMap().getOrDefault(gameEntity.getUniquePlatform(), null)
}
if (downloadEntity != null) {
val xapkStatus = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
if (XapkUnzipStatus.SUCCESS.name == xapkStatus && isInstalling(downloadEntity.path)) {// 安装过程中避免重复点击
return
}
if (XapkUnzipStatus.UNZIPPING.name == xapkStatus) {
cancelUnzipTask(downloadEntity)
return
}
when (str) {
context.getString(R.string.resume) -> {
DownloadManager.getInstance().resume(downloadEntity, false)
}
context.getString(R.string.waiting) -> {
Utils.toast(context, "最多只能同时下载三个任务,请稍等")
}
else -> {
DownloadManager.getInstance().pause(downloadEntity.url)
}
}
}
}
}
//下载
private fun download(
context: Context,
gameEntity: GameEntity,
downloadBtn: View?,
entrance: String,
location: String,
asVGame: Boolean,
isSubscribe: Boolean,
traceEvent: ExposureEvent?
) {
if (gameEntity.getApk().isEmpty()) return
val msg = FileUtils.isCanDownload(context, gameEntity.getApk().firstOrNull()?.size ?: "")
if (TextUtils.isEmpty(msg)) {
DownloadManager.createDownload(
context,
gameEntity,
asVGame,
entrance,
location,
isSubscribe,
traceEvent
)
ToastUtils.toast(gameEntity.name + "已加入下载队列")
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
val toast = context.getString(R.string.unsupported_browser_install_hint)
AppExecutor.uiExecutor.executeWithDelay({
ToastUtils.toast(toast)
}, 1000)
}
if (downloadBtn is DownloadButton) {
downloadBtn.text = "0%"
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
}
DeviceRemindDialog.showDeviceRemindDialog(context, gameEntity)
} else {
Utils.toast(context, msg)
}
}
//插件化
private fun plugin(
context: Context,
gameEntity: GameEntity,
downloadBtn: View?,
entrance: String,
location: String,
isSubscribe: Boolean,
traceEvent: ExposureEvent?
) {
val msg = FileUtils.isCanDownload(context, gameEntity.getApk().firstOrNull()?.size ?: "")
if (TextUtils.isEmpty(msg)) {
DownloadManager.createDownload(context, gameEntity, false, entrance, location, isSubscribe, traceEvent)
ToastUtils.toast(gameEntity.name + "已加入下载队列")
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
val toast = context.getString(R.string.unsupported_browser_install_hint)
AppExecutor.uiExecutor.executeWithDelay({
ToastUtils.toast(toast)
}, 1000)
}
if (downloadBtn is DownloadButton) {
downloadBtn.setText(R.string.downloading)
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN
}
} else {
Utils.toast(context, msg)
}
}
//安装
private fun install(
context: Context,
gameEntity: GameEntity,
position: Int,
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
refreshCallback: EmptyCallback?
) {
val apkEntity = gameEntity.getApk().firstOrNull()
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
if (downloadEntity != null) {
val path = downloadEntity.path
when {
FileUtils.isEmptyFile(path) -> {
Utils.toast(context, R.string.install_failure_hint)
DownloadManager.getInstance().cancel(downloadEntity.url)
gameEntity.getEntryMap().remove(apkEntity?.getPlatform())
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}
PackageUtils.isCanPluggable(apkEntity) -> {
DialogHelper.showPluginDialog(
context,
pluginDesc = gameEntity.pluginDesc,
gameId = gameEntity.id,
gameName = gameEntity.name ?: "",
gameType = gameEntity.categoryChinese,
platform = gameEntity.platform ?: ""
) {
PackageInstaller.uninstall(context, path)
}
}
else -> {
PackageInstaller.install(context, downloadEntity)
}
}
}
}
//更新
private fun update(
context: Context,
gameEntity: GameEntity,
entrance: String,
location: String,
asVGame: Boolean,
isSubscribe: Boolean,
traceEvent: ExposureEvent?
) {
// 执行更新操作前,先清理历史下载任务,避免冲突
if (gameEntity.getApk().size == 1 && !asVGame) {
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
if (downloadEntity != null) {
DownloadManager.getInstance().cancel(downloadEntity.url)
}
}
DownloadManager.createDownload(context, gameEntity, asVGame, entrance, location, isSubscribe, traceEvent)
}
}