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