Compare commits

..

39 Commits

Author SHA1 Message Date
5bd882b489 chore: 版本更新至 5.42.5 2025-07-09 10:34:02 +08:00
1c1d1ff9b9 Merge branch 'hotfix/v5.42.4-1194/GHZSCY-8199' into 'release'
fix: 鸿蒙版本识别错误 https://jira.shanqu.cc/browse/GHZSCY-8199

See merge request halo/android/assistant-android!2228
2025-07-09 09:34:06 +08:00
a4e806d536 fix: 鸿蒙版本识别错误 https://jira.shanqu.cc/browse/GHZSCY-8199 2025-07-08 17:36:11 +08:00
122a0b929f Merge branch 'hotfix/v5.42.4-1194/GHZS-8203' into 'release'
fix: 已安装游戏替换问题 https://jira.shanqu.cc/browse/GHZSCY-8203

See merge request halo/android/assistant-android!2227
2025-07-08 17:28:11 +08:00
2a069fb5e7 fix: 已安装游戏替换问题 https://jira.shanqu.cc/browse/GHZSCY-8203 2025-07-08 17:14:49 +08:00
115b6638a8 Merge branch 'hotfix/v5.42.4-1194/huawei-deadsystemexception' into 'release'
fix: 华为系 android 10 设备停用静默获取已安装应用列表功能

See merge request halo/android/assistant-android!2226
2025-07-08 15:42:42 +08:00
ecbdcdced7 fix: 华为系 android 10 设备停用静默获取已安装应用列表功能 2025-07-08 14:54:08 +08:00
01db3b07d4 Merge branch 'fix/GHZSCY-8198' into 'release'
fix:【光环助手】鸿蒙系统安装弹窗「前往设置」按钮点击无反应 https://jira.shanqu.cc/browse/GHZSCY-8198

See merge request halo/android/assistant-android!2225
2025-07-08 09:45:19 +08:00
081658873f fix:【光环助手】鸿蒙系统安装弹窗「前往设置」按钮点击无反应 https://jira.shanqu.cc/browse/GHZSCY-8198 2025-07-08 09:45:19 +08:00
8d7157095d Merge branch 'feat/GHZSCY-8150' into 'release'
feat: GameDetailPageTabSelect埋点事件优化-客户端 https://jira.shanqu.cc/browse/GHZSCY-8150

See merge request halo/android/assistant-android!2224
2025-07-07 15:29:25 +08:00
1eb84ca71a feat: GameDetailPageTabSelect埋点事件优化-客户端 https://jira.shanqu.cc/browse/GHZSCY-8150 2025-07-07 15:27:56 +08:00
9f4149358a Merge branch 'hotfix/v5.42.4-1194/simulator_crash' into 'release'
fix: 修复 mumu 模拟器上 loadDataWithBaseUrl 方法的空指针闪退问题

See merge request halo/android/assistant-android!2223
2025-07-07 14:33:46 +08:00
5451f244bc Merge branch 'hotfix/v5.42.4-1194/subject_tab_crash' into 'release'
fix: 修复进入专题合集页面后快速返回出现的闪退问题...

See merge request halo/android/assistant-android!2222
2025-07-07 11:31:14 +08:00
aca80aceea fix: 修复进入专题合集页面后快速返回出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/456018/?project=22 2025-07-07 11:29:16 +08:00
964b391eec fix: 修复 mumu 模拟器上 loadDataWithBaseUrl 方法的空指针闪退问题 2025-07-07 10:37:08 +08:00
7584da3734 Merge branch 'hotfix/v5.42.4-1194/exposure_crash' into 'release'
fix: 修复曝光获取当前页面名称时偶发的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/456204

See merge request halo/android/assistant-android!2221
2025-06-30 15:01:27 +08:00
62060a5bf0 fix: 修复曝光获取当前页面名称时偶发的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/456204 2025-06-30 14:59:46 +08:00
f49caa11c8 Merge branch 'hotfix/v5.42.4-1194/tab_wrapper_crash' into 'release'
fix: 修复二级多tab导航页显示引导时出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/447802

See merge request halo/android/assistant-android!2219
2025-06-30 14:58:41 +08:00
61c2f48a50 fix: 修复二级多tab导航页显示引导时出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/447802 2025-06-30 14:43:40 +08:00
b9e0585dc9 chore: 版本更新至 5.42.4 2025-06-16 17:31:54 +08:00
9f191832fd Merge branch 'hotfix/v5.42.3-1193/GHZSCY-8143' into 'release'
fix: 修复 dsp 广告曝光上报问题 https://jira.shanqu.cc/browse/GHZSCY-8143

See merge request halo/android/assistant-android!2215
2025-06-16 14:48:43 +08:00
d8ee461a0a fix: 修复 dsp 广告曝光上报问题 2025-06-16 13:58:49 +08:00
99094896b1 Merge branch 'fix/libao_crash' into 'release'
fix: 修复礼包列表偶发闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/455408

See merge request halo/android/assistant-android!2214
2025-06-09 11:10:34 +08:00
23203b0c5d fix: 修复礼包列表偶发闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/455408 2025-06-09 10:46:01 +08:00
4e054aa834 chore: 版本更新至 5.42.3 2025-06-03 11:07:01 +08:00
e36cc54083 Merge branch 'fix/202506/454319' into 'release'
fix:https://sentry.shanqu.cc/organizations/lightgame/issues/454319/?project=22

See merge request halo/android/assistant-android!2213
2025-06-03 11:01:58 +08:00
bc5935d4b4 Merge branch 'hotfix/v5.42.2-1192/filter_crash' into 'release'
fix: 修复游戏屏蔽功能偶发的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/453949

See merge request halo/android/assistant-android!2212
2025-06-03 10:56:07 +08:00
8fc3bb720d fix:https://sentry.shanqu.cc/organizations/lightgame/issues/454319/?project=22 2025-06-03 10:45:27 +08:00
e8b68f889d fix: 修复游戏屏蔽功能偶发的闪退问题 2025-06-03 10:42:36 +08:00
649af64e62 Merge branch 'fix/GHZSCY-8061' into 'release'
fix:【光环助手】自定义专题合集-自定义设置点击问题 https://jira.shanqu.cc/browse/GHZSCY-8061

See merge request halo/android/assistant-android!2211
2025-05-30 13:39:50 +08:00
46516fb9c0 fix:【光环助手】自定义专题合集-自定义设置点击问题 https://jira.shanqu.cc/browse/GHZSCY-8061 2025-05-30 13:39:50 +08:00
eecfdced32 chore: 版本更新至 5.42.2 2025-05-30 11:37:13 +08:00
74d9aaf664 Merge branch 'hotfix/v5.42.1-1191/exposure_crash' into 'release'
fix: 修复曝光收集时的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/454091

See merge request halo/android/assistant-android!2210
2025-05-30 11:35:17 +08:00
28bbb128dd fix: 修复曝光收集时的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/454091 2025-05-30 09:43:19 +08:00
7640812518 chore: 版本更新至 5.42.1 2025-05-29 11:03:59 +08:00
0a30e82e17 Merge branch 'hotfix/v5.42.0-1190/exposure_crash' into 'release'
fix: 修复曝光收集时的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/453915

See merge request halo/android/assistant-android!2208
2025-05-29 11:01:45 +08:00
559951ad82 fix: 修复曝光收集时的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/453915 2025-05-29 10:43:08 +08:00
4a4cba5445 Merge branch 'feat/GHZSCY-8049-merge' into 'release'
feat: 游戏详情UI优化-客户端 https://jira.shanqu.cc/browse/GHZSCY-8049

See merge request halo/android/assistant-android!2209
2025-05-29 10:22:59 +08:00
b6d6568ac9 feat: 游戏详情UI优化-客户端 https://jira.shanqu.cc/browse/GHZSCY-8049 2025-05-29 10:21:47 +08:00
55 changed files with 1327 additions and 1455 deletions

View File

@ -18,6 +18,7 @@ import com.therouter.TheRouter
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.image.ImageInfo
import com.g00fy2.versioncompare.Version
import com.gh.common.exposure.ExposureManager
import com.gh.common.util.DirectUtils.directToLinkPage
import com.gh.common.util.LogUtils
@ -186,11 +187,11 @@ object AdDelegateHelper {
"halo_launch" -> {
config.ownerAd?.startAd?.let { it.id = config.ownerAd.id }
// HarmonyOS 2.2.0 版本不展示第三方开屏广告 (因为会引起奇怪的闪退)
if (MetaUtil.getRom().name == "HarmonyOS"
&& MetaUtil.getRom().versionName == "2.2.0"
&& config.displayRule.adSource == AD_TYPE_SDK) {
// HarmonyOS 4.2.0 版本不展示第三方开屏广告 (因为会引起奇怪的闪退)
if (MetaUtil.getRom().romName == "HarmonyOS"
&& Version(MetaUtil.getRom().romVersion).isLowerThan(Version("4.2.0"))
&& config.displayRule.adSource == AD_TYPE_SDK
) {
return
}

View File

@ -390,7 +390,7 @@ public class Config {
"manufacturer", Build.MANUFACTURER,
"model", Build.MODEL,
"android_sdk_version", String.valueOf(Build.VERSION.SDK_INT),
"rom", MetaUtil.INSTANCE.getRom().name() + " " + MetaUtil.INSTANCE.getRom().getVersionName()
"rom", MetaUtil.INSTANCE.getRom().getRomName() + " " + MetaUtil.INSTANCE.getRom().getRomVersion()
);
RetrofitManager.getInstance()

View File

@ -16,6 +16,7 @@ class DefaultExposureStateChangeListener : IExposureStateChangeListener {
val exposureStatus = if (inExposure) "曝光中" else "结束曝光"
val isCPMExposureEvent = exposureEvent.payload.miniGameType == Constants.WECHAT_MINI_GAME_CPM
val isDSPExposureEvent = exposureEvent.payload.miniGameType == Constants.DSP_GAME
Utils.log(
RecyclerViewExposureHelper.TAG,
@ -29,6 +30,12 @@ class DefaultExposureStateChangeListener : IExposureStateChangeListener {
"上报 CPM 曝光 ${exposureEvent.payload.gameName} ${exposureEvent.id}"
)
ExposureManager.logCPM(exposureEvent)
} else if (isDSPExposureEvent && inExposure) {
Utils.log(
RecyclerViewExposureHelper.TAG,
"上报 DSP 曝光 ${exposureEvent.payload.gameName} ${exposureEvent.id}"
)
ExposureManager.logDSP(exposureEvent)
}
if (!inExposure

View File

@ -111,6 +111,12 @@ object ExposureManager {
}
}
fun logDSP(event: ExposureEvent) {
AppExecutor.logExecutor.execute {
DspReportHelper.report(event.payload.showUrl)
}
}
/**
* @param forcedUpload Ignore all restrictions.
*/

View File

@ -73,7 +73,7 @@ object RegionSettingHelper {
if (list is ArrayList) return list
}
val listCopy: ArrayList<GameEntity> = if (list is ArrayList) list else ArrayList(list)
val listCopy: ArrayList<GameEntity> = ArrayList(list)
listCopy.removeAll { mFilterGameIdSet?.contains(it.id) ?: false }
return listCopy
}

View File

@ -108,21 +108,32 @@ object GameSubstituteRepositoryHelper {
var thisPositionNeedToBeReplaced = false
// 检查是否已安装该游戏里同包名的 APK
for (apk in game.getApk()) {
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
if (game.getApk().size == 1) {
val apk = game.getApk().firstOrNull()
// 若该游戏只有一个 APK且该 APK 的包名在本地已安装的包名列表中
if (PackageHelper.localPackageNameSet.contains(apk?.packageName)) {
// 将该位置的游戏标记为需要替换
positionOfGameToBeReplacedList.add(index)
thisPositionNeedToBeReplaced = true
break
}
} else {
// 检查是否已安装该游戏里同包名的 APK
for (apk in game.getApk()) {
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
// 将该位置的游戏标记为需要替换
positionOfGameToBeReplacedList.add(index)
thisPositionNeedToBeReplaced = true
break
}
}
}
// 检查是否已安装该游戏 id
if (PackagesManager.getInstalledDataByGameId(game.id) != null) {
if (!thisPositionNeedToBeReplaced && PackagesManager.getInstalledDataByGameId(game.id) != null) {
// 将该位置的游戏标记为需要替换
positionOfGameToBeReplacedList.add(index)
thisPositionNeedToBeReplaced = true
break
continue
}
// 若此游戏所包含的 apk 没有已安装,那么再检查是否已安装有预设相关包名
@ -152,11 +163,19 @@ object GameSubstituteRepositoryHelper {
if (mGameCollectionList.isNullOrEmpty()) return
// 临时的游戏 ID 列表(包含 gameList 的游戏),避免重复替换
val tempDisplayingGameIdSet = HashSet(displayingGameIdSet)
gameList.forEach {
tempDisplayingGameIdSet.add(it.id)
}
for (position in positionOfGameToBeReplacedList) {
val validGame = getValidGame(relatedCollectionId, displayingGameIdSet)
val validGame = getValidGame(relatedCollectionId, tempDisplayingGameIdSet)
validGame?.let {
gameList[position] = it
displayingGameIdSet.add(it.id)
tempDisplayingGameIdSet.add(it.id)
}
}
}

View File

@ -245,6 +245,7 @@ public class LogUtils {
object.put("jnfj", MetaUtil.getBase64EncodedIMEI());
object.put("G_ID", UserManager.getInstance().getDeviceId());
object.put("oaid", HaloApp.getInstance().getOAID());
object.put("rom", MetaUtil.getMeta().getRom());
} catch (JSONException e) {
e.printStackTrace();
}
@ -264,6 +265,7 @@ public class LogUtils {
object.put("channel", HaloApp.getInstance().getChannel());
object.put("dia", MetaUtil.getBase64EncodedAndroidId());
object.put("oaid", MetaUtil.INSTANCE.getMeta().getOaid());
object.put("rom", MetaUtil.getMeta().getRom());
object.put("time", Utils.getTime(context));
object.put("network", DeviceUtils.getNetwork(context));
object.put("user_id", UserManager.getInstance().getUserId());
@ -289,6 +291,7 @@ public class LogUtils {
metaObject.put("channel", meta.getChannel());
metaObject.put("gid", meta.getGid());
metaObject.put("oaid", meta.getOaid());
metaObject.put("rom", MetaUtil.getMeta().getRom());
metaObject.put("jnfj", MetaUtil.getBase64EncodedIMEI());
metaObject.put("mac", meta.getMac());
metaObject.put("manufacturer", meta.getManufacturer());
@ -495,6 +498,7 @@ public class LogUtils {
metaObject.put("os", meta.getOs());
metaObject.put("userId", meta.getUserId());
metaObject.put("oaid", HaloApp.getInstance().getOAID());
metaObject.put("rom", MetaUtil.getMeta().getRom());
} catch (JSONException e) {
e.printStackTrace();

View File

@ -33,6 +33,7 @@ import com.lightgame.utils.Utils
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.*
import java.util.HashMap
import java.util.Locale
import java.util.concurrent.Executors
import kotlin.collections.ArrayList
import kotlin.collections.HashSet
@ -288,12 +289,22 @@ object PackageHelper {
* 用户是否已经使用另类方式获取已安装应用列表
*/
private fun isUseAlternativeWayToGetInstalledPackages(): Boolean {
if (isBuggyHuaweiDevice()) {
useAlternativeWayToGetInstalledPackages = false
return false
}
return useAlternativeWayToGetInstalledPackages
|| (SPUtils.getBoolean(SP_GET_INSTALLED_PACKAGES_BY_ALTERNATIVE_API)
.also { useAlternativeWayToGetInstalledPackages = it })
}
private fun updateUseAlternativeWayToGetInstalledPackages() {
if (isBuggyHuaweiDevice()) {
useAlternativeWayToGetInstalledPackages = false
return
}
// 启用另类获取已安装应用列表的 API
useAlternativeWayToGetInstalledPackages = true
SPUtils.setBoolean(SP_GET_INSTALLED_PACKAGES_BY_ALTERNATIVE_API, true)
@ -478,7 +489,12 @@ object PackageHelper {
/**
* 是否支持动态获取已安装应用列表权限
*/
fun isSupportGetInstalledAppsPermission(context: Context): Boolean {
private fun isSupportGetInstalledAppsPermission(context: Context): Boolean {
if (isBuggyHuaweiDevice()) {
// 华为系 Android 10 设备存在 bug调用过多可能会触发 DeadSystemException
return false
}
if (isUseAlternativeWayToGetInstalledPackages()) {
// 已经使用另类获取已安装应用列表形式,强制判定为不支持动态获取已安装应用列表权限
return false
@ -789,4 +805,13 @@ object PackageHelper {
return packageList
}
private fun isBuggyHuaweiDevice(): Boolean {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
val manufacturer = Build.MANUFACTURER.lowercase(Locale.CHINA) ?: ""
return manufacturer == "huawei" || manufacturer == "honor"
} else {
return false
}
}
}

View File

@ -37,7 +37,7 @@ public class PostCommentUtils {
device.put("model", Build.MODEL);
device.put("manufacturer", Build.MANUFACTURER);
device.put("android_version", android.os.Build.VERSION.RELEASE);
device.put("rom", MetaUtil.INSTANCE.getRom().name() + " " + MetaUtil.INSTANCE.getRom().getVersionName());
device.put("rom", MetaUtil.INSTANCE.getRom().getRomName() + " " + MetaUtil.INSTANCE.getRom().getRomVersion());
content.put("device", device);
} catch (Exception e) {
e.printStackTrace();

View File

@ -9,15 +9,14 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.gh.common.constant.Config
import com.gh.gamecenter.common.utils.DialogHelper
import com.gh.gamecenter.entity.NewApiSettingsEntity
import com.lightgame.utils.Utils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.DialogHelper
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.enlargeTouchArea
import com.gh.gamecenter.common.utils.setDrawableEnd
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.entity.NewApiSettingsEntity
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
/**
* 处理厂商纯净/安全模式的辅助类
@ -313,9 +312,11 @@ object PureModeHelper {
intent.setPackage("com.huawei.security.privacycenter")
intent.setAction("com.huawei.securitycenter.PURE_MODE_ACTIVITY")
intent.putExtra("intent_from_settings", true)
context.startActivity(intent)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
HaloApp.getInstance().startActivity(intent)
} catch (_: Exception) {
toSystemSettings(context)
}
}

View File

@ -9,7 +9,11 @@ import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.common.exposure.meta.MetaUtil.getMeta
import com.gh.gamecenter.common.loghub.LoghubUtils
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.DeviceUtils
import com.gh.gamecenter.common.utils.asVGame
import com.gh.gamecenter.common.utils.getExtension
import com.gh.gamecenter.common.utils.getMetaExtra
import com.gh.gamecenter.common.utils.isSimulatorGame
import com.gh.ndownload.NDataChanger
import com.gh.ndownload.NDownloadBridge
import com.halo.assistant.HaloApp
@ -427,6 +431,7 @@ object DownloadDataHelper {
metaObject.put("channel", meta.channel)
metaObject.put("gid", meta.gid)
metaObject.put("oaid", meta.oaid)
metaObject.put("rom", meta.rom)
metaObject.put("manufacturer", meta.manufacturer)
metaObject.put("model", meta.model)
metaObject.put("network", DeviceUtils.getNetwork(context))

View File

@ -3,9 +3,6 @@ package com.gh.download
import android.annotation.SuppressLint
import android.text.TextUtils
import com.gh.common.util.*
import com.gh.common.util.DataCollectionUtils
import com.gh.common.util.PackageInstaller
import com.gh.common.util.PackageUtils
import com.gh.common.xapk.XapkInstaller
import com.gh.download.server.BrowserInstallHelper
import com.gh.gamecenter.common.constant.Constants
@ -33,9 +30,7 @@ import com.lightgame.download.DownloadEntity
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONException
import org.json.JSONObject

View File

@ -7,6 +7,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.common.DefaultUrlHandler
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.loadDataCompat
import com.gh.gamecenter.databinding.DownloadDialogInstructionItemBinding
class DownloadDialogInstructionItemViewHolder(val binding: DownloadDialogInstructionItemBinding) :
@ -14,11 +15,8 @@ class DownloadDialogInstructionItemViewHolder(val binding: DownloadDialogInstruc
fun bindItem(listData: List<DownloadDialogItemData>, position: Int, entrance: String) {
val instruction = listData[position].instruction
binding.webView.loadDataWithBaseURL(
null,
binding.webView.loadDataCompat(
"<body style='margin:0;padding:0;color:#666666;font-size:12px;line-height:18px;'>$instruction</body>",
"text/html",
"utf-8", null
)
binding.webView.settings
binding.webView.setBackgroundColor(Color.TRANSPARENT)

View File

@ -9,6 +9,7 @@ import androidx.fragment.app.FragmentActivity
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.common.utils.loadDataCompat
import com.gh.gamecenter.databinding.DialogDownloadLinkBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.halo.assistant.HaloApp
@ -27,10 +28,7 @@ class DownloadLinkDialog : BaseDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val binding: DialogDownloadLinkBinding = DialogDownloadLinkBinding.inflate(layoutInflater, container, false)
binding.title.text = mLinkEntity?.title
binding.webView.loadDataWithBaseURL(
null,
mLinkEntity?.content ?: "", "text/html", "utf-8", null
)
binding.webView.loadDataCompat(mLinkEntity?.content ?: "")
binding.confirm.setOnClickListener {
dismissAllowingStateLoss()

View File

@ -886,7 +886,7 @@ class GameDetailViewModel(
params["source"] = HaloApp.getInstance().application.getString(R.string.app_name)
params["jnfj"] = MetaUtil.getBase64EncodedIMEI()
params["manufacturer"] = Build.MANUFACTURER
params["rom"] = MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName
params["rom"] = MetaUtil.getRom().romName + " " + MetaUtil.getRom().romVersion
params["suggestion_type"] = "游戏求更新"
params["game_id"] = game?.id ?: ""

View File

@ -815,7 +815,10 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
downloadStatus = gameEntity?.downloadStatusChinese ?: "",
gameType = gameEntity?.categoryChinese ?: "",
position = position,
tabContent = tabEntity.name
tabContent = tabEntity.name,
linkType = tabEntity.link?.type ?: "",
linkId = tabEntity.link?.link ?: "",
linkText = tabEntity.link?.text ?: ""
)
val entrance = if (mEntrance.contains("论坛详情")) "论坛" else "游戏"

View File

@ -7,7 +7,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import android.widget.LinearLayout
import androidx.core.view.children
import androidx.core.view.forEach
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.RecyclerView
@ -117,7 +117,7 @@ class GameLibaoAdapter(
binding.horizontalScrollView.goneIf(libaoEntity.materials.isEmpty()) {
if (binding.imagesContainer.tag == libaoEntity.id) {
binding.imagesContainer.children.forEach { view ->
binding.imagesContainer.forEach { view ->
if (view is SimpleDraweeView) {
view.hierarchy.roundingParams = RoundingParams().apply {
setCornersRadius(4F.dip2px().toFloat())

View File

@ -541,7 +541,7 @@ class RatingEditActivity : ToolBarActivity(), KeyboardHeightObserver {
jsonObject.put("game_version", gameVersion)
jsonObject.put("source", if (mFromAmway) "anliwall" else "game_detail")
jsonObject.put("plugin_version", PackageUtils.getMetaData(this, mInstallPackageName, "gh_version"))
jsonObject.put("rom", MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName)
jsonObject.put("rom", MetaUtil.getRom().romName + " " + MetaUtil.getRom().romVersion)
jsonObject.put("again", again)
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())

View File

@ -246,9 +246,10 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
setNavigationTitle(it.title)
})
dataList.observe(viewLifecycleOwner) { (shouldScrollToTop, data) ->
adapter.submitList(data) {
dataList.observe(viewLifecycleOwner) {
adapter.submitList(it) {
if (shouldScrollToTop) {
shouldScrollToTop = false
binding.gameList.scrollToPosition(0)
}
}

View File

@ -29,7 +29,7 @@ interface OnCustomPageEventListener {
/**
* 换一批
*/
fun onChangeABatch(componentId: String, subjectEntity: SubjectEntity)
fun onChangeABatch(subjectEntity: SubjectEntity)
fun onChangeAppBarColor(color: Int)
@ -56,10 +56,7 @@ interface OnCustomPageEventListener {
/**
* 点击进入专题详情
*/
fun navigateSubjectDetailPage(
item: CustomSubjectCollectionItem,
subject: CustomPageData.LinkColumnCollection.CustomSubjectEntity
)
fun navigateSubjectDetailPage(item: CustomSubjectCollectionItem, subject: CustomPageData.LinkColumnCollection.CustomSubjectEntity)
/**

View File

@ -35,11 +35,9 @@ class SubjectEventHelper(viewModel: CustomPageViewModel) : CustomPageItemChildEv
gameEntity.tempDspLogMap = map.toMap() // Return an immutable copy
}
}
gameEntity.isMiniGame() -> {
tracker.trackMiniGameClick(_item, gameEntity)
}
else -> {
tracker.trackColumnClick(_item, gameEntity, "游戏")
}
@ -53,11 +51,9 @@ class SubjectEventHelper(viewModel: CustomPageViewModel) : CustomPageItemChildEv
gameEntity.isDspGame -> {
tracker.trackDspGameClick(_item, gameEntity, "按钮", "自定义页面")
}
gameEntity.isMiniGame() -> {
tracker.trackMiniGameClick(_item, gameEntity)
}
else -> {
tracker.trackColumnClick(_item, gameEntity, "按钮")
}
@ -71,9 +67,9 @@ class SubjectEventHelper(viewModel: CustomPageViewModel) : CustomPageItemChildEv
}
}
fun onChangeABatch(componentId: String, subject: SubjectEntity) {
fun onChangeABatch(subject: SubjectEntity) {
tracker.trackColumnClick(_item, null, "右上角", "换一批")
viewModel.onChangeABatch(componentId,subject)
viewModel.onChangeABatch(subject)
}
fun onMoreClick(link: LinkEntity) {

View File

@ -1,185 +0,0 @@
package com.gh.gamecenter.home.custom.model
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.entity.PKEntity
import com.gh.gamecenter.entity.AmwayCommentEntity
import com.gh.gamecenter.entity.DiscoveryCardEntity
import com.gh.gamecenter.entity.HomeItemTestV2Entity
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.feature.entity.AcctRecord
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_COLUMN_COLLECTION
import com.gh.vspace.VGameItemData
/**
* 接口返回的原始数据模型,最终需要转化成 CustomPageItem 在ui层呈现
*/
sealed class CustomItemDTO(
val componentId: String, // 当前组件的唯一标识,用于后续更新单个数据时,快速找到目标数据
val link: LinkEntity
)
// 游戏专题:展开大图样式专用
class GameItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
val data: GameEntity,
val linkColumn: SubjectEntity?,
) : CustomItemDTO(_componentId, _link)
//游戏专题
data class SubjectItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
var data: SubjectEntity
) : CustomItemDTO(_componentId, _link) {
val scrollState = ScrollState()
}
// 专题合集/游戏单合集
class CollectionItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
val data: CustomPageData.LinkColumnCollection
) : CustomItemDTO(_componentId, _link) {
val isSubjectCollection: Boolean // 是否是专题合集(还有可能是游戏单合集)
get() = link.type == CUSTOM_LINK_TYPE_COLUMN_COLLECTION
var showPage: Int = 0
var loadPage: Int = 1
var isLoadedEnd: Boolean = false
val uiState = UIState()
/**
* 保存ui层状态
*/
data class UIState(
var isBackToStart: Boolean = false
)
}
// 最近在玩
data class RecentGamesItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
var data: List<VGameItemData>
) : CustomItemDTO(_componentId, _link)
// 微信小游戏-最近在玩
data class RecentWechatMiniGamesItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
var data: List<GameEntity>
) : CustomItemDTO(_componentId, _link)
// qq小游戏-最近在玩
data class RecentQqMiniGamesItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
var data: List<GameEntity>,
val linkQqGameRecentlyPlayed: CustomPageData.LinkRecentlyPlayed
) : CustomItemDTO(_componentId, _link)
// 加速游戏最近在玩
data class RecentAcceleratorGamesItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
var data: List<AcctRecord>,
val moreLink: LinkEntity?
) : CustomItemDTO(_componentId, _link)
// qq小游戏专题
data class QqMiniGamesItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
val data: SubjectEntity
) : CustomItemDTO(_componentId, _link) {
val scrollState = ScrollState()
}
// 微信小游戏专题
data class WechatMiniGamesItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
val data: SubjectEntity
) : CustomItemDTO(_componentId, _link) {
val scrollState = ScrollState()
}
// 微信小游戏CPM专题组件
data class WeChatMiniGamesCPMSubjectItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
var data: SubjectEntity
) : CustomItemDTO(_componentId, _link){
val scrollState = ScrollState()
}
// DSP专题组件
data class DSPItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
var data: SubjectEntity
) : CustomItemDTO(_componentId, _link){
val scrollState = ScrollState()
}
// 插件化区域
data class PluginItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
var data: List<GameEntity>
) : CustomItemDTO(_componentId, _link)
// 新游开测
data class GameTestV2ItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
val data: HomeItemTestV2Entity
) : CustomItemDTO(_componentId, _link)
// 光环推荐
data class DiscoverCardItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
var data: DiscoveryCardEntity?
) : CustomItemDTO(_componentId, _link)
// 安利墙
data class AmwayItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
val data: List<AmwayCommentEntity>
) : CustomItemDTO(_componentId, _link)
// 内容卡片
data class ContentCardItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
val data: CustomPageData.ContentCard
) : CustomItemDTO(_componentId, _link)
// 通用内容合集
data class CommonContentCollectionItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
val data: CustomPageData.CommonContentCollection
) : CustomItemDTO(_componentId, _link)
// PK
data class PKItemDTO(
private val _componentId: String,
private val _link: LinkEntity,
var data: PKEntity?
) : CustomItemDTO(_componentId, _link)
class ScrollState(
var scrolledOffset: Int = 0
)

View File

@ -1,42 +0,0 @@
package com.gh.gamecenter.home.custom.model
import android.util.LruCache
import com.gh.gamecenter.feature.entity.GameEntity
import io.reactivex.Observable
import io.reactivex.Single
class CustomPageCacheDataSource {
// 计算内存缓存大小这里取应用最大可用内存的1/8单位KB
private fun calculateMemoryCacheSize(): Int {
val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt()
return maxMemory / 8
}
private val memoryCache: LruCache<String, List<GameEntity>> =
object : LruCache<String, List<GameEntity>>(calculateMemoryCacheSize()) {
override fun sizeOf(key: String, value: List<GameEntity>): Int {
return value.toTypedArray().size / 1024 // 单位KB
}
}
fun getGameList(subjectId: String) = Observable.create {
val gameList = memoryCache.get(subjectId)
if (gameList.isNullOrEmpty()) {
it.onComplete()
} else {
it.onNext(gameList)
}
}
fun putGameList(subjectId: String?, data: List<GameEntity>) {
if (!subjectId.isNullOrBlank()) {
memoryCache.put(subjectId, data)
}
}
fun onClear() {
memoryCache.evictAll()
}
}

View File

@ -15,10 +15,10 @@ import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.vspace.VGameItemData
abstract class CustomPageItem(
// 当前模块在数据列表中的位置注意非ui页面的位置而是数据列表中的位置因为某条数据可能会拆分成多个item
val link: LinkEntity,
var position: Int,// 当前模块在数据列表中的位置注意非ui页面的位置而是数据列表中的位置因为某条数据可能会拆分成多个item
val componentPosition: Int,
val componentId: String,
var position: Int,
val componentPosition: Int
) {
abstract val itemType: Int
@ -362,11 +362,9 @@ abstract class CustomPageItem(
data class CustomSubjectItem(
private val _link: LinkEntity,
val data: SubjectEntity,
private val scrollState: ScrollState,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String,
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = subjectTypeMap[data.type] ?: CUSTOM_PAGE_ITEM_TYPE_INVALID
@ -381,11 +379,7 @@ data class CustomSubjectItem(
get() = data.data ?: emptyList()
// 临时变量,记录横向列表滚动的距离
var scrolledOffset: Int
get() = scrollState.scrolledOffset
set(value) {
scrollState.scrolledOffset = value
}
var scrolledOffset: Int = 0
val exposureSource: List<ExposureSource>
get() = listOf(ExposureSource("专题", "${data.name ?: ""}+$componentStyle+${data.id}"))
@ -426,7 +420,7 @@ data class CustomSubjectItem(
if (latestDayBeforeTodayPair.first >= testDayOffset) {
latestDayBeforeTodayPair = Pair(testDayOffset, index)
}
} else {
} else if (testDayOffset > 0) {
if (testDayOffset <= latestDayAfterTodayPair.first) {
latestDayAfterTodayPair = Pair(testDayOffset, index)
}
@ -446,12 +440,11 @@ data class CustomSubjectItem(
data class CustomSplitSubjectItem(
private val _link: LinkEntity,
var data: SubjectEntity,
val step: Int,
val startChildPosition: Int,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String,
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
val step: Int,
val startChildPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
var splitItemCount: Int = -1 // 游戏专题拆分出来的子项数量
@ -516,9 +509,8 @@ data class CustomGameItem(
val linkColumn: SubjectEntity?,
val childPosition: Int,
private val _position: Int, // 当前 item 在 ui 中的位置
private val _componentPosition: Int, // 当前组件的位置
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int // 当前组件的位置
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_GAME_HOME_GAME_ITEM
@ -554,11 +546,9 @@ data class CustomGameItem(
data class CustomSubjectCollectionItem(
private val _link: LinkEntity,
val data: CustomPageData.LinkColumnCollection,
val uiState: CollectionItemDTO.UIState,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
val isSubjectCollection: Boolean // 是否是专题合集(还有可能是游戏单合集)
get() = link.type == CUSTOM_LINK_TYPE_COLUMN_COLLECTION
@ -582,14 +572,19 @@ data class CustomSubjectCollectionItem(
emptyList()
}
//当前显示的页码
// 临时变量:记录合集中,轮换刷新时当前显示的页码
var showPage: Int = 0
var isBackToStart: Boolean
get() = uiState.isBackToStart
set(value) {
uiState.isBackToStart = value
}
// 临时变量:记录合集中,轮换刷新时当前加载的页码
var loadPage: Int = 1
// 临时变量记录点击轮换刷新时是否正在loading
var isLoading: Boolean = false
// 临时变量,数据是否已全部加载完毕
var isLoadedEnd: Boolean = false
var isBackToStart = true
val showSubject: CustomPageData.LinkColumnCollection.CustomSubjectEntity?
get() = data.data.getOrNull(showPage % data.data.size)
@ -597,12 +592,14 @@ data class CustomSubjectCollectionItem(
override fun doAreItemsTheSame(other: CustomPageItem): Boolean {
return other is CustomSubjectCollectionItem
&& data.id == other.data.id
}
override fun doAreContentsTheSames(other: CustomPageItem): Boolean {
return other is CustomSubjectCollectionItem
&& showPage == other.showPage
&& isLoading == other.isLoading
&& isLoadedEnd == other.isLoadedEnd
&& showSubject == other.showSubject
}
}
@ -611,9 +608,8 @@ data class CustomRecentGamesItem(
private val _link: LinkEntity,
val data: List<VGameItemData>,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_RECENT_PLAY
@ -632,9 +628,8 @@ data class CustomRecentWeChatMiniGamesItem(
private val _link: LinkEntity,
val data: List<GameEntity>,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_MINI_GAME_RECENT_PLAY
@ -652,9 +647,8 @@ data class CustomWeChatMiniGamesCPMSubjectItem(
private val _link: LinkEntity,
val data: SubjectEntity,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_MINI_GAME_RECENT_PLAY
@ -673,9 +667,8 @@ data class CustomRecentQqMiniGamesItem(
val data: List<GameEntity>,
val linkQqGameRecentlyPlayed: CustomPageData.LinkRecentlyPlayed,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_MINI_GAME_RECENT_PLAY
@ -697,9 +690,8 @@ data class CustomRecentAcceleratorItem(
val data: List<AcctRecord>,
val moreLink: LinkEntity?,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_ACCELERATOR_RECENT_PLAYED
@ -721,9 +713,8 @@ data class CustomPluginItem(
private val _link: LinkEntity,
val data: List<GameEntity>,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_PLUGIN
@ -744,9 +735,8 @@ data class CustomGameTestV2Item(
private val _link: LinkEntity,
val data: HomeItemTestV2Entity,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_NEW_GAME_TEST
@ -764,9 +754,8 @@ data class CustomDiscoverCardItem(
private val _link: LinkEntity,
val data: DiscoveryCardEntity?,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
val spanCount = 3
@ -792,9 +781,8 @@ data class CustomAmwayItem(
private val _link: LinkEntity,
val data: List<AmwayCommentEntity>,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_AMWAY_WALL
@ -812,9 +800,8 @@ data class CustomContentCardItem(
private val _link: LinkEntity,
val data: CustomPageData.ContentCard,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_CONTENT_CARD
@ -835,9 +822,8 @@ data class CustomCommonContentCollectionItem(
private val _link: LinkEntity,
val data: CustomPageData.CommonContentCollection,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = if (data.layout == COMMON_CONTENT_COLLECTION_LAYOUT_BANNER) {
@ -875,11 +861,10 @@ data class CustomCommonContentCollectionItem(
data class CustomSplitCommonContentCollectionItem(
private val _link: LinkEntity,
val data: CustomPageData.CommonContentCollection,
val leftPosition: Int,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
val leftPosition: Int,
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType
get() = commonContentCollection[data.layout] ?: CUSTOM_PAGE_ITEM_TYPE_INVALID
@ -912,9 +897,8 @@ data class CustomPKItem(
private val _link: LinkEntity,
val data: PKEntity?,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_PK
@ -932,9 +916,8 @@ data class CustomDspPlaceholderItem(
private val _link: LinkEntity,
val data: SubjectEntity,
private val _position: Int,
private val _componentPosition: Int,
private val _componentId: String
) : CustomPageItem(_link, _position, _componentPosition, _componentId) {
private val _componentPosition: Int
) : CustomPageItem(_link, _position, _componentPosition) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_MINI_GAME_RECENT_PLAY
@ -947,9 +930,14 @@ data class CustomDspPlaceholderItem(
}
}
object CustomFooterItem : CustomPageItem(LinkEntity(), -1, -1, "") {
object CustomFooterItem : CustomPageItem(LinkEntity(), -1, -1) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_FOOTER
}
object CustomInvalidItem : CustomPageItem(LinkEntity(), -2, -2) {
override val itemType: Int
get() = CUSTOM_PAGE_ITEM_TYPE_INVALID
}

View File

@ -1,10 +1,8 @@
package com.gh.gamecenter.home.custom.model
import android.content.Context
import android.util.LruCache
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.feature.entity.FloatingWindowEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.halo.assistant.HaloApp
import java.text.SimpleDateFormat
import java.util.*

View File

@ -56,17 +56,12 @@ class CustomPageRemoteDataSource(
}
}
fun loadColumnsCollectionContents(
collectionId: String,
page: Int
): Single<MutableList<CustomPageData.LinkColumnCollection.CustomSubjectEntity>> =
newApi.getColumnsCollectionContents(collectionId, "component", page, 1)
fun loadGameCollectionContents(
collectionId: String,
page: Int
): Single<MutableList<CustomPageData.LinkColumnCollection.CustomSubjectEntity>> =
newApi.getGameCollectionContents(collectionId, "component", page, 1)
fun loadCollectionContent(item: CustomSubjectCollectionItem): Single<List<CustomPageData.LinkColumnCollection.CustomSubjectEntity>> =
if (item.isSubjectCollection) {
newApi.getColumnsCollectionContents(item.data.id, "component", item.loadPage + 1, 1)
} else {
newApi.getGameCollectionContents(item.data.id, "component", item.loadPage + 1, 1)
}
fun loadChangeSubjectGame(subjectEntity: SubjectEntity): Observable<List<GameEntity>> =
if (subjectEntity.isQQColumn) {

View File

@ -2,13 +2,10 @@ package com.gh.gamecenter.home.custom.model
import androidx.annotation.MainThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asLiveData
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.HomePluggableHelper
import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.Constants.SP_HIDDEN_NOTIFICATIONS
import com.gh.gamecenter.common.utils.observableToMain
@ -20,9 +17,7 @@ import com.gh.gamecenter.entity.DiscoveryGameCardEntity
import com.gh.gamecenter.entity.DiscoveryGameCardLabel
import com.gh.gamecenter.feature.entity.AcctRecord
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PluginLocation
import com.gh.gamecenter.gamedetail.accelerator.AccelerationDataBase
import com.gh.gamecenter.packagehelper.PackageRepository
import com.gh.gamecenter.retrofit.RetrofitManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
@ -39,30 +34,6 @@ class CustomPageShareRepository private constructor() {
private val compositeDisposable = CompositeDisposable()
private val _pluginGames = MediatorLiveData<List<GameEntity>>().apply {
addSource(PackageRepository.gameUpdateLiveData) { updateList ->
val gameList = arrayListOf<GameEntity>()
updateList.forEach {
if (it.isPluggable && it.indexPlugin == "open" && it.isShowPlugin(PluginLocation.only_index)) {
val game = it.transformGameEntity()
if (HomePluggableHelper.showHomePluggable(game)) {
game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
gameList.add(game)
}
}
}
// 下载七天排序
gameList.sortWith { o1, o2 -> o2.download - o1.download }
value = gameList
}
}
val pluginGames: LiveData<List<GameEntity>> = _pluginGames
fun temporarilyBlockGameInPluginItem(gameId: String) {
val gameList = _pluginGames.value ?: return
_pluginGames.value = gameList.filterNot { it.id == gameId }
}
private val _discoverData = MutableLiveData<DiscoveryCardEntity>()
val discoverData: LiveData<DiscoveryCardEntity> = _discoverData

View File

@ -26,7 +26,10 @@ import com.gh.gamecenter.home.custom.createExposureEvent
import com.gh.gamecenter.home.custom.eventlistener.CustomPageItemChildEventHelper
import com.gh.gamecenter.home.custom.eventlistener.GameSubjectCollectionEventHelper
import com.gh.gamecenter.home.custom.eventlistener.SubjectEventHelper
import com.gh.gamecenter.home.custom.model.*
import com.gh.gamecenter.home.custom.model.CustomPageItem
import com.gh.gamecenter.home.custom.model.CustomSplitSubjectItem
import com.gh.gamecenter.home.custom.model.CustomSubjectCollectionItem
import com.gh.gamecenter.home.custom.model.CustomSubjectItem
import com.lightgame.download.DownloadEntity
abstract class BaseCustomViewHolder(
@ -95,14 +98,7 @@ abstract class BaseCustomViewHolder(
titleBinding.root.goneIf(false)
setSubjectTitle(
titleBinding,
CustomSubjectItem(
item.link,
item.data,
ScrollState(),
item.position,
item.componentPosition,
item.componentId
),
CustomSubjectItem(item.link, item.data, item.position, item.componentPosition),
eventHelper,
titleType
)
@ -193,7 +189,7 @@ abstract class BaseCustomViewHolder(
when (subject.home) {
HOME_CHANGE -> {
// 点击换一批
eventHelper.onChangeABatch(item.componentId, subject)
eventHelper.onChangeABatch(subject)
}
HOME_MORE -> {

View File

@ -88,7 +88,7 @@ class CustomRefreshIconViewHolder(
} else {
_subjectEntity = subjectEntity
}
println("kayn -->isBackToStart:${item.isBackToStart}")
// 如果游戏全部被屏蔽,自动加载下一页
if (subjectEntity.games.isEmpty()) {
childEventHelper.onRotateRefresh()

View File

@ -38,12 +38,19 @@ object MiniGameRecentlyPlayUseCase {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<List<GameEntity>>() {
override fun onSuccess(data: List<GameEntity>) {
if (data.isNotEmpty()) {
if (gameType == Constants.QQ_MINI_GAME) {
_qqRecentGamesItemLiveData.value = data
} else {
_wechatRecentGamesItemLiveData.value = data
}
if (gameType == Constants.QQ_MINI_GAME) {
_qqRecentGamesItemLiveData.value = data
} else {
_wechatRecentGamesItemLiveData.value = data
}
}
override fun onFailure(exception: Exception) {
super.onFailure(exception)
if (gameType == Constants.QQ_MINI_GAME) {
_qqRecentGamesItemLiveData.value = emptyList()
} else {
_wechatRecentGamesItemLiveData.value = emptyList()
}
}
})
@ -83,7 +90,10 @@ object MiniGameRecentlyPlayUseCase {
_qqRecentGamesItemLiveData.value
} else {
_wechatRecentGamesItemLiveData.value
} ?: emptyList()
} ?: let {
loadRecentlyPlayedMiniGameList(gameType)// 最近在玩数据为空时,则调用接口获取数据
emptyList()
}
fun clearRecentlyPlayedMiniGameList(gameType: String = "") {
when (gameType) {

View File

@ -6,7 +6,6 @@ import com.gh.gamecenter.common.livedata.NonStickyMutableLiveData
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.feature.entity.GameEntity
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
/**
@ -15,7 +14,11 @@ import io.reactivex.schedulers.Schedulers
class WGameSubjectCPMListUseCase(
private val repository: WGameSubjectCPMListRepository = WGameSubjectCPMListRepository()
) {
private val compositeDisposable = CompositeDisposable()
/**
* 微信专题CPM请求记录用于避免重复请求以专题ID作为Key
*/
private val requestKeyList = mutableListOf<String>()
/**
* 微信小游戏CPM列表这里的LiveData充当类似于EventBus的角色因此使用NonStickyMutableLiveData
@ -23,18 +26,21 @@ class WGameSubjectCPMListUseCase(
private val _wechatMiniGameCPMListLiveData = NonStickyMutableLiveData<Pair<String, List<GameEntity>>>()
val wechatMiniGameCPMListLiveData: LiveData<Pair<String, List<GameEntity>>> = _wechatMiniGameCPMListLiveData
fun getWechatMiniGameCPMList(componentId: String, minimumSize: Int, onlyFee: Boolean) {
@SuppressLint("CheckResult")
fun getWechatMiniGameCPMList(subjectId: String?, minimumSize: Int, onlyFee: Boolean) {
if (subjectId.isNullOrEmpty() || requestKeyList.contains(subjectId)) {
return
}
requestKeyList.add(subjectId)
repository.getColumn(null, 1, null, null, null, null, minimumSize, onlyFee)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<List<GameEntity>>() {
override fun onSuccess(data: List<GameEntity>) {
_wechatMiniGameCPMListLiveData.value = componentId to data
requestKeyList.remove(subjectId)
_wechatMiniGameCPMListLiveData.value = subjectId to data
}
}).let(compositeDisposable::add)
}
fun onClear() {
compositeDisposable.clear()
})
}
}

View File

@ -6,6 +6,7 @@ import androidx.recyclerview.widget.DiffUtil.ItemCallback
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.debounceActionWithInterval
import com.gh.gamecenter.common.utils.toBinding
import com.gh.gamecenter.common.view.Chips
import com.gh.gamecenter.databinding.ItemColumnCollectionCustomTabBinding
@ -30,8 +31,10 @@ class CustomTabFollowAdapter(private val viewModel: ColumnCollectionTabViewModel
endIcon.setImageResource(R.drawable.ic_basic_x_8_secondary)
endIcon.imageTintList = null
setOnClickListener {
if (!isForbidden) {
viewModel?.addMore(subjectData)
debounceActionWithInterval(500) {
if (!isForbidden) {
viewModel?.addMore(subjectData)
}
}
}
}

View File

@ -6,6 +6,7 @@ import androidx.recyclerview.widget.DiffUtil.ItemCallback
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.debounceActionWithInterval
import com.gh.gamecenter.common.utils.toBinding
import com.gh.gamecenter.common.view.Chips
import com.gh.gamecenter.databinding.ItemColumnCollectionCustomTabBinding
@ -26,7 +27,9 @@ class CustomTabMoreAdapter(private val viewModel: ColumnCollectionTabViewModel?)
startIcon.setImageResource(R.drawable.ic_auxiliary_plus_secondary_8)
startIcon.imageTintList = null
setOnClickListener {
viewModel?.addFollow(subjectData)
debounceActionWithInterval(500) {
viewModel?.addFollow(subjectData)
}
}
}
}

View File

@ -812,6 +812,8 @@ class SubjectTabFragment : ToolbarFragment() {
}
override fun onBackPressed(): Boolean {
if (!isAdded) return super.onBackPressed()
if (binding.settingGuideContainer.isVisible) {
binding.settingGuideContainer.performClick()
return true

View File

@ -118,6 +118,8 @@ class TabWrapperFragment: BaseTabWrapperFragment(), ISmartRefresh, ISmartRefresh
if (shouldShow && guide != null && guidePosition != -1) {
tabLayout?.post {
if (activity == null) return@post
val tabView = tabLayout?.getTabAt(guidePosition)?.view
if (tabView != null) {
if (!isDefaultCustomPageFragment() && priorityChain.isHandlerQueueEmpty()) {
@ -133,7 +135,7 @@ class TabWrapperFragment: BaseTabWrapperFragment(), ISmartRefresh, ISmartRefresh
} else {
multiTabGuideHandler.doPreProcess(
true,
requireActivity(),
activity,
mBaseHandler,
guide,
tabLayout,

View File

@ -243,7 +243,7 @@ class VFeedbackDialogFragment : BaseDialogFragment() {
"source" to HaloApp.getInstance().application.getString(R.string.app_name)
"jnfj" to MetaUtil.getBase64EncodedIMEI()
"manufacturer" to Build.MANUFACTURER
"rom" to MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName
"rom" to MetaUtil.getRom().romName + " " + MetaUtil.getRom().romVersion
"suggestion_type" to "游戏问题"
"game_id" to game.id

View File

@ -152,7 +152,7 @@ class AccelerationUseCase {
"from" to "",
"game_id" to game.id,
"manufacturer" to Build.MANUFACTURER,
"rom" to MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName,
"rom" to MetaUtil.getRom().romName + " " + MetaUtil.getRom().romVersion,
"suggestion_type" to "加速器失败",
"message" to "加速失败, 游戏ID: ${game.id}, 游戏名: ${game.name ?: ""}",
"log" to it

View File

@ -693,7 +693,7 @@ class WebFragment : LazyFragment(), IScrollable {
webview.loadUrl(mWebUrl)
}
} else {
webview.loadDataWithBaseURL(null, mWebUrl, "text/html", "utf-8", null)
webview.loadDataCompat(mWebUrl)
}
}
if (mIsHorizontalDispatcherEnabled) {

View File

@ -15,9 +15,14 @@ import com.tencent.vasdolly.helper.ChannelReaderUtil
class FlavorProviderImp : IFlavorProvider {
private var isInit = false
private val pendingEvent = arrayListOf<String>()
override fun init(application: Application, activity: Activity, activateRatio: Int) {
SMHelper.init(application, getChannelStr(application))
isInit = true
if (HaloApp.getInstance().isBrandNewInstall) {
logEvent("EVENT_ACTIVE")
SPUtils.setLong("TIME_OF_BRAND_NEW_INSTALL", System.currentTimeMillis() / 1000)
@ -31,6 +36,8 @@ class FlavorProviderImp : IFlavorProvider {
SPUtils.setBoolean("SHOULD_SEND_RETENTION_EVENT", false)
}
}
pendingEvent.forEach(SMHelper::onEvent)
pendingEvent.clear()
}
override fun getChannelStr(application: Application): String {
@ -43,7 +50,11 @@ class FlavorProviderImp : IFlavorProvider {
}
override fun logEvent(content: String) {
SMHelper.onEvent(content)
if (isInit) {
SMHelper.onEvent(content)
} else {
pendingEvent.add(content)
}
}
override fun logCoreEvent() {

View File

@ -7,8 +7,8 @@ ext {
targetSdkVersion = 30 // 升级targetSdkVersion到 34 时需要根据官方文档补全前台服务的权限类型。比如 NDownloadServiceKeepAliveService
// application info (每个大版本之间的 versionCode 增加 20)
versionCode = 1210
versionName = "5.43.0"
versionCode = 1195
versionName = "5.42.5"
applicationId = "com.gh.gamecenter"
applicationIdGat = "com.gh.gamecenter.intl"
@ -99,7 +99,7 @@ ext {
verifier = "1.0.6"
skeleton = "1.1.5"
mta = "6.8.0"
romChecker = "1.0.3"
romChecker = "2.0.0"
oss = "2.8.8"
desugarJdkLibs = "1.1.5"
toolargetool = "0.3.0"

View File

@ -39,7 +39,7 @@ class QaFeedbackViewModel(application: Application, private val contentId: Strin
map["source"] = HaloApp.getInstance().getString(R.string.app_name)
map["jnfj"] = getBase64EncodedIMEI()
map["manufacturer"] = Build.MANUFACTURER
map["rom"] = MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName
map["rom"] = MetaUtil.getRom().romName + " " + MetaUtil.getRom().romVersion
val requestBody = map.toRequestBody()
RetrofitManager.getInstance().api

View File

@ -209,7 +209,7 @@ class SuggestViewModel(
"source" to getApplication<Application>().getString(R.string.app_name)
"jnfj" to getBase64EncodedIMEI()
"manufacturer" to Build.MANUFACTURER
"rom" to MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName
"rom" to MetaUtil.getRom().romName + " " + MetaUtil.getRom().romVersion
"suggestion_type" to suggestType
"from" to contact
"contact_func" to contactType.value
@ -318,7 +318,7 @@ class SuggestViewModel(
"source" to getApplication<Application>().getString(R.string.app_name)
"jnfj" to getBase64EncodedIMEI()
"manufacturer" to Build.MANUFACTURER
"rom" to MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName
"rom" to MetaUtil.getRom().romName + " " + MetaUtil.getRom().romVersion
"suggestion_type" to mSuggestType
"app_name" to appName
"owner_type" to copyrightIdentity

View File

@ -63,7 +63,7 @@ dependencies {
kapt "com.google.auto.service:auto-service:${autoServiceVersion}"
api "com.louiscad.splitties:splitties-views-dsl:${splitties}"
api "com.louiscad.splitties:splitties-views-dsl-constraintlayout:${splitties}"
api "com.github.nichbar:AndroidRomChecker:${romChecker}"
api "com.lg:romchecker:${romChecker}"
api "androidx.cardview:cardview:${cardView}"
api "com.google.android.material:material:${material}"
api "com.scwang.smartrefresh:SmartRefreshLayout:${smartRefreshLayout}"

View File

@ -33,7 +33,6 @@ object MetaUtil {
private var rom: Rom? = null
fun refreshMeta() {
val appProvider = TheRouter.get(IAppProvider::class.java)
val buildConfigProvider = TheRouter.get(IBuildConfigProvider::class.java)
val userManagerProvider = TheRouter.get(IUserManagerProvider::class.java)
@ -55,7 +54,7 @@ object MetaUtil {
exposureVersion = buildConfigProvider?.getExposureVersion(),
session_id = Tracker.sessionId,
launch_id = Tracker.launchId,
rom = ""
rom = getRom().romName + " " + getRom().romVersion
)
}
@ -68,7 +67,13 @@ object MetaUtil {
}
fun getRom(): Rom {
if (rom == null) {
val appProvider = TheRouter.get(IAppProvider::class.java)
if (appProvider?.isUserAcceptPrivacyPolicy(HaloApp.getInstance()) == false) {
// 如果用户没有同意隐私政策,则返回一个默认的 Rom 对象
return Rom.create("unknown", "unknown", "unknown")
}
if (rom == null || rom?.romName == "unknown") {
rom = RomIdentifier.getRom()
}
return rom!!

View File

@ -167,20 +167,22 @@ object TrackerLogger {
}
private fun getMeta(): JSONObject {
val (_, _, model, manufacturer, _, _, android_version, network, _, gid, oaid, channel, appVersion, userId) = MetaUtil.getMeta()
val meta = MetaUtil.getMeta()
val metaObject = JSONObject()
try {
metaObject.put("dia", getBase64EncodedAndroidId())
metaObject.put("android_version", android_version)
metaObject.put("app_version", appVersion)
metaObject.put("channel", channel)
metaObject.put("gid", gid)
metaObject.put("oaid", oaid)
metaObject.put("android_version", meta.android_version)
metaObject.put("app_version", meta.appVersion)
metaObject.put("channel", meta.channel)
metaObject.put("gid", meta.gid)
metaObject.put("oaid", meta.oaid)
metaObject.put("rom", meta.rom)
metaObject.put("jnfj", getBase64EncodedIMEI())
metaObject.put("manufacturer", manufacturer)
metaObject.put("model", model)
metaObject.put("network", network)
metaObject.put("user_id", userId)
metaObject.put("manufacturer", meta.manufacturer)
metaObject.put("model", meta.model)
metaObject.put("network", meta.network)
metaObject.put("user_id", meta.userId)
} catch (e: JSONException) {
e.printStackTrace()
}

View File

@ -1494,6 +1494,26 @@ fun WebView.enableForceDark(isDarkModeOn: Boolean) {
}
}
fun WebView.loadDataCompat(data: String, mimeType: String = "text/html", encoding: String = "utf-8") {
try {
this.loadDataWithBaseURL(
null,
data,
mimeType,
encoding,
null
)
} catch (e: NullPointerException) {
this.loadDataWithBaseURL(
"localhost",
data,
"text/html",
"utf-8",
null
)
}
}
/**
* WebView是否启用强制深色模式
*/

View File

@ -52,7 +52,7 @@ public class LogUtils {
metaObject.put("os", meta.getOs());
metaObject.put("userId", meta.getUserId());
metaObject.put("oaid", appProvider.getOaid());
metaObject.put("rom", meta.getRom());
} catch (JSONException e) {
e.printStackTrace();
}
@ -71,6 +71,7 @@ public class LogUtils {
metaObject.put("channel", meta.getChannel());
metaObject.put("gid", meta.getGid());
metaObject.put("oaid", meta.getOaid());
metaObject.put("rom", meta.getRom());
metaObject.put("jnfj", MetaUtil.getBase64EncodedIMEI());
metaObject.put("mac", meta.getMac());
metaObject.put("manufacturer", meta.getManufacturer());
@ -79,7 +80,7 @@ public class LogUtils {
metaObject.put("os", meta.getOs());
metaObject.put("user_id", meta.getUserId());
metaObject.put("oaid", appProvider.getOaid());
metaObject.put("rom", meta.getRom());
} catch (JSONException e) {
e.printStackTrace();
}
@ -132,7 +133,7 @@ public class LogUtils {
metaObject.put("os", meta.getOs());
metaObject.put("userId", meta.getUserId());
metaObject.put("oaid", meta.getOaid());
metaObject.put("rom", meta.getRom());
object.put("event", "SHARE");
object.put("meta", metaObject);
object.put("timestamp", System.currentTimeMillis() / 1000);

View File

@ -517,7 +517,10 @@ object SensorsBridge {
downloadStatus: String,
gameType: String,
position: Int,
tabContent: String
tabContent: String,
linkType: String,
linkId: String,
linkText: String,
) {
val json = json {
KEY_GAME_ID to gameId
@ -532,6 +535,9 @@ object SensorsBridge {
KEY_GAME_TYPE to gameType
KEY_POSITION to position
KEY_TAB_CONTENT to tabContent
KEY_LINK_TYPE to linkType
KEY_LINK_ID to linkId
KEY_LINK_TEXT to linkText
}
trackEvent(EVENT_GAME_DETAIL_PAGE_TAB_SELECT, json)

View File

@ -65,6 +65,7 @@ object AppExecutor {
val cachedScheduler by lazy { Schedulers.from(ioExecutor) }
val computationScheduler by lazy { Schedulers.from(heavyWeightIoExecutor) }
val logScheduler by lazy { Schedulers.from(logExecutor) }
class MainThreadExecutor : Executor {
private val mainThreadHandler = Handler(Looper.getMainLooper())

View File

@ -49,7 +49,12 @@ data class ExposureEvent(
eTrace: List<ExposureEvent>? = null,
event: ExposureType = ExposureType.EXPOSURE
) {
val currentActivity = CurrentActivityHolder.getCurrentActivity()
val currentActivity = try {
CurrentActivityHolder.getCurrentActivity()
} catch (e: Exception) {
// 捕获异常,避免在获取当前 Activity 时出现问题
null
}
val currentActivitySimpleName = if (currentActivity != null) currentActivity::class.simpleName else "unknown"
val businessId = if (currentActivity is IBusiness) currentActivity.getBusinessId() else null

View File

@ -72,7 +72,7 @@ class RecyclerViewExposureHelper(
init {
val disposable = collectExposureSubject
.throttleLatest(SAMPLE_RATE, TimeUnit.MILLISECONDS)
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
collectExposureData()
}, {

View File

@ -169,7 +169,7 @@ class Va : IVa {
LogConstants.KEY_MANUFACTURER to Build.MANUFACTURER,
LogConstants.KEY_MODEL to Build.MODEL,
LogConstants.KEY_NETWORK to (MetaUtil.getMeta().network ?: ""),
LogConstants.KEY_ROM to RomIdentifier.getRom().name + " " + RomIdentifier.getRom().versionName,
LogConstants.KEY_ROM to RomIdentifier.getRom().romName + " " + RomIdentifier.getRom().romVersion,
LogConstants.KEY_HOST_VERSION to hostVersion,
LogConstants.KEY_HOST_CHANNEL to hostChannel,
LogConstants.KEY_OAID to oaid,

2
vasdk

Submodule vasdk updated: 02d9241f8d...16201868dd