diff --git a/app/build.gradle b/app/build.gradle index 09cf79981c..79e47cb0bc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -417,6 +417,7 @@ dependencies { debugImplementation "com.bytedance.tools.codelocator:codelocator-core:2.0.3" compileOnly project(":va-core") compileOnly project(":va-plugin-host-lib") + implementation project(":va-plugin-host") } File propFile = file('sign.properties') diff --git a/app/src/main/java/com/gh/common/constant/Config.java b/app/src/main/java/com/gh/common/constant/Config.java index 7f7bdbbc11..b1c181b2c4 100644 --- a/app/src/main/java/com/gh/common/constant/Config.java +++ b/app/src/main/java/com/gh/common/constant/Config.java @@ -5,10 +5,10 @@ import android.content.SharedPreferences; import android.os.Build; import android.preference.PreferenceManager; import android.text.TextUtils; +import android.util.Log; import androidx.annotation.Nullable; -import com.gh.common.util.AdHelper; import com.gh.common.util.PackageHelper; import com.gh.common.util.PackageUtils; import com.gh.gamecenter.BuildConfig; @@ -46,6 +46,7 @@ import java.util.Locale; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; +import io.reactivex.subjects.BehaviorSubject; import okhttp3.ResponseBody; public class Config { @@ -75,6 +76,7 @@ public class Config { private static SimulatorEntity mNewSimulatorEntity; private static VSetting mVSetting; private static VNewSetting mVNewSetting; + public static BehaviorSubject vNewSettingSubject = BehaviorSubject.create(); private static GameGuidePopupEntity mGameGuidePopupEntity; private static SharedPreferences mDefaultSharedPreferences; @@ -308,12 +310,14 @@ public class Config { return mVSetting; } + @Nullable public static VNewSetting getVNewSettingEntity() { if (mVNewSetting == null) { try { String json = SPUtils.getString(Constants.SP_V_NEW_SETTINGS); if (!TextUtils.isEmpty(json)) { mVNewSetting = GsonUtils.fromJson(json, VNewSetting.class); + vNewSettingSubject.onNext(mVNewSetting); } } catch (Exception e) { e.printStackTrace(); @@ -351,9 +355,8 @@ public class Config { .subscribe(new BiResponse() { @Override public void onSuccess(VNewSetting data) { - // TODO: test - data.getVa().getArch32().setUrl("https://dev-app-static.796697.com/va/apk/2024/01/04/com.gh.gamecenter.addon_2.0.0-debug_20000_0.0.10_1704335165.apk"); mVNewSetting = data; + vNewSettingSubject.onNext(mVNewSetting); SPUtils.setString(Constants.SP_V_NEW_SETTINGS, GsonUtils.toJson(data)); } }); 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 075101fd9f..bedfa05e4d 100644 --- a/app/src/main/java/com/gh/common/util/DownloadObserver.kt +++ b/app/src/main/java/com/gh/common/util/DownloadObserver.kt @@ -489,11 +489,18 @@ object DownloadObserver { "space_schema_type", if (downloadEntity.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) "32位" else "64位" ) + } else if(downloadEntity.gameId == Constants.HALO_FUN_NEW_32_GAME_ID) { + SensorsBridge.trackEvent( + "HaloFunDownloadDone", + "space_schema_type", + "32位(新)" + ) } if (downloadEntity.gameId != Constants.GHZS_GAME_ID && downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) != Constants.SIMULATOR_DOWNLOAD - && downloadEntity.gameId != Constants.HALO_FUN_GAME_ID) { + && downloadEntity.gameId != Constants.HALO_FUN_GAME_ID + && downloadEntity.gameId != Constants.HALO_FUN_NEW_32_GAME_ID) { SensorsBridge.trackEventWithExposureSource( "DownloadProcessFinish", exposureEvent?.source, diff --git a/app/src/main/java/com/gh/gamecenter/entity/VNewSetting.kt b/app/src/main/java/com/gh/gamecenter/entity/VNewSetting.kt index 52d9909863..917094b647 100644 --- a/app/src/main/java/com/gh/gamecenter/entity/VNewSetting.kt +++ b/app/src/main/java/com/gh/gamecenter/entity/VNewSetting.kt @@ -23,23 +23,20 @@ class VNewSetting { val versionName: String, @SerializedName("version_code") val versionCode: Int, - // TODO: test change to val - var url: String + val url: String ) data class VaPlugin( @SerializedName("_id") - val id: String, - @SerializedName("version") - val versionName: String, - @SerializedName("version_code") - val versionCode: Int, - @SerializedName("update_log") - var updateLog: String?, + val id: String?, + @SerializedName("version_name") + val versionName: String?, + @SerializedName("change_log") + var changeLog: String?, @SerializedName("url_32") - val url32: String, - @SerializedName("url64") - val url64: String, + val url32: String?, + @SerializedName("url_64") + val url64: String?, ) } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/retrofit/service/VApiService.kt b/app/src/main/java/com/gh/gamecenter/retrofit/service/VApiService.kt index be899fec04..866a1c0256 100644 --- a/app/src/main/java/com/gh/gamecenter/retrofit/service/VApiService.kt +++ b/app/src/main/java/com/gh/gamecenter/retrofit/service/VApiService.kt @@ -5,6 +5,7 @@ import com.gh.gamecenter.entity.VNewSetting import com.gh.gamecenter.entity.VSetting import io.reactivex.Single import retrofit2.http.GET +import retrofit2.http.Header import retrofit2.http.Query interface VApiService { @@ -26,5 +27,15 @@ interface VApiService { fun getSettings(@Query("version") version: String?, @Query("android") androidSdkVersion: Int): Single @GET("new/setting") - fun getNewSettings(@Query("version") version: String?, @Query("android") androidSdkVersion: Int): Single + fun getNewSettings( + @Query("version") version: String?, + @Query("android") androidSdkVersion: Int, + ): Single + + @GET("new/upgrade") + fun getNewPackageUpdate( + @Query("version") version: String?, + @Query("gh_version") ghVersion: String?, + @Query("channel") channel: String, + ): Single } \ No newline at end of file diff --git a/app/src/main/java/com/gh/vspace/VHelper.kt b/app/src/main/java/com/gh/vspace/VHelper.kt index 89664a8aec..0f2f8ce099 100644 --- a/app/src/main/java/com/gh/vspace/VHelper.kt +++ b/app/src/main/java/com/gh/vspace/VHelper.kt @@ -15,6 +15,7 @@ import android.view.View import androidx.annotation.WorkerThread import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.* +import com.g00fy2.versioncompare.Version import com.gh.ad.AdDelegateHelper import com.gh.common.constant.Config import com.gh.common.exposure.ExposureUtils @@ -23,6 +24,9 @@ import com.gh.common.util.* import com.gh.common.util.NewFlatLogUtils import com.gh.download.DownloadManager import com.gh.download.PackageObserver +import com.gh.download.simple.DownloadListener +import com.gh.download.simple.DownloadMessageHandler +import com.gh.download.simple.SimpleDownloadManager import com.gh.gamecenter.R import com.gh.gamecenter.SplashScreenActivity import com.gh.gamecenter.common.base.GlobalActivityManager @@ -47,9 +51,15 @@ import com.gh.vspace.db.VGameDatabase import com.gh.vspace.db.VGameEntity import com.gh.vspace.gapps.GAppsDownloadDialogFragment import com.halo.assistant.HaloApp +import com.lg.download.DownloadError +import com.lg.download.DownloadStatus +import com.lg.download.httpclient.DefaultHttpClient +import com.lg.ndownload.DownloadConfigBuilder import com.lg.vspace.VaApp import com.lg.vspace.VirtualAppManager import com.lg.vspace.bridge.BuildConfig +import com.lg.vspace.plugin.host.PluginFileUtils +import com.lg.vspace.plugin.host.PluginHelper import com.lg.vspace.remote.BinderPool import com.lg.vspace.remote.listener.RemoteConnectListener import com.lg.vspace.remote.model.AppInstallerInfo @@ -58,13 +68,14 @@ import com.lg.vspace.remote.model.VGameInstallerResult import com.lightgame.download.DownloadEntity import com.lightgame.utils.AppManager import com.lightgame.utils.Utils +import com.va.host.HostUtils import io.reactivex.schedulers.Schedulers import io.reactivex.subjects.PublishSubject import org.greenrobot.eventbus.EventBus import java.io.File import java.util.* import java.util.concurrent.CopyOnWriteArrayList -import kotlin.collections.ArrayList +import java.util.concurrent.TimeUnit object VHelper { @@ -73,6 +84,7 @@ object VHelper { private const val KEY_LAST_PLAYED_TIME = "last_played_time" private const val KEY_LAST_ALERT_64_UPDATE_URL = "last_alert_64_update_url" private const val KEY_LAST_ALERT_32_UPDATE_URL = "last_alert_32_update_url" + private const val KEY_LAST_ALERT_32_NEW_UPDATE_URL = "last_alert_32_new_update_url" private const val KEY_TOTAL_PLAYED_TIME = "total_played_time" private const val G_GMS_PACKAGE_NAME = "com.google.android.gms" @@ -89,6 +101,7 @@ object VHelper { const val LOG_TAG = "VSPACE" const val DEFAULT_VSPACE_PACKAGENAME = "com.lg.vspace" const val VSPACE_32BIT_PACKAGENAME = "$DEFAULT_VSPACE_PACKAGENAME.addon" + const val VSPACE_32BIT_NEW_PACKAGENAME = com.lg.vspace.BuildConfig.EXT_PACKAGE_NAME private val mDelegateManager by lazy { VirtualAppManager.get() } private val mPackageInstalledLiveData by lazy { MutableLiveData() } @@ -101,6 +114,7 @@ object VHelper { private var m64UpdateEntity: AppEntity? = null private var m32UpdateEntity: AppEntity? = null + private var mNew32UpdateEntity: AppEntity? = null private var mIsInitialized = false // 是否已初始化 private var mIsServiceConnected = false // AIDL 服务是否成功连接,不可作为 AIDL 仍然可用的依据 @@ -256,6 +270,12 @@ object VHelper { getVSpaceUpdate(config.arch32, false) } + val newConfig = Config.getVNewSettingEntity()?.va + if (newConfig?.arch32 != null && mNew32UpdateEntity == null) { + // 检查畅玩助手 32 位组件(新)更新 + getVNewSpaceUpdate(newConfig.arch32.packageName) + } + runOnIoThread { refreshVGameSnapshot() } @@ -537,9 +557,7 @@ object VHelper { if (isInstalled(gameEntity?.getUniquePackageName())) { oldCwValidateVSpaceBeforeAction(context, gameEntity, callback) } else { - //TODO: check new cw 32 va component - - callback.invoke() + newCwValidateVspaceBeforeAction(context, gameEntity, callback) } } @@ -656,6 +674,86 @@ object VHelper { callback.invoke() } + private fun newCwValidateVspaceBeforeAction(context: Context, gameEntity: GameEntity?, callback: () -> Unit) { + val bit = gameEntity?.gameBit ?: "" + if (bit == "32") { + val vaConfig = Config.getVNewSettingEntity()?.va + if (vaConfig == null) { + ToastUtils.toast("畅玩助手空间暂未上线") + return + } + val is32VSpaceInstalled = PackageUtils.isInstalledFromAllPackage(context, vaConfig.arch32?.packageName) + if (!is32VSpaceInstalled) { + val appEntity = AppEntity() + appEntity.versionCode = vaConfig.arch32?.versionCode ?: 0 + appEntity.version = vaConfig.arch32?.versionName + appEntity.url = vaConfig.arch32?.url + + VSpace32NewDialogFragment.showDownloadDialog( + context, + appEntity, + gameId = gameEntity?.id ?: "", + gameName = gameEntity?.name ?: "", + ) + return + } + val contains32Update = newCw32ShouldShowUpdate( + mNew32UpdateEntity, + PackageUtils.getVersionCodeByPackageName(vaConfig.arch32?.packageName) + ) + if (contains32Update) { + val updateEntity = mNew32UpdateEntity + val dialogType = if (updateEntity!!.isAlertEveryTime()) "强制更新" else "提示更新" + NewFlatLogUtils.logHaloFunUpdateDialogShow( + gameEntity?.id ?: "", + gameEntity?.name ?: "", + "32位" + ) + SPUtils.setString( + KEY_LAST_ALERT_32_NEW_UPDATE_URL, + updateEntity.url + updateEntity.alert + ) + DialogHelper.showDialog( + context = context, + title = "服务工具更新提示", + content = updateEntity.content.toString(), + cancelText = "立即更新", + confirmText = "继续游戏", + cancelClickCallback = { + NewFlatLogUtils.logHaloFunUpdateDialogClick( + dialogType, + "立即更新", + "32位" + ) + VSpaceDialogFragment.showDownloadDialog( + context, + null, + updateEntity, + gameEntity, + autoDownload = true, + isUpdate = true + ) + }, + confirmClickCallback = { + NewFlatLogUtils.logHaloFunUpdateDialogClick(dialogType, "继续游戏", "") + callback.invoke() + }, + extraConfig = DialogHelper.Config(centerTitle = true), + uiModificationCallback = { + if (updateEntity.isAlertEveryTime()) { + it.confirmTv.visibility = View.GONE + it.cancelTv.setTextColor(R.color.theme_font.toColor(context)) + } + + it.confirmTv.setTextColor(R.color.text_subtitle.toColor(context)) + } + ) + return + } + } + callback.invoke() + } + /** * 获取已安装的包名列表 */ @@ -1652,6 +1750,20 @@ object VHelper { }) } + @SuppressLint("CheckResult") + private fun getVNewSpaceUpdate(packageName: String) { + val installedVersionName = PackageUtils.getVersionNameByPackageName(packageName) ?: "" + RetrofitManager.getInstance() + .vApi + .getNewPackageUpdate(installedVersionName, PackageUtils.getGhVersionName(), HaloApp.getInstance().channel) + .subscribeOn(Schedulers.io()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: AppEntity) { + mNew32UpdateEntity = data + } + }) + } + /** * 通过 PackageRepository 检查更新 */ @@ -1695,6 +1807,27 @@ object VHelper { return false } + private fun newCw32ShouldShowUpdate( + updateEntity: AppEntity?, + installedSpaceVersionCode: Int, + ): Boolean { + if (updateEntity == null) return false + + val hasNewerVersion = installedSpaceVersionCode < updateEntity.versionCode + + if (!hasNewerVersion) return false + + if (updateEntity.isAlertEveryTime()) return true + + val lastAlertUpdateUrl = updateEntity.url + updateEntity.alert + if (updateEntity.isAlertOnceADay() + && SPUtils.getString(KEY_LAST_ALERT_32_NEW_UPDATE_URL) != lastAlertUpdateUrl + ) { + return true + } + return false + } + /** * 打开畅玩广场(版块) */ @@ -1862,4 +1995,66 @@ object VHelper { return sortedEntityList.take(8) } + @SuppressLint("CheckResult") + fun preparePluginUpdate() { + Config.vNewSettingSubject.debounce(2, TimeUnit.SECONDS).doOnNext { + it?.vaPlugin?.let { vaPlugin -> + if (!vaPlugin.id.isNullOrEmpty() && !vaPlugin.url64.isNullOrEmpty()) { + val installedPluginVersion = HostUtils.getPluginVersion() + Utils.log( + LOG_TAG, + "插件更新:本地插件版本[${installedPluginVersion}], 推送版本[${vaPlugin.versionName}]" + ) + if (installedPluginVersion?.isNotEmpty() == true + && Version(vaPlugin.versionName).isHigherThan(installedPluginVersion) + ) { + + val pluginFileName = "${vaPlugin.id}.zip" + val currentPluginFile = File(HaloApp.getInstance().cacheDir, pluginFileName) + if (currentPluginFile.exists() && PluginFileUtils.isZipFile(currentPluginFile)) { + // 已经下载好了 + PluginHelper.getInstance().updatePlugin(currentPluginFile) + } else { + val currentDownloadEntity = DownloadMessageHandler.findEntity(vaPlugin.id) + if (currentDownloadEntity != null) { + SimpleDownloadManager.cancel(vaPlugin.id) + } + SimpleDownloadManager.download( + DownloadConfigBuilder() + .setUniqueId(vaPlugin.id) + .setFileName(pluginFileName) + .setUrl(vaPlugin.url64) + .setPathToStore(HaloApp.getInstance().cacheDir.absolutePath + File.separator) + .setHttpClient(DefaultHttpClient()) + .setDownloadThreadSize(2) + .setDownloadListener(DownloadMessageHandler) + .setDownloadExecutor(AppExecutor.ioExecutor) + .build() + ) + DownloadMessageHandler.registerListener(vaPlugin.id, object : DownloadListener { + override fun onError(error: DownloadError) { + } + + override fun onProgress(progress: Float) { + } + + override fun onSizeReceived(fileSize: Long) { + } + + override fun onStatusChanged(status: DownloadStatus) { + if (status == DownloadStatus.COMPLETED) { + PluginHelper.getInstance().updatePlugin(currentPluginFile) + DownloadMessageHandler.unregisterListener(vaPlugin.id, this) + } + } + + override fun onSpeedChanged(speed: Float) { + } + }) + } + } + } + } + }.subscribeOn(Schedulers.io()).subscribe({}, {}) + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/vspace/VSpace32NewDialogFragment.kt b/app/src/main/java/com/gh/vspace/VSpace32NewDialogFragment.kt new file mode 100644 index 0000000000..c03ff2ffea --- /dev/null +++ b/app/src/main/java/com/gh/vspace/VSpace32NewDialogFragment.kt @@ -0,0 +1,306 @@ +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.* +import com.gh.common.util.NewFlatLogUtils +import com.gh.download.DownloadManager +import com.gh.gamecenter.R +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.core.utils.SPUtils +import com.gh.gamecenter.core.utils.ToastUtils +import com.gh.gamecenter.databinding.DialogVspace32NewBinding +import com.gh.gamecenter.entity.AppEntity +import com.gh.gamecenter.feature.entity.GameEntity +import com.gh.gamecenter.feature.view.DownloadButton +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 +import java.io.File + +class VSpace32NewDialogFragment : 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 { DialogVspace32NewBinding.inflate(layoutInflater) } + private var mIsLogInstallShow = false + private var mIsLogAutoInstallClick = false + private var mIsClickDownloadThisTime = false // 是否本次弹出Dialog点击的下载按钮 + 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_NEW_PACKAGENAME) { + dismissAllowingStateLoss() + } + } + + val downloadSnapshot = DownloadManager.getInstance() + .getDownloadEntitySnapshotByPackageName(VHelper.VSPACE_32BIT_NEW_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) + } + + if (downloadSnapshot?.status == done) { + NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_show") + SensorsBridge.trackEvent("HaloFunExpandInstallDialogShow") + mIsLogInstallShow = true + } else { + NewFlatLogUtils.logHaloFun32DialogEvent("halo_fun_32_download_tip_dialog_show", mGameId, mGameName) + SensorsBridge.trackEvent("HaloFunExpandDownloadDialogShow", "game_id", mGameId, "game_name", mGameName) + } + + mBinding.downloadBtn.setOnClickListener { + if (downloadSnapshot?.status == done) { + if (!File(downloadSnapshot.path).exists()) { + ToastUtils.toast("畅玩组件已损坏,即将重新下载") + DownloadManager.getInstance().cancel(downloadSnapshot.url) + DownloadManager.getInstance().add(downloadSnapshot) + } else { + PackageInstaller.install(requireContext(), downloadSnapshot) + NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_click") + SensorsBridge.trackEvent("HaloFunExpandInstallButtonClick") + } + } 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 = Constants.HALO_FUN_NEW_32_GAME_ID + downloadEntity.path = PackageInstaller.getDownloadPathWithId(downloadId, "apk") + downloadEntity.packageName = VHelper.VSPACE_32BIT_NEW_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() + + mIsClickDownloadThisTime = true + + AppExecutor.uiExecutor.executeWithDelay({ + DownloadManager.getInstance().cancel(mDownloadUrl) + DownloadManager.getInstance().add(downloadEntity) + }, 200) + + DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity, "开始") + NewFlatLogUtils.logHaloFun32DialogEvent("halo_fun_32_download_tip_dialog_click", mGameId, mGameName) + SensorsBridge.trackEvent("HaloFunExpandDownloadDialogDownloadClick") + } + } + + } + + override fun onStart() { + super.onStart() + DownloadManager.getInstance().addObserver(mDataWatcher) + + // 上面监听安装包名变化的 LiveData 监听有可能被冲掉了 + // 手动再检查一下安装状态,避免出现已安装但是没有 dismiss 弹窗的问题 + if (PackageUtils.isInstalledFromAllPackage(requireContext(), VHelper.VSPACE_32BIT_NEW_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 + + if (!mIsLogInstallShow) { + NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_show") + SensorsBridge.trackEvent("HaloFunExpandInstallDialogShow") + mIsLogInstallShow = true + } + + val isVSpace32DownloadOnly = + downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.VSPACE_32_DOWNLOAD_ONLY + val isAutoInstall = SPUtils.getBoolean(Constants.SP_AUTO_INSTALL, true) + if (!isVSpace32DownloadOnly && isAutoInstall && !mIsLogAutoInstallClick && mIsClickDownloadThisTime) { + NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_click") + SensorsBridge.trackEvent("HaloFunExpandInstallButtonClick") + mIsLogAutoInstallClick = true + } + + downloadBtn.setOnClickListener { + if (!File(downloadEntity.path).exists()) { + ToastUtils.toast("畅玩组件已损坏,即将重新下载") + DownloadManager.getInstance().cancel(downloadEntity.url) + DownloadManager.getInstance().add(downloadEntity) + } else { + PackageInstaller.install(requireContext(), downloadEntity) + NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_click") + SensorsBridge.trackEvent("HaloFunExpandInstallButtonClick") + } + } + } + + 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" + + @JvmStatic + fun showDownloadDialog( + context: Context?, + appEntity32: AppEntity, + 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 + + val downloadDialog = VSpace32NewDialogFragment().apply { + arguments = Bundle().apply { + putParcelable(KEY_APP_ENTITY_32, appEntity32) + putString(EntranceConsts.KEY_GAME_ID, gameId) + putString(EntranceConsts.KEY_GAME_NAME, gameName) + } + } + downloadDialog.show( + fragmentActivity.supportFragmentManager, + VSpace32NewDialogFragment::class.java.name + ) + } + + private fun hasDialogDisplayedInCurrentActivity(fragmentActivity: FragmentActivity): Boolean { + val fragments: List = fragmentActivity.supportFragmentManager.fragments + fragments.forEach { fragment -> + if (fragment is VSpace32NewDialogFragment) return true + } + return false + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/halo/assistant/HaloApp.java b/app/src/main/java/com/halo/assistant/HaloApp.java index d620a12eb4..ddaea4e0af 100644 --- a/app/src/main/java/com/halo/assistant/HaloApp.java +++ b/app/src/main/java/com/halo/assistant/HaloApp.java @@ -459,7 +459,7 @@ public class HaloApp extends MultiDexApplication { LoadedApkHuaWei.hookHuaWeiVerifier(this); DownloadMessageHandler.INSTANCE.init(SimpleDownloadDatabase.getInstance().downloadDao()); - + VHelper.INSTANCE.preparePluginUpdate(); // 预加载游戏库图标 SubjectRecommendEntity barData = HomeBottomBarHelper.getDefaultGameBarData(); if (!TextUtils.isEmpty(barData.getIconSelect())) { diff --git a/app/src/main/res/layout/dialog_vspace_32_new.xml b/app/src/main/res/layout/dialog_vspace_32_new.xml new file mode 100644 index 0000000000..ae0005f624 --- /dev/null +++ b/app/src/main/res/layout/dialog_vspace_32_new.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 34ba352d49..0b4c1b5b67 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 @@ -73,6 +73,7 @@ public class Constants { public static final String GHZS_GAME_ID = "5ae4462c2924bc7936438d07"; public static final String HALO_FUN_GAME_ID = "62bd412bbbf04747cd3de539"; // 畅玩助手ID + public static final String HALO_FUN_NEW_32_GAME_ID = "eeeeeeeeeeeeeeeeeeeeeeee"; // 32位新畅玩助手ID public static final String EXTRA_DOWNLOAD_TYPE = "extra_download_type"; public static final String SILENT_UPDATE = "静默更新";