From a4c323b5e09eb96829146ced45ae3da499af950b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E5=AD=90=E7=BB=B4?= Date: Thu, 18 May 2023 17:59:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=2032=E4=BD=8D=E7=95=85=E7=8E=A9=E6=B8=B8?= =?UTF-8?q?=E6=88=8F=E4=B8=8B=E8=BD=BD=E6=B5=81=E7=A8=8B=E2=80=94=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E7=AB=AF=20https://jira.shanqu.cc/browse/CWZS-36?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/gh/common/DefaultJsApi.kt | 2 +- .../util/ArchiveDownloadButtonHelper.kt | 6 +- .../com/gh/common/util/DownloadObserver.kt | 2 +- .../java/com/gh/download/DownloadManager.java | 1 + .../com/gh/gamecenter/entity/AppEntity.kt | 2 + app/src/main/java/com/gh/vspace/VHelper.kt | 174 +++++++--- .../com/gh/vspace/VSpace32DialogFragment.kt | 301 ++++++++++++++++++ .../com/gh/vspace/VSpaceDialogFragment.kt | 165 +++++++--- .../gh/vspace/VSpaceUpdate32DialogFragment.kt | 291 +++++++++++++++++ .../drawable/bg_vspace_dialog_completed.xml | 8 + app/src/main/res/drawable/ic_completed.xml | 10 + app/src/main/res/layout/dialog_vspace.xml | 13 +- app/src/main/res/layout/dialog_vspace_32.xml | 144 +++++++++ .../res/layout/dialog_vspace_update_32.xml | 129 ++++++++ .../gamecenter/common/constant/Constants.java | 1 + .../gh/gamecenter/feature/entity/ApkEntity.kt | 4 +- 16 files changed, 1164 insertions(+), 89 deletions(-) create mode 100644 app/src/main/java/com/gh/vspace/VSpace32DialogFragment.kt create mode 100644 app/src/main/java/com/gh/vspace/VSpaceUpdate32DialogFragment.kt create mode 100644 app/src/main/res/drawable/bg_vspace_dialog_completed.xml create mode 100644 app/src/main/res/drawable/ic_completed.xml create mode 100644 app/src/main/res/layout/dialog_vspace_32.xml create mode 100644 app/src/main/res/layout/dialog_vspace_update_32.xml diff --git a/app/src/main/java/com/gh/common/DefaultJsApi.kt b/app/src/main/java/com/gh/common/DefaultJsApi.kt index 246fa81031..aa04efacce 100644 --- a/app/src/main/java/com/gh/common/DefaultJsApi.kt +++ b/app/src/main/java/com/gh/common/DefaultJsApi.kt @@ -209,7 +209,7 @@ class DefaultJsApi( runOnUiThread { // 若畅玩列表中安装了,优先启动畅玩游戏 if (VHelper.isInstalled(packageName)) { - if (!VHelper.showDialogIfVSpaceIsNeeded(context, "", "")) { + if (!VHelper.showDialogIfVSpaceIsNeeded(context, "", "", "")) { VHelper.launch(context, packageName) } } else { diff --git a/app/src/main/java/com/gh/common/util/ArchiveDownloadButtonHelper.kt b/app/src/main/java/com/gh/common/util/ArchiveDownloadButtonHelper.kt index cb501d40ed..83c847ccbe 100644 --- a/app/src/main/java/com/gh/common/util/ArchiveDownloadButtonHelper.kt +++ b/app/src/main/java/com/gh/common/util/ArchiveDownloadButtonHelper.kt @@ -49,7 +49,7 @@ object ArchiveDownloadButtonHelper { downloadBtn.setOnClickListener { when { // 检查是否已安装畅玩助手 - !VHelper.isVSpaceInstalled(context) -> showVspaceTipDialog(context, gameEntity) + !VHelper.isVSpaceInstalled(context) -> showVSpaceTipDialog(context, gameEntity) // 检查是否已安装游戏 !VHelper.isInstalled(packageName) -> { // 检查游戏是否在安装中 @@ -82,7 +82,7 @@ object ArchiveDownloadButtonHelper { } } - private fun showVspaceTipDialog(context: Context, gameEntity: GameEntity?) { + private fun showVSpaceTipDialog(context: Context, gameEntity: GameEntity?) { NewFlatLogUtils.logCloudArchiveVSpaceDownloadDialogShow() DialogHelper.showDialog( context, @@ -92,7 +92,7 @@ object ArchiveDownloadButtonHelper { R.string.cancel.toResString(), { NewFlatLogUtils.logCloudArchiveVSpaceDownloadDialogClick(R.string.archive_vspace_dialog_confirm.toResString()) - VHelper.showVspaceDialog(context, gameEntity) + VHelper.showVSpaceDialog(context, gameEntity) }, { NewFlatLogUtils.logCloudArchiveVSpaceDownloadDialogClick(R.string.cancel.toResString()) diff --git a/app/src/main/java/com/gh/common/util/DownloadObserver.kt b/app/src/main/java/com/gh/common/util/DownloadObserver.kt index 59fd7e299c..3c17681f91 100644 --- a/app/src/main/java/com/gh/common/util/DownloadObserver.kt +++ b/app/src/main/java/com/gh/common/util/DownloadObserver.kt @@ -277,7 +277,7 @@ object DownloadObserver { val downloadType = downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) // 是否是自动安装 val isAutoInstall = SPUtils.getBoolean(Constants.SP_AUTO_INSTALL, true) - if (downloadType == Constants.SIMULATOR_DOWNLOAD || isAutoInstall) { + if (downloadType != Constants.VSPACE_32_DOWNLOAD_ONLY && (downloadType == Constants.SIMULATOR_DOWNLOAD || isAutoInstall)) { if (FileUtils.isEmptyFile(downloadEntity.path)) { Utils.toast(mApplication, R.string.install_failure_hint) downloadManager.cancel(downloadEntity.url) diff --git a/app/src/main/java/com/gh/download/DownloadManager.java b/app/src/main/java/com/gh/download/DownloadManager.java index 0404c8c7ff..e8011592e5 100644 --- a/app/src/main/java/com/gh/download/DownloadManager.java +++ b/app/src/main/java/com/gh/download/DownloadManager.java @@ -341,6 +341,7 @@ public class DownloadManager implements DownloadStatusListener { ExtensionsKt.addMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE, Constants.SMOOTH_GAME); ExtensionsKt.addMetaExtra(downloadEntity, DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200"); ExtensionsKt.addMetaExtra(downloadEntity, VHelper.KEY_REQUIRED_G_APPS, gameEntity.getGAppsSwitch()); + ExtensionsKt.addMetaExtra(downloadEntity, VHelper.KEY_BIT, apkEntity.getBit()); SensorsBridge.trackEvent("HaloFunGameDownloadClick", "game_name", gameEntity.getName(), diff --git a/app/src/main/java/com/gh/gamecenter/entity/AppEntity.kt b/app/src/main/java/com/gh/gamecenter/entity/AppEntity.kt index 4834cb509a..a7cfe098db 100644 --- a/app/src/main/java/com/gh/gamecenter/entity/AppEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/entity/AppEntity.kt @@ -31,6 +31,8 @@ class AppEntity( * EVERY_TIME_OPEN(每次打开) */ var alert: String? = null, + // 关联64位更新 + var relation: AppEntity? = null ) : Parcelable { fun isAlertEveryTime() = alert == "EVERY_TIME_OPEN" diff --git a/app/src/main/java/com/gh/vspace/VHelper.kt b/app/src/main/java/com/gh/vspace/VHelper.kt index aaad0f3688..fa07dfa31b 100644 --- a/app/src/main/java/com/gh/vspace/VHelper.kt +++ b/app/src/main/java/com/gh/vspace/VHelper.kt @@ -78,8 +78,12 @@ object VHelper { "https://dev-and-static.ghzs.com/game/apk/smooth_google/google_play_services.zip" const val G_APPS_DOWNLOAD_URL = "https://and-static.ghzs.com/game/apk/smooth_google/google_play_services.zip" + // 畅玩游戏位数 + const val KEY_BIT = "bit" + const val LOG_TAG = "VSPACE" const val DEFAULT_VSPACE_PACKAGENAME = "com.lg.vspace" + const val VSPACE_32BIT_PACKAGENAME = "$DEFAULT_VSPACE_PACKAGENAME.addon" const val PLATFORM_V = "畅玩版" private val mDelegateManager by lazy { VirtualAppManager.get() } @@ -90,7 +94,8 @@ object VHelper { private val mVGameDao by lazy { VGameDatabase.instance.vGameDao() } private var mVGameSnapshotList = arrayListOf() - private var mUpdateEntity: AppEntity? = null + private var m64UpdateEntity: AppEntity? = null + private var m32UpdateEntity: AppEntity? = null private var mIsInitialized = false // 是否已初始化 private var mIsServiceConnected = false // AIDL 服务是否成功连接,不可作为 AIDL 仍然可用的依据 @@ -108,6 +113,9 @@ object VHelper { // 因为显示下载畅玩弹窗而处于挂起状态的游戏回调,供安装完畅玩组件后自动下载用 private var mPendingDownloadCallback: (() -> Unit)? = null + // 供安装完畅玩组件判断畅玩游戏位数使用 + private var mBit = "" + // 批量安装的 map k: 包名, v: 文件 private var mBatchInstallMap = hashMapOf() @@ -136,12 +144,20 @@ object VHelper { private val mPackageObserver by lazy { PackageObserver.PackageChangeListener { val vaConfig = Config.getVSettingEntity()?.va ?: return@PackageChangeListener - val isVSpace = - it.packageName == vaConfig.arch32?.packageName || it.packageName == vaConfig.arch64?.packageName + val isVSpace32 = it.packageName == vaConfig.arch32?.packageName + val isVSpace64 = it.packageName == vaConfig.arch64?.packageName - if (!isVSpace) return@PackageChangeListener + if (!isVSpace64 && !isVSpace32) return@PackageChangeListener + + // 需要安装32位畅玩时跳过64位畅玩安装成功的回调 + val skip64VSpaceInstalled = mBit == "32" && isVSpace64 && !PackageUtils.isInstalledFromAllPackage( + HaloApp.getInstance(), + vaConfig.arch32?.packageName + ) if (it.type == EBPackage.TYPE_INSTALLED) { + if (skip64VSpaceInstalled) return@PackageChangeListener + // 帮用户启动因为没有安装畅玩组件而没法进行的下载任务 // 因为有可能回调时还在后台,但还要弹窗什么的,所以可能会闪退?先 try catch 一下看看 try { @@ -151,11 +167,14 @@ object VHelper { } mPendingDownloadCallback = null + mBit = "" } if (!isVIsUsed()) return@PackageChangeListener if (it.type == EBPackage.TYPE_INSTALLED) { + if (skip64VSpaceInstalled) return@PackageChangeListener + // 即时调用大概率调不起来,我也不知道为什么,只能延迟大法了 AppExecutor.uiExecutor.executeWithDelay({ connectService() @@ -191,8 +210,15 @@ object VHelper { connectService(shouldCheckUpdate = true) } - // 检查畅玩助手组件更新 - getVSpaceUpdate(config.arch64) + // 检查畅玩助手64位组件更新 + getVSpaceUpdate(config.arch64, true) + } + + if (config?.arch32 != null + && PackageUtils.isInstalledFromAllPackage(context, config.arch32.packageName) + ) { + // 检查畅玩助手32位组件更新 + getVSpaceUpdate(config.arch32, false) } PackageObserver.registerPackageChangeChangeListener(mPackageObserver) } @@ -357,8 +383,13 @@ object VHelper { /** * 显示下载畅玩空间弹窗 */ - fun showVspaceDialog(context: Context, gameEntity: GameEntity?) { - VSpaceDialogFragment.showDownloadDialog(context, getVSpaceDownloadEntity(false), gameEntity) + fun showVSpaceDialog(context: Context, gameEntity: GameEntity?) { + VSpaceDialogFragment.showDownloadDialog( + context, + appEntity64 = getVSpaceDownloadEntity(false), + appEntity32 = getVSpaceDownloadEntity(forUpdate = false, false), + gameEntity = gameEntity + ) } /** @@ -445,32 +476,75 @@ object VHelper { fun validateVSpaceBeforeAction(context: Context, gameEntity: GameEntity?, callback: () -> Unit) { // 仅下载类型为畅玩的类型才执行判断 if (gameEntity == null || gameEntity.isVGame()) { - if (showDialogIfVSpaceIsNeeded(context, gameEntity?.id ?: "", gameEntity?.name ?: "")) { + if (showDialogIfVSpaceIsNeeded( + context, + gameEntity?.id ?: "", + gameEntity?.name ?: "", + gameEntity?.getApk()?.get(0)?.bit ?: "" + ) + ) { + mBit = gameEntity?.getApk()?.get(0)?.bit ?: "" mPendingDownloadCallback = callback return } val vaConfig64 = Config.getVSettingEntity()?.va?.arch64 - val installedSpaceVersionCode = PackageUtils.getVersionCodeByPackageName(vaConfig64?.packageName) + val vaConfig32 = Config.getVSettingEntity()?.va?.arch32 + val installed64SpaceVersionCode = PackageUtils.getVersionCodeByPackageName(vaConfig64?.packageName) + val installed32SpaceVersionCode = PackageUtils.getVersionCodeByPackageName(vaConfig32?.packageName) // 检查更新 - val containsUpdate = shouldShowVSpaceUpdate(mUpdateEntity, installedSpaceVersionCode) + val contains64Update = shouldShowVSpaceUpdate(m64UpdateEntity, installed64SpaceVersionCode) + val contains32Update = if (gameEntity?.getApk()?.get(0)?.bit == "32") shouldShowVSpaceUpdate( + m32UpdateEntity, + installed32SpaceVersionCode + ) else false - if (containsUpdate) { - val dialogType = if (mUpdateEntity!!.isAlertEveryTime()) "强制更新" else "提示更新" + var containsRelated64Update = false + + if (contains32Update) { + // 检查关联64位是否需要更新 + if (m32UpdateEntity?.relation != null) { + containsRelated64Update = + shouldShowVSpaceUpdate(m32UpdateEntity?.relation, installed64SpaceVersionCode) + } + } + + if (contains32Update || contains64Update) { + val updateEntity = if (contains64Update) m64UpdateEntity else m32UpdateEntity + val dialogType = if (updateEntity!!.isAlertEveryTime()) "强制更新" else "提示更新" NewFlatLogUtils.logHaloFunEvent("halo_fun_update_dialog_show") - SPUtils.setString(KEY_LAST_ALERT_UPDATE_URL, mUpdateEntity!!.url + mUpdateEntity!!.alert) + SPUtils.setString(KEY_LAST_ALERT_UPDATE_URL, updateEntity.url + updateEntity.alert) DialogHelper.showDialog( context = context, title = "服务工具更新提示", - content = mUpdateEntity!!.content.toString(), + content = updateEntity.content.toString(), cancelText = "立即更新", confirmText = "继续游戏", cancelClickCallback = { NewFlatLogUtils.logHaloFunUpdateDialogClick(dialogType, "立即更新") + val downloadEntity64 = getVSpaceDownloadEntity(forUpdate = true, is64Bit = true) + val downloadEntity32 = getVSpaceDownloadEntity(forUpdate = true, is64Bit = false) + val appEntity64 = + if (contains32Update && containsRelated64Update) { + // 对比32位关联的64位更新与64位单独更新推送的版本号 + if (contains64Update && downloadEntity64.versionCode > (downloadEntity32.relation?.versionCode + ?: 0) + ) { + downloadEntity64 + } else { + downloadEntity32.relation + } + } else if (contains64Update) { + downloadEntity64 + } else { + null + } + val appEntity32 = if (contains32Update) downloadEntity32 else null VSpaceDialogFragment.showDownloadDialog( context, - getVSpaceDownloadEntity(true), + appEntity64, + appEntity32, gameEntity, autoDownload = true, isUpdate = true @@ -482,7 +556,7 @@ object VHelper { }, extraConfig = DialogHelper.Config(centerTitle = true), uiModificationCallback = { - if (mUpdateEntity!!.isAlertEveryTime()) { + if (updateEntity.isAlertEveryTime()) { it.confirmTv.visibility = View.GONE it.cancelTv.setTextColor(R.color.theme_font.toColor(context)) } @@ -549,7 +623,13 @@ object VHelper { ) { Utils.log(LOG_TAG, "尝试安装新游戏 ${downloadEntity.path}") - if (showDialogIfVSpaceIsNeeded(context, downloadEntity.gameId, downloadEntity.name)) return + if (showDialogIfVSpaceIsNeeded( + context, + downloadEntity.gameId, + downloadEntity.name, + downloadEntity.getMetaExtra(KEY_BIT) + ) + ) return // 当且仅当 // 1. 全局安装完成启动游戏开关打开 @@ -1037,7 +1117,7 @@ object VHelper { * 如果已安装或配置为空返回 true * 未安装的情况下会弹弹窗 */ - fun showDialogIfVSpaceIsNeeded(context: Context, gameId: String, gameName: String): Boolean { + fun showDialogIfVSpaceIsNeeded(context: Context, gameId: String, gameName: String, bit: String): Boolean { Utils.log(LOG_TAG, "检测是否已安装畅玩空间") val vaConfig = Config.getVSettingEntity()?.va @@ -1048,33 +1128,50 @@ object VHelper { return true } - // TODO 检测 32 位 - if (!PackageUtils.isInstalledFromAllPackage(context, vaConfig.arch64?.packageName)) { - VSpaceDialogFragment.showDownloadDialog( - context, - getVSpaceDownloadEntity(false), - gameId = gameId, - gameName = gameName - ) - Utils.log(LOG_TAG, "显示下载畅玩空间弹窗") - return true + val is64VSpaceInstalled = PackageUtils.isInstalledFromAllPackage(context, vaConfig.arch64?.packageName) + val is32VSpaceInstalled = PackageUtils.isInstalledFromAllPackage(context, vaConfig.arch32?.packageName) + when { + !is64VSpaceInstalled -> { + VSpaceDialogFragment.showDownloadDialog( + context, + appEntity64 = getVSpaceDownloadEntity(false), + appEntity32 = getVSpaceDownloadEntity(forUpdate = false, false), + gameId = gameId, + gameName = gameName, + bit = bit + ) + Utils.log(LOG_TAG, "显示下载64位畅玩空间弹窗") + return true + } + + bit == "32" && !is32VSpaceInstalled -> { + VSpace32DialogFragment.showDownloadDialog( + context, + getVSpaceDownloadEntity(forUpdate = false, false), + gameId = gameId, + gameName = gameName + ) + Utils.log(LOG_TAG, "显示下载32位畅玩空间弹窗") + return true + } } Utils.log(LOG_TAG, "畅玩空间已安装") return false } - private fun getVSpaceDownloadEntity(forUpdate: Boolean): AppEntity { + private fun getVSpaceDownloadEntity(forUpdate: Boolean, is64Bit: Boolean = true): AppEntity { return if (!forUpdate) { val appEntity = AppEntity() - val vaConfig64 = Config.getVSettingEntity()?.va?.arch64 - appEntity.versionCode = vaConfig64?.versionCode ?: 0 - appEntity.version = vaConfig64?.versionName - appEntity.url = vaConfig64?.url + val vaConfig = + if (is64Bit) Config.getVSettingEntity()?.va?.arch64 else Config.getVSettingEntity()?.va?.arch32 + appEntity.versionCode = vaConfig?.versionCode ?: 0 + appEntity.version = vaConfig?.versionName + appEntity.url = vaConfig?.url appEntity } else { - mUpdateEntity!! + if (is64Bit) m64UpdateEntity!! else m32UpdateEntity!! } } @@ -1207,7 +1304,7 @@ object VHelper { * 获取畅玩空间更新 */ @SuppressLint("CheckResult") - private fun getVSpaceUpdate(config: VSetting.VaArch) { + private fun getVSpaceUpdate(config: VSetting.VaArch, is64Bit: Boolean) { val installedVersionName = PackageUtils.getVersionNameByPackageName(config.packageName) val installedVersionCode = PackageUtils.getVersionCodeByPackageName(config.packageName) @@ -1217,7 +1314,7 @@ object VHelper { .subscribeOn(Schedulers.io()) .subscribe(object : BiResponse() { override fun onSuccess(data: AppEntity) { - mUpdateEntity = data + if (is64Bit) m64UpdateEntity = data else m32UpdateEntity = data } }) } @@ -1251,8 +1348,9 @@ object VHelper { if (updateEntity.isAlertEveryTime()) return true + val lastAlertUpdateUrl = updateEntity.url + updateEntity.alert if (updateEntity.isAlertOnceADay() - && SPUtils.getString(KEY_LAST_ALERT_UPDATE_URL) != (mUpdateEntity!!.url + mUpdateEntity!!.alert) + && SPUtils.getString(KEY_LAST_ALERT_UPDATE_URL) != lastAlertUpdateUrl ) { return true } diff --git a/app/src/main/java/com/gh/vspace/VSpace32DialogFragment.kt b/app/src/main/java/com/gh/vspace/VSpace32DialogFragment.kt new file mode 100644 index 0000000000..343fdf4b27 --- /dev/null +++ b/app/src/main/java/com/gh/vspace/VSpace32DialogFragment.kt @@ -0,0 +1,301 @@ +package com.gh.vspace + +import android.annotation.SuppressLint +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import com.gh.common.exposure.ExposureUtils +import com.gh.common.exposure.ExposureUtils.DownloadType.DOWNLOAD +import com.gh.common.exposure.ExposureUtils.DownloadType.UPDATE +import com.gh.common.util.DataCollectionUtils +import com.gh.common.util.DirectUtils +import com.gh.common.util.NewFlatLogUtils +import com.gh.common.util.PackageInstaller +import com.gh.common.util.PackageUtils +import com.gh.gamecenter.feature.view.DownloadButton +import com.gh.download.DownloadManager +import com.gh.gamecenter.R +import com.gh.gamecenter.common.base.activity.BaseActivity +import com.gh.gamecenter.common.base.fragment.BaseDraggableDialogFragment +import com.gh.gamecenter.common.constant.Constants +import com.gh.gamecenter.common.constant.EntranceConsts +import com.gh.gamecenter.common.utils.* +import com.gh.gamecenter.core.AppExecutor +import com.gh.gamecenter.databinding.DialogVspace32Binding +import com.gh.gamecenter.entity.AppEntity +import com.gh.gamecenter.feature.entity.GameEntity +import com.halo.assistant.HaloApp +import com.lightgame.download.DataWatcher +import com.lightgame.download.DownloadConfig +import com.lightgame.download.DownloadEntity +import com.lightgame.download.DownloadStatus.* +import com.lightgame.utils.AppManager + +class VSpace32DialogFragment : BaseDraggableDialogFragment() { + + private var mAppEntity: AppEntity? = null + private var mGameId: String = "" + private var mGameName: String = "" + private val mDownloadUrl by lazy { mAppEntity?.url ?: "" } + private val mBinding by lazy { DialogVspace32Binding.inflate(layoutInflater) } + private val mDataWatcher = object : DataWatcher() { + override fun onDataChanged(downloadEntity: DownloadEntity) { + if (downloadEntity.url == mDownloadUrl && isAdded) { + updateDownloadButton(downloadEntity) + } + } + + override fun onDataInit(downloadEntity: DownloadEntity) { + onDataChanged(downloadEntity) + } + } + + override fun getRootView(): View = mBinding.root + override fun getDragCloseView(): View = mBinding.dragClose + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + mAppEntity = arguments?.get(KEY_APP_ENTITY_32) as AppEntity + mGameId = arguments?.getString(EntranceConsts.KEY_GAME_ID) ?: "" + mGameName = arguments?.getString(EntranceConsts.KEY_GAME_NAME) ?: "" + } + + @SuppressLint("ClickableViewAccessibility") + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return mBinding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + val mViewModel = viewModelProvider() + mViewModel.packageLiveData.observe(this) { + if (it.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) { + dismissAllowingStateLoss() + } + } + + val downloadSnapshot = DownloadManager.getInstance() + .getDownloadEntitySnapshotByPackageName(VHelper.VSPACE_32BIT_PACKAGENAME) + mBinding.downloadBtn.text = if (downloadSnapshot?.status == done) "安装" else "下载" + mBinding.downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL + mBinding.descTv.text = "《$mGameName》需安装完整的畅玩服务组件,安装后即可给您带来急速的畅玩体验~" + mBinding.privacyPolicyTv.setOnClickListener { + NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_privacy_click") + DirectUtils.directToWebView(requireContext(), Constants.SMOOTH_GAME_PRIVACY_POLICY_ADDRESS) + } + + + mBinding.downloadBtn.setOnClickListener { + if (downloadSnapshot?.status == done) { + PackageInstaller.install(requireContext(), downloadSnapshot) + SensorsBridge.trackEvent("HaloFunInstallButtonClick") + } else { + val downloadEntity = DownloadEntity() + + val name = "畅玩助手V" + mAppEntity?.version + "(32位)" + val downloadId = PackageInstaller.createDownloadId(name) + + downloadEntity.url = mDownloadUrl + downloadEntity.name = name + downloadEntity.platform = "官方版" + downloadEntity.gameId = "62bd412bbbf04747cd3de539" + downloadEntity.path = PackageInstaller.getDownloadPathWithId(downloadId, "apk") + downloadEntity.packageName = VHelper.VSPACE_32BIT_PACKAGENAME + downloadEntity.addMetaExtra(DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200") + + val gameEntity = GameEntity(downloadEntity.gameId, downloadEntity.name) + gameEntity.gameVersion = mAppEntity?.version ?: "" + + // 确定下载类型 + val downloadType = + if (arguments?.getBoolean(VSpaceDialogFragment.KEY_IS_UPDATE) == true) UPDATE else DOWNLOAD + + downloadEntity.exposureTrace = ExposureUtils.logADownloadExposureEvent( + gameEntity, + downloadEntity.platform, + null, + downloadType + ).toJson() + + AppExecutor.uiExecutor.executeWithDelay({ + DownloadManager.getInstance().cancel(mDownloadUrl) + DownloadManager.getInstance().add(downloadEntity) + }, 200) + + DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity, "开始") + } + } + + } + + override fun onStart() { + super.onStart() + DownloadManager.getInstance().addObserver(mDataWatcher) + + // 上面监听安装包名变化的 LiveData 监听有可能被冲掉了 + // 手动再检查一下安装状态,避免出现已安装但是没有 dismiss 弹窗的问题 + if (PackageUtils.isInstalled(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)) { + dismissAllowingStateLoss() + } + } + + override fun onStop() { + super.onStop() + DownloadManager.getInstance().removeObserver(mDataWatcher) + } + + private fun updateDownloadButton(downloadEntity: DownloadEntity) { + val downloadBtn = mBinding.downloadBtn + downloadBtn.progress = (downloadEntity.progress * 10).toInt() + when (downloadEntity.status) { + downloading -> { + downloadBtn.setText(R.string.pause) + downloadBtn.progress = (downloadEntity.percent * 10).toInt() + downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL + downloadBtn.setOnClickListener { + DownloadManager.getInstance().pause(mDownloadUrl) + } + } + + pause -> { + downloadBtn.setText(R.string.resume) + downloadBtn.setOnClickListener { + DownloadManager.getInstance().resume(downloadEntity, true) + } + } + + overflow, + timeout, + neterror, + diskisfull, + waiting, + subscribe -> { + downloadBtn.setText(R.string.waiting) + downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL + downloadBtn.setOnClickListener { + DownloadManager.getInstance().resume(downloadEntity, false) + } + } + + done -> { + downloadBtn.setText(R.string.install) + downloadBtn.buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL + + SensorsBridge.trackEvent("HaloFunDownloadDone") + + downloadBtn.setOnClickListener { + PackageInstaller.install(requireContext(), downloadEntity) + SensorsBridge.trackEvent("HaloFunInstallButtonClick") + } + } + + cancel, + hijack, + notfound, + uncertificated, + unqualified -> { + downloadBtn.text = "下载畅玩助手服务组件" + downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL + downloadBtn.setOnClickListener { + DownloadManager.getInstance().resume(downloadEntity, true) + } + } + + else -> { + // do nothing + } + } + } + + companion object { + const val KEY_APP_ENTITY_32 = "app_entity_32" + const val KEY_AUTO_DOWNLOAD = "auto_download" + const val KEY_IS_UPDATE = "is_update" + + @JvmStatic + fun showDownloadDialog( + context: Context?, + appEntity32: AppEntity, + autoDownload: Boolean = false, + isUpdate: Boolean = false, + gameId: String = "", + gameName: String = "" + ) { + val fragmentActivity: FragmentActivity = if (context is FragmentActivity) { + context + } else { + val currentActivity = AppManager.getInstance().currentActivity() + if (currentActivity is FragmentActivity) { + currentActivity + } else { + throw IllegalStateException("current activity context must be FragmentActivity") + } + } + + // 防止重复弹出 + if (hasDialogDisplayedInCurrentActivity(fragmentActivity)) return + + NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_show") + + if (context is BaseActivity) { + SensorsBridge.trackEvent( + "HaloFunDownloadDialogShow", + "last_page_name", context::class.java.simpleName, + "last_page_id", context.getUniqueId(), + "last_page_business_id", context.getBusinessId().first, + ) + } + + + val downloadDialog = VSpace32DialogFragment().apply { + arguments = Bundle().apply { + putParcelable(KEY_APP_ENTITY_32, appEntity32) + putString(EntranceConsts.KEY_GAME_ID, gameId) + putString(EntranceConsts.KEY_GAME_NAME, gameName) + putBoolean(KEY_AUTO_DOWNLOAD, autoDownload) + putBoolean(KEY_IS_UPDATE, isUpdate) + } + } + downloadDialog.show( + fragmentActivity.supportFragmentManager, + VSpace32DialogFragment::class.java.name + ) + } + + @JvmStatic + fun showDownloadDialog( + context: Context?, + appEntity32: AppEntity, + gameEntity: GameEntity?, + autoDownload: Boolean = false, + isUpdate: Boolean = false + ) { + showDownloadDialog( + context, + appEntity32, + autoDownload, + isUpdate, + gameEntity?.id ?: "", + gameEntity?.name ?: "" + ) + } + + private fun hasDialogDisplayedInCurrentActivity(fragmentActivity: FragmentActivity): Boolean { + val fragments: List = fragmentActivity.supportFragmentManager.fragments + fragments.forEach { fragment -> + if (fragment is VSpace32DialogFragment) return true + } + return false + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/vspace/VSpaceDialogFragment.kt b/app/src/main/java/com/gh/vspace/VSpaceDialogFragment.kt index 651d0d33a2..bd764ee5db 100644 --- a/app/src/main/java/com/gh/vspace/VSpaceDialogFragment.kt +++ b/app/src/main/java/com/gh/vspace/VSpaceDialogFragment.kt @@ -41,14 +41,18 @@ import com.lightgame.utils.AppManager class VSpaceDialogFragment : BaseDraggableDialogFragment() { - private var mAppEntity: AppEntity? = null + private var mAppEntity64: AppEntity? = null + private var mAppEntity32: AppEntity? = null private var mGameId: String = "" private var mGameName: String = "" - private val mDownloadUrl by lazy { mAppEntity?.url ?: "" } + private var mBit: String = "" // 畅玩游戏位数 + private var mIsUpdate = false + private val mDownloadUrl64 by lazy { mAppEntity64?.url ?: "" } + private val mDownloadUrl32 by lazy { mAppEntity32?.url ?: "" } private val mBinding by lazy { DialogVspaceBinding.inflate(layoutInflater) } private val mDataWatcher = object : DataWatcher() { override fun onDataChanged(downloadEntity: DownloadEntity) { - if (downloadEntity.url == mDownloadUrl && isAdded) { + if (((mAppEntity64 != null && downloadEntity.url == mDownloadUrl64) || (mAppEntity64 == null && downloadEntity.url == mDownloadUrl32)) && isAdded) { updateDownloadButton(downloadEntity) } } @@ -64,9 +68,12 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - mAppEntity = arguments?.get(KEY_ENTITY) as AppEntity + mAppEntity64 = arguments?.get(KEY_APP_ENTITY_64) as AppEntity + mAppEntity32 = arguments?.get(KEY_APP_ENTITY_32) as AppEntity mGameId = arguments?.getString(EntranceConsts.KEY_GAME_ID) ?: "" mGameName = arguments?.getString(EntranceConsts.KEY_GAME_NAME) ?: "" + mBit = arguments?.getString(VHelper.KEY_BIT) ?: "" + mIsUpdate = arguments?.getBoolean(KEY_IS_UPDATE) == true } @SuppressLint("ClickableViewAccessibility") @@ -84,13 +91,17 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { val mViewModel = viewModelProvider() mViewModel.packageLiveData.observe(this) { if (it.packageName == VHelper.DEFAULT_VSPACE_PACKAGENAME) { + if (mIsUpdate) showVSpace32UpdateDialogIfNeeded() else showVSpace32DownloadDialogIfNeeded() + dismissAllowingStateLoss() + } + if (it.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) { dismissAllowingStateLoss() } } mBinding.downloadBtn.text = "下载畅玩助手服务组件" mBinding.downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL - mBinding.descTv.text = "检测到您未安装畅玩64位组件,\n点击下载即可体验急速畅玩~" + mBinding.descTv.text = "《$mGameName》需先安装畅玩服务组件,安装后即可进入游戏体验新鲜功能~" mBinding.privacyPolicyTv.setOnClickListener { NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_privacy_click") DirectUtils.directToWebView(requireContext(), Constants.SMOOTH_GAME_PRIVACY_POLICY_ADDRESS) @@ -103,40 +114,60 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_download_click") SensorsBridge.trackEvent("HaloFunDownloadDialogDownloadClick", "game_id", mGameId, "game_name", mGameName) - val name = "畅玩助手V" + mAppEntity?.version - val downloadId = PackageInstaller.createDownloadId(name) - - val downloadEntity = DownloadEntity() - downloadEntity.url = mDownloadUrl - downloadEntity.name = name - downloadEntity.platform = "官方版" - downloadEntity.gameId = "62bd412bbbf04747cd3de539" - downloadEntity.path = PackageInstaller.getDownloadPathWithId(downloadId, "apk") - downloadEntity.packageName = VHelper.DEFAULT_VSPACE_PACKAGENAME - downloadEntity.addMetaExtra(DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200") - // 确定下载类型 - val downloadType = - if (arguments?.getBoolean(KEY_IS_UPDATE) == true) UPDATE else DOWNLOAD - val gameEntity = GameEntity(downloadEntity.gameId, downloadEntity.name) - gameEntity.gameVersion = mAppEntity?.version ?: "" + val downloadType = if (mIsUpdate) UPDATE else DOWNLOAD + var downloadEntity64: DownloadEntity? = null + var downloadEntity32: DownloadEntity? = null - val event = ExposureUtils.logADownloadExposureEvent( - gameEntity, - downloadEntity.platform, - null, - downloadType - ) + if (mAppEntity64 != null) { + downloadEntity64 = getDownloadEntity(true) - downloadEntity.exposureTrace = event.toJson() + val gameEntity64 = GameEntity(downloadEntity64.gameId, downloadEntity64.name) + gameEntity64.gameVersion = mAppEntity64?.version ?: "" + + downloadEntity64.exposureTrace = ExposureUtils.logADownloadExposureEvent( + gameEntity64, + downloadEntity64.platform, + null, + downloadType + ).toJson() + + // 收集下载数据 + DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity64, "开始") + } + + val is32VSpaceInstalled = PackageUtils.isInstalledFromAllPackage(context, VHelper.VSPACE_32BIT_PACKAGENAME) + if (mBit == "32" && mAppEntity32 != null && !(is32VSpaceInstalled && !mIsUpdate)) { + downloadEntity32 = getDownloadEntity(false) + + // 非32位单独下载时下载完成不弹出安装界面 + if (mAppEntity64 != null) { + downloadEntity32.addMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE, Constants.VSPACE_32_DOWNLOAD_ONLY) + } + + val gameEntity32 = GameEntity(downloadEntity32.gameId, downloadEntity32.name) + gameEntity32.gameVersion = mAppEntity32?.version ?: "" + + downloadEntity32.exposureTrace = ExposureUtils.logADownloadExposureEvent( + gameEntity32, + downloadEntity32.platform, + null, + downloadType + ).toJson() + + DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity32, "开始") + } AppExecutor.uiExecutor.executeWithDelay({ - DownloadManager.getInstance().cancel(mDownloadUrl) - DownloadManager.getInstance().add(downloadEntity) + if (downloadEntity64 != null) { + DownloadManager.getInstance().cancel(mDownloadUrl64) + DownloadManager.getInstance().add(downloadEntity64) + } + if (downloadEntity32 != null) { + DownloadManager.getInstance().cancel(mDownloadUrl32) + DownloadManager.getInstance().add(downloadEntity32) + } }, 200) - - // 收集下载数据 - DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity, "开始") } if (arguments?.getBoolean(KEY_AUTO_DOWNLOAD) == true && downloadSnapshot == null) { @@ -144,6 +175,17 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { } } + private fun getDownloadEntity(is64Bit: Boolean) = DownloadEntity().apply { + url = if (is64Bit) mDownloadUrl64 else mDownloadUrl32 + name = + "畅玩助手V" + (if (is64Bit) mAppEntity64?.version else mAppEntity32?.version) + "(${if (is64Bit) 64 else 32}位)" + platform = "官方版" + gameId = "62bd412bbbf04747cd3de539" + path = PackageInstaller.getDownloadPathWithId(PackageInstaller.createDownloadId(name), "apk") + packageName = if (is64Bit) VHelper.DEFAULT_VSPACE_PACKAGENAME else VHelper.VSPACE_32BIT_PACKAGENAME + addMetaExtra(DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200") + } + override fun onStart() { super.onStart() DownloadManager.getInstance().addObserver(mDataWatcher) @@ -151,8 +193,36 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { // 上面监听安装包名变化的 LiveData 监听有可能被冲掉了 // 手动再检查一下安装状态,避免出现已安装但是没有 dismiss 弹窗的问题 if (PackageUtils.isInstalled(requireContext(), VHelper.DEFAULT_VSPACE_PACKAGENAME)) { + if (mIsUpdate) showVSpace32UpdateDialogIfNeeded() else showVSpace32DownloadDialogIfNeeded() dismissAllowingStateLoss() } + if (PackageUtils.isInstalled(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)) { + dismissAllowingStateLoss() + } + } + + private fun showVSpace32DownloadDialogIfNeeded() { + val is32VSpaceInstalled = + PackageUtils.isInstalledFromAllPackage(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME) + if (!is32VSpaceInstalled && mBit == "32" && mAppEntity32 != null && !mAppEntity32?.url.isNullOrEmpty()) { + VSpace32DialogFragment.showDownloadDialog( + requireContext(), + mAppEntity32!!, + gameId = mGameId, + gameName = mGameName + ) + } + } + + private fun showVSpace32UpdateDialogIfNeeded() { + if (mBit == "32" && mAppEntity32 != null && !mAppEntity32?.url.isNullOrEmpty()) { + VSpaceUpdate32DialogFragment.showDownloadDialog( + requireContext(), + mAppEntity32!!, + gameId = mGameId, + gameName = mGameName + ) + } } override fun onStop() { @@ -169,7 +239,7 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { downloadBtn.progress = (downloadEntity.percent * 10).toInt() downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL downloadBtn.setOnClickListener { - DownloadManager.getInstance().pause(mDownloadUrl) + DownloadManager.getInstance().pause(downloadEntity.url) } } @@ -223,18 +293,21 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { } companion object { - const val KEY_ENTITY = "entity" + const val KEY_APP_ENTITY_64 = "app_entity_64" + const val KEY_APP_ENTITY_32 = "app_entity_32" const val KEY_AUTO_DOWNLOAD = "auto_download" const val KEY_IS_UPDATE = "is_update" @JvmStatic fun showDownloadDialog( context: Context?, - appEntity: AppEntity, + appEntity64: AppEntity?, + appEntity32: AppEntity?, autoDownload: Boolean = false, isUpdate: Boolean = false, gameId: String = "", - gameName: String = "" + gameName: String = "", + bit: String = "" ) { val fragmentActivity: FragmentActivity = if (context is FragmentActivity) { context @@ -264,9 +337,11 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { val downloadDialog = VSpaceDialogFragment().apply { arguments = Bundle().apply { - putParcelable(KEY_ENTITY, appEntity) + if (appEntity64 != null) putParcelable(KEY_APP_ENTITY_64, appEntity64) + if (appEntity32 != null) putParcelable(KEY_APP_ENTITY_32, appEntity32) putString(EntranceConsts.KEY_GAME_ID, gameId) putString(EntranceConsts.KEY_GAME_NAME, gameName) + putString(VHelper.KEY_BIT, bit) putBoolean(KEY_AUTO_DOWNLOAD, autoDownload) putBoolean(KEY_IS_UPDATE, isUpdate) } @@ -280,12 +355,22 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { @JvmStatic fun showDownloadDialog( context: Context?, - appEntity: AppEntity, + appEntity64: AppEntity?, + appEntity32: AppEntity?, gameEntity: GameEntity?, autoDownload: Boolean = false, isUpdate: Boolean = false ) { - showDownloadDialog(context, appEntity, autoDownload, isUpdate, gameEntity?.id ?: "", gameEntity?.name ?: "") + showDownloadDialog( + context, + appEntity64, + appEntity32, + autoDownload, + isUpdate, + gameEntity?.id ?: "", + gameEntity?.name ?: "", + gameEntity?.getApk()?.get(0)?.bit ?: "" + ) } private fun hasDialogDisplayedInCurrentActivity(fragmentActivity: FragmentActivity): Boolean { diff --git a/app/src/main/java/com/gh/vspace/VSpaceUpdate32DialogFragment.kt b/app/src/main/java/com/gh/vspace/VSpaceUpdate32DialogFragment.kt new file mode 100644 index 0000000000..bd398eafaa --- /dev/null +++ b/app/src/main/java/com/gh/vspace/VSpaceUpdate32DialogFragment.kt @@ -0,0 +1,291 @@ +package com.gh.vspace + +import android.annotation.SuppressLint +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import com.gh.common.exposure.ExposureUtils +import com.gh.common.exposure.ExposureUtils.DownloadType.DOWNLOAD +import com.gh.common.exposure.ExposureUtils.DownloadType.UPDATE +import com.gh.common.util.DataCollectionUtils +import com.gh.common.util.NewFlatLogUtils +import com.gh.common.util.PackageInstaller +import com.gh.common.util.PackageUtils +import com.gh.gamecenter.feature.view.DownloadButton +import com.gh.download.DownloadManager +import com.gh.gamecenter.R +import com.gh.gamecenter.common.base.activity.BaseActivity +import com.gh.gamecenter.common.base.fragment.BaseDialogFragment +import com.gh.gamecenter.common.constant.EntranceConsts +import com.gh.gamecenter.common.utils.* +import com.gh.gamecenter.core.AppExecutor +import com.gh.gamecenter.databinding.DialogVspaceUpdate32Binding +import com.gh.gamecenter.entity.AppEntity +import com.gh.gamecenter.feature.entity.GameEntity +import com.halo.assistant.HaloApp +import com.lightgame.download.DataWatcher +import com.lightgame.download.DownloadConfig +import com.lightgame.download.DownloadEntity +import com.lightgame.download.DownloadStatus.* +import com.lightgame.utils.AppManager + +class VSpaceUpdate32DialogFragment : BaseDialogFragment() { + + private var mAppEntity: AppEntity? = null + private var mGameId: String = "" + private var mGameName: String = "" + private val mDownloadUrl by lazy { mAppEntity?.url ?: "" } + private val mBinding by lazy { DialogVspaceUpdate32Binding.inflate(layoutInflater) } + private val mDataWatcher = object : DataWatcher() { + override fun onDataChanged(downloadEntity: DownloadEntity) { + if (downloadEntity.url == mDownloadUrl && isAdded) { + updateDownloadButton(downloadEntity) + } + } + + override fun onDataInit(downloadEntity: DownloadEntity) { + onDataChanged(downloadEntity) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + mAppEntity = arguments?.get(KEY_APP_ENTITY_32) as AppEntity + mGameId = arguments?.getString(EntranceConsts.KEY_GAME_ID) ?: "" + mGameName = arguments?.getString(EntranceConsts.KEY_GAME_NAME) ?: "" + } + + @SuppressLint("ClickableViewAccessibility") + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return mBinding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + val mViewModel = viewModelProvider() + mViewModel.packageLiveData.observe(this) { + if (it.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) { + dismissAllowingStateLoss() + } + } + + val downloadSnapshot = DownloadManager.getInstance() + .getDownloadEntitySnapshotByPackageName(VHelper.VSPACE_32BIT_PACKAGENAME) + mBinding.downloadBtn.text = if (downloadSnapshot?.status == done) "安装" else "下载" + mBinding.downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL + mBinding.contentTv.text = "《$mGameName》需安装完整的畅玩服务组件,安装后即可给您带来急速的畅玩体验~" + + mBinding.downloadBtn.setOnClickListener { + if (downloadSnapshot?.status == done) { + PackageInstaller.install(requireContext(), downloadSnapshot) + SensorsBridge.trackEvent("HaloFunInstallButtonClick") + } else { + val downloadEntity = DownloadEntity() + + val name = "畅玩助手V" + mAppEntity?.version + "(32位)" + val downloadId = PackageInstaller.createDownloadId(name) + + downloadEntity.url = mDownloadUrl + downloadEntity.name = name + downloadEntity.platform = "官方版" + downloadEntity.gameId = "62bd412bbbf04747cd3de539" + downloadEntity.path = PackageInstaller.getDownloadPathWithId(downloadId, "apk") + downloadEntity.packageName = VHelper.VSPACE_32BIT_PACKAGENAME + downloadEntity.addMetaExtra(DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200") + + val gameEntity = GameEntity(downloadEntity.gameId, downloadEntity.name) + gameEntity.gameVersion = mAppEntity?.version ?: "" + + // 确定下载类型 + val downloadType = + if (arguments?.getBoolean(VSpaceDialogFragment.KEY_IS_UPDATE) == true) UPDATE else DOWNLOAD + + downloadEntity.exposureTrace = ExposureUtils.logADownloadExposureEvent( + gameEntity, + downloadEntity.platform, + null, + downloadType + ).toJson() + + AppExecutor.uiExecutor.executeWithDelay({ + DownloadManager.getInstance().cancel(mDownloadUrl) + DownloadManager.getInstance().add(downloadEntity) + }, 200) + + DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity, "开始") + } + } + + } + + override fun onStart() { + super.onStart() + DownloadManager.getInstance().addObserver(mDataWatcher) + + // 上面监听安装包名变化的 LiveData 监听有可能被冲掉了 + // 手动再检查一下安装状态,避免出现已安装但是没有 dismiss 弹窗的问题 + if (PackageUtils.isInstalled(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)) { + dismissAllowingStateLoss() + } + } + + override fun onStop() { + super.onStop() + DownloadManager.getInstance().removeObserver(mDataWatcher) + } + + private fun updateDownloadButton(downloadEntity: DownloadEntity) { + val downloadBtn = mBinding.downloadBtn + downloadBtn.progress = (downloadEntity.progress * 10).toInt() + when (downloadEntity.status) { + downloading -> { + downloadBtn.setText(R.string.pause) + downloadBtn.progress = (downloadEntity.percent * 10).toInt() + downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL + downloadBtn.setOnClickListener { + DownloadManager.getInstance().pause(mDownloadUrl) + } + } + + pause -> { + downloadBtn.setText(R.string.resume) + downloadBtn.setOnClickListener { + DownloadManager.getInstance().resume(downloadEntity, true) + } + } + + overflow, + timeout, + neterror, + diskisfull, + waiting, + subscribe -> { + downloadBtn.setText(R.string.waiting) + downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL + downloadBtn.setOnClickListener { + DownloadManager.getInstance().resume(downloadEntity, false) + } + } + + done -> { + downloadBtn.setText(R.string.install) + downloadBtn.buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL + + SensorsBridge.trackEvent("HaloFunDownloadDone") + + downloadBtn.setOnClickListener { + PackageInstaller.install(requireContext(), downloadEntity) + SensorsBridge.trackEvent("HaloFunInstallButtonClick") + } + } + + cancel, + hijack, + notfound, + uncertificated, + unqualified -> { + downloadBtn.text = "下载畅玩助手服务组件" + downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL + downloadBtn.setOnClickListener { + DownloadManager.getInstance().resume(downloadEntity, true) + } + } + + else -> { + // do nothing + } + } + } + + companion object { + const val KEY_APP_ENTITY_32 = "app_entity_32" + const val KEY_AUTO_DOWNLOAD = "auto_download" + const val KEY_IS_UPDATE = "is_update" + + @JvmStatic + fun showDownloadDialog( + context: Context?, + appEntity32: AppEntity, + autoDownload: Boolean = false, + isUpdate: Boolean = false, + gameId: String = "", + gameName: String = "" + ) { + val fragmentActivity: FragmentActivity = if (context is FragmentActivity) { + context + } else { + val currentActivity = AppManager.getInstance().currentActivity() + if (currentActivity is FragmentActivity) { + currentActivity + } else { + throw IllegalStateException("current activity context must be FragmentActivity") + } + } + + // 防止重复弹出 + if (hasDialogDisplayedInCurrentActivity(fragmentActivity)) return + + NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_show") + + if (context is BaseActivity) { + SensorsBridge.trackEvent( + "HaloFunDownloadDialogShow", + "last_page_name", context::class.java.simpleName, + "last_page_id", context.getUniqueId(), + "last_page_business_id", context.getBusinessId().first, + ) + } + + + val downloadDialog = VSpaceUpdate32DialogFragment().apply { + arguments = Bundle().apply { + putParcelable(KEY_APP_ENTITY_32, appEntity32) + putString(EntranceConsts.KEY_GAME_ID, gameId) + putString(EntranceConsts.KEY_GAME_NAME, gameName) + putBoolean(KEY_AUTO_DOWNLOAD, autoDownload) + putBoolean(KEY_IS_UPDATE, isUpdate) + } + } + downloadDialog.show( + fragmentActivity.supportFragmentManager, + VSpaceUpdate32DialogFragment::class.java.name + ) + } + + @JvmStatic + fun showDownloadDialog( + context: Context?, + appEntity32: AppEntity, + gameEntity: GameEntity?, + autoDownload: Boolean = false, + isUpdate: Boolean = false + ) { + showDownloadDialog( + context, + appEntity32, + autoDownload, + isUpdate, + gameEntity?.id ?: "", + gameEntity?.name ?: "" + ) + } + + private fun hasDialogDisplayedInCurrentActivity(fragmentActivity: FragmentActivity): Boolean { + val fragments: List = fragmentActivity.supportFragmentManager.fragments + fragments.forEach { fragment -> + if (fragment is VSpaceUpdate32DialogFragment) return true + } + return false + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_vspace_dialog_completed.xml b/app/src/main/res/drawable/bg_vspace_dialog_completed.xml new file mode 100644 index 0000000000..6a7d1abf9c --- /dev/null +++ b/app/src/main/res/drawable/bg_vspace_dialog_completed.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_completed.xml b/app/src/main/res/drawable/ic_completed.xml new file mode 100644 index 0000000000..cbba06ec4b --- /dev/null +++ b/app/src/main/res/drawable/ic_completed.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/dialog_vspace.xml b/app/src/main/res/layout/dialog_vspace.xml index fb6474ef6b..2f2d24e4cb 100644 --- a/app/src/main/res/layout/dialog_vspace.xml +++ b/app/src/main/res/layout/dialog_vspace.xml @@ -7,7 +7,7 @@ @@ -30,19 +30,20 @@ + tools:text="《XXX》需先安装畅玩服务组件,安装后即可进入游戏体验新鲜功能~" /> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/iconContainer" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_vspace_update_32.xml b/app/src/main/res/layout/dialog_vspace_update_32.xml new file mode 100644 index 0000000000..2eb8305d88 --- /dev/null +++ b/app/src/main/res/layout/dialog_vspace_update_32.xml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_common/src/main/java/com/gh/gamecenter/common/constant/Constants.java b/module_common/src/main/java/com/gh/gamecenter/common/constant/Constants.java index 251a8e1aee..41729fe928 100644 --- a/module_common/src/main/java/com/gh/gamecenter/common/constant/Constants.java +++ b/module_common/src/main/java/com/gh/gamecenter/common/constant/Constants.java @@ -76,6 +76,7 @@ public class Constants { public static final String SIMULATOR_GAME = "simulator_game"; public static final String SIMULATOR = "simulator"; public static final String SMOOTH_GAME = "smooth_game"; // 畅玩类型的游戏 + public static final String VSPACE_32_DOWNLOAD_ONLY = "vspace_32_download_only"; // 仅下载32位畅玩助手,不跳转安装 public static final String GAME_NAME = "game_name"; public static final String GAME_TYPE = "game_type"; public static final String SIMULATOR_DOWNLOAD_START_TIME = "simulator_download_start_time"; diff --git a/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/ApkEntity.kt b/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/ApkEntity.kt index 29812b385a..52e5115553 100644 --- a/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/ApkEntity.kt +++ b/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/ApkEntity.kt @@ -52,7 +52,9 @@ data class ApkEntity( var updateDesc: String = "", @SerializedName("download_status") var downloadStatus: String = "", - var format: String = "" + var format: String = "", + // 畅玩游戏位数 + val bit: String = "", ) : Parcelable { fun getPlatform(): String? { if (TextUtils.isEmpty(platform)) {