Compare commits

..

204 Commits

Author SHA1 Message Date
5a48293bd8 fix: 修复 build_with_simple_backup.sh 不能在 mac Bash 上编译的问题 2025-01-17 18:45:37 +08:00
d0bf23ae48 Merge remote-tracking branch 'origin/release' into dev 2025-01-17 14:15:55 +08:00
b2fde1e0af Merge branch 'hotfix/v5.38.8-1118/meta_build_script_channel_issue' into 'release'
fix: 修复推广打包渠道不生效的问题

See merge request halo/android/assistant-android!2045
2025-01-16 16:01:39 +08:00
ab1350ff46 fix: 修复推广打包渠道不生效的问题 2025-01-16 16:00:25 +08:00
7f991e29d4 Merge branch 'fix/xiaomi_parallel_game_auth' into 'dev'
fix: 修复小米部分机型双开由于缺少权限无法授权登录的问题

See merge request halo/android/assistant-android!2044
2025-01-16 11:04:40 +08:00
40edf76aed fix: 修复小米部分机型双开由于缺少权限无法授权登录的问题 2025-01-16 11:04:40 +08:00
aaeb83c5df Merge branch 'fix/splash_flicker_on_miui' into 'dev'
fix: 修复部分小米设备修改状态栏颜色导致开屏广告闪烁的问题

See merge request halo/android/assistant-android!2043
2025-01-16 09:29:05 +08:00
5739f0a800 fix: 修复部分小米设备修改状态栏颜色导致开屏广告闪烁的问题 2025-01-15 17:58:16 +08:00
10cc81e7fc Merge branch 'feat/va-relative' into 'dev'
feat: 同步va的release代码

See merge request halo/android/assistant-android!2042
2025-01-15 15:00:42 +08:00
60a50f5722 feat: 同步va的release代码 2025-01-15 14:58:32 +08:00
644881c14f Merge branch 'fix/package_check_stuck_issue' into 'dev'
fix: 修复包名检测弹窗弹出较慢的问题

See merge request halo/android/assistant-android!2041
2025-01-15 14:48:19 +08:00
a0e43930a0 Merge remote-tracking branch 'origin/release' into dev
# Conflicts:
#	app/src/main/java/com/gh/ad/AdDelegateHelper.kt
#	dependencies.gradle
#	module_login/src/main/java/com/gh/gamecenter/login/user/UserRepository.java
#	vasdk
2025-01-15 14:27:40 +08:00
aa5f6f4f24 fix: 修复包名检测弹窗弹出较慢的问题 2025-01-15 14:22:22 +08:00
ab7668fd81 chore: 版本更新至 5.38.8 2025-01-15 09:19:40 +08:00
c6f014c984 Merge branch 'hotfix/v5.38.7-1117/pre_download_error' into 'release'
fix: 修复预下载获取资源时,服务端报错未能正确处理的问题

See merge request halo/android/assistant-android!2040
2025-01-14 16:30:31 +08:00
c215bd195e fix: 修复预下载获取资源时,服务端报错未能正确处理的问题 2025-01-14 16:27:43 +08:00
bb73598a87 Merge branch 'hotfix/va-relative' into 'release'
fix: va_core进程没有启动导致aidl的NPE问题。

See merge request halo/android/assistant-android!2039
2025-01-14 16:24:52 +08:00
c6f70d1b4c fix: va_core进程没有启动导致aidl的NPE问题。 2025-01-14 16:23:01 +08:00
ce7f75976c Merge branch 'fix/GHZSCY-7371' into 'dev'
fix: 游戏详情-多版本插件下载问题 https://jira.shanqu.cc/browse/GHZSCY-7371

See merge request halo/android/assistant-android!2038
2025-01-14 13:45:06 +08:00
c8a7999990 fix: 游戏详情-多版本插件下载问题 https://jira.shanqu.cc/browse/GHZSCY-7371 2025-01-14 10:49:52 +08:00
0cd281a53c Merge branch 'hotfix/va-relative' into 'release'
fix: 手机不支持armeabi-v7a架构时,根据游戏来选择架构

See merge request halo/android/assistant-android!2037
2025-01-10 18:01:24 +08:00
e92d89d498 fix: 手机不支持armeabi-v7a架构时,根据游戏来选择架构 2025-01-10 17:44:03 +08:00
a22858389b chore: 版本更新至 5.38.7 2025-01-10 13:55:24 +08:00
e9d091043d Merge branch 'hotfix/va-relative' into 'release'
feat: 同步商业版VA,修复权限问题。

See merge request halo/android/assistant-android!2036
2025-01-10 11:25:46 +08:00
db4ac95094 feat: 同步商业版VA,修复权限问题。
fix: 实名认证超大UI问题
fix: sentry va relative log.
2025-01-10 11:24:45 +08:00
13be47d440 Merge branch 'fix/search-page-crash' into 'release'
fix:https://sentry.shanqu.cc/organizations/lightgame/issues/423398/?project=22

See merge request halo/android/assistant-android!2035
2025-01-10 11:21:43 +08:00
beee098cfe fix:https://sentry.shanqu.cc/organizations/lightgame/issues/423398/?project=22 2025-01-10 11:17:26 +08:00
d67aaf956b Merge branch 'feat/GHZSCY-7046' into 'release'
feat: 补充启动广告图相关广告加载事件埋点—客户端 https://jira.shanqu.cc/browse/GHZSCY-7046

See merge request halo/android/assistant-android!2034
2025-01-09 17:29:21 +08:00
1ed9151b1f feat: 补充启动广告图相关广告加载事件埋点—客户端 https://jira.shanqu.cc/browse/GHZSCY-7046 2025-01-09 16:43:54 +08:00
13f20f6883 Merge branch 'hotfix/v5.38.6-1116/ad_view_background' into 'release'
fix: 还原自有开屏广告的背景颜色 https://jira.shanqu.cc/browse/GHZSCY-7360

See merge request halo/android/assistant-android!2033
2025-01-09 15:28:06 +08:00
78e320a192 fix: 还原自有开屏广告的背景颜色 https://jira.shanqu.cc/browse/GHZSCY-7360 2025-01-09 15:27:34 +08:00
e51db47fad Merge branch 'cherry-pick-f8a26ece' into 'release'
Merge branch 'fix/GHZSCY-7277' into 'dev'

See merge request halo/android/assistant-android!2032
2025-01-09 15:24:18 +08:00
ac02ea88b9 Merge branch 'fix/GHZSCY-7277' into 'dev'
修复错误的下载错误提示 https://jira.shanqu.cc/browse/GHZSCY-7277

See merge request halo/android/assistant-android!2025

(cherry picked from commit f8a26ece01)

54ee3ea3 fix: 游戏下载异常提示 https://jira.shanqu.cc/browse/GHZSCY-7277

Co-authored-by: 陈君陶 <chenjuntao@ghzhushou.com>
2025-01-09 15:23:53 +08:00
f60004fc81 Merge branch 'feat/GHZSCY-7359' into 'release'
需求合并

See merge request halo/android/assistant-android!2031
2025-01-09 15:05:29 +08:00
0cf39a82e2 Merge branch 'fix/viewstub_crashes' into 'release'
fix: 修复ViewStub偶发闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/422108/events/?project=22 https://sentry.shanqu.cc/organizations/lightgame/issues/425087/?project=22

See merge request halo/android/assistant-android!2030
2025-01-09 15:03:51 +08:00
315f244153 fix:【光环助手】包名检测及搜索页面在深色模式下的显示问题 https://jira.shanqu.cc/browse/GHZSCY-6985 2025-01-09 14:54:37 +08:00
f4bdc02d70 fix: 【光环助手】深色模式显示问题 https://jira.shanqu.cc/browse/GHZSCY-7121 2025-01-09 14:54:17 +08:00
aef39eb481 feat: 样式组件优化汇总—客户端 https://jira.shanqu.cc/browse/GHZSCY-6866 2025-01-09 14:53:37 +08:00
dc2e7147d9 fix: 修复ViewStub偶发闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/422108/events/?project=22 https://sentry.shanqu.cc/organizations/lightgame/issues/425087/?project=22 2025-01-09 14:49:58 +08:00
fdcb6342bf Merge branch 'hotfix/v5.38.6-1116/crashes' into 'release'
修复部分 5.38.6 线上闪退

See merge request halo/android/assistant-android!2029
2025-01-09 14:37:49 +08:00
b0da4f8986 Merge branch 'hotfix/v5.38.6-1116/blank_ad_view' into 'release'
fix: 优化开屏广告的显示,提高线程池的 core 线程数,限制视频开屏广告的触摸控制

See merge request halo/android/assistant-android!2028
2025-01-09 14:37:40 +08:00
f7cc906cc5 fix: 优化开屏广告的显示,提高线程池的 core 线程数,限制视频开屏广告的触摸控制 2025-01-09 14:37:40 +08:00
795fbabd90 Merge branch 'hotfix/v5.38.6-1116/login_culprit' into 'release'
修复`我的光环`页面在用户信息接口异常时的显示问题 https://jira.shanqu.cc/browse/GHZSCY-7340

See merge request halo/android/assistant-android!2027
2025-01-09 14:34:25 +08:00
e770f8a359 fix: 修复安装完成后更新安装信息时的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/395511 2025-01-09 11:49:38 +08:00
dd12b103be fix: 捕抓上报游戏启动日志的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/406179 2025-01-09 09:59:32 +08:00
21f4a398d5 fix: 处理数组越界闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/408904 2025-01-09 09:45:22 +08:00
f8a26ece01 Merge branch 'fix/GHZSCY-7277' into 'dev'
修复错误的下载错误提示 https://jira.shanqu.cc/browse/GHZSCY-7277

See merge request halo/android/assistant-android!2025
2025-01-08 10:10:32 +08:00
54ee3ea376 fix: 游戏下载异常提示 https://jira.shanqu.cc/browse/GHZSCY-7277 2025-01-07 17:56:09 +08:00
8dfb1644a8 fix: 登录状态显示问题 https://jira.shanqu.cc/browse/GHZSCY-7340 2025-01-07 17:48:53 +08:00
945e034f88 Merge branch 'fix/bind_phone_toRequestBody' into 'dev'
fix: 修复 bindPhone 相关接口 toRequestBody 时没有附带正确 body 的问题; 还原原生 settings 实现

See merge request halo/android/assistant-android!2024
2025-01-06 15:52:23 +08:00
a5ca88729a fix: 修复 bindPhone 相关接口 toRequestBody 时没有附带正确 body 的问题; 还原原生 settings 实现 2025-01-06 15:51:40 +08:00
d4bb3835cf Merge branch 'revert-e30557e2' into 'dev'
Revert "fix:https://jira.shanqu.cc/browse/GHZSCY-7300 【光环助手】预约上线弹窗神策数据上报问题"

See merge request halo/android/assistant-android!2022
2024-12-31 18:13:23 +08:00
3c63b74900 Revert "fix:https://jira.shanqu.cc/browse/GHZSCY-7300 【光环助手】预约上线弹窗神策数据上报问题"
This reverts merge request !2020
2024-12-31 18:10:16 +08:00
712cd21f6e Merge branch 'feat/GHZSCY-7168' into 'dev'
feat:CPM微信小游戏“换一批”功能优化—客户端 https://jira.shanqu.cc/browse/GHZSCY-7168

See merge request halo/android/assistant-android!2012
2024-12-31 16:58:00 +08:00
2b9098faa7 feat:CPM微信小游戏“换一批”功能优化—客户端 https://jira.shanqu.cc/browse/GHZSCY-7168 2024-12-31 16:38:25 +08:00
c0fde44534 Merge branch 'feat/upload_route_doc' into 'dev'
feat: 光环助手跳转链接规则优化 (补充跳转文档上传的脚本)

See merge request halo/android/assistant-android!2021
2024-12-31 16:35:28 +08:00
785f99f0ef feat: 光环助手跳转链接规则优化 (补充跳转文档上传的脚本) 2024-12-31 16:34:59 +08:00
dbd733aec6 Merge branch 'fix/GHZSCY-7300' into 'dev'
fix:https://jira.shanqu.cc/browse/GHZSCY-7300 【光环助手】预约上线弹窗神策数据上报问题

See merge request halo/android/assistant-android!2020
2024-12-31 15:46:36 +08:00
e30557e261 fix:https://jira.shanqu.cc/browse/GHZSCY-7300 【光环助手】预约上线弹窗神策数据上报问题 2024-12-31 15:45:05 +08:00
9744b95126 Merge branch 'fix/viewstub_crash' into 'release'
fix: 修复ViewStub偶发闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/423818/?project=22

See merge request halo/android/assistant-android!2019
2024-12-27 15:14:25 +08:00
009608165c Merge branch 'fix-issues-421826' into 'release'
fix:https://sentry.shanqu.cc/organizations/lightgame/issues/421826/?project=22

See merge request halo/android/assistant-android!2018
2024-12-27 14:02:39 +08:00
98356a7dd7 fix: 修复ViewStub偶发闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/423818/?project=22 2024-12-27 13:56:10 +08:00
8389041379 fix:https://sentry.shanqu.cc/organizations/lightgame/issues/421826/?project=22 2024-12-27 13:49:29 +08:00
e4352590e9 Merge branch 'feat/GHZSCY-7052' into 'dev'
feat: 游戏下载关闭状态新增“跳转第三方”—客户端 https://jira.shanqu.cc/browse/GHZSCY-7052

See merge request halo/android/assistant-android!2017
2024-12-26 10:41:37 +08:00
4f68a52d54 feat: 游戏下载关闭状态新增“跳转第三方”—客户端 https://jira.shanqu.cc/browse/GHZSCY-7052 2024-12-26 10:41:37 +08:00
93f87c8022 Merge branch 'feat/GHZSCY-6866' into 'dev'
feat: 样式组件优化汇总—客户端 https://jira.shanqu.cc/browse/GHZSCY-6866

See merge request halo/android/assistant-android!2016
2024-12-24 11:42:13 +08:00
a77beed7db feat: 样式组件优化汇总—客户端 https://jira.shanqu.cc/browse/GHZSCY-6866 2024-12-24 11:42:13 +08:00
112ddfda13 Merge branch 'feat/GHZSCY-6945' into 'dev'
feat: 消息通知:极光推送本地化—客户端 https://jira.shanqu.cc/browse/GHZSCY-6945

See merge request halo/android/assistant-android!2015
2024-12-24 11:41:36 +08:00
14cf39f10b feat: 消息通知:极光推送本地化—客户端 https://jira.shanqu.cc/browse/GHZSCY-6945 2024-12-24 11:41:36 +08:00
d775e804fd Merge branch 'feat/GHZSCY-6824' into 'dev'
feat: 新游开测相关功能优化(第四期)—客户端 https://jira.shanqu.cc/browse/GHZSCY-6824

See merge request halo/android/assistant-android!2014
2024-12-24 10:11:27 +08:00
d65062af26 feat: 新游开测相关功能优化(第四期)—客户端 https://jira.shanqu.cc/browse/GHZSCY-6824 2024-12-24 10:11:27 +08:00
2522bf5654 Merge branch 'fix/parallel_game_auth' into 'dev'
fix: 修复双开分身游戏无法授权登录的问题

See merge request halo/android/assistant-android!2013
2024-12-19 17:03:24 +08:00
92177ae5f2 fix: 修复双开分身游戏无法授权登录的问题 2024-12-19 17:03:24 +08:00
21ab15a907 Merge branch 'feat/GHZSCY-6335' into 'dev'
feat:【光环助手】实名认证-实名状态更新——畅玩助手 https://jira.shanqu.cc/browse/GHZSCY-6335

See merge request halo/android/assistant-android!2011
2024-12-16 14:38:15 +08:00
5bea92c08e feat:【光环助手】实名认证-实名状态更新——畅玩助手 https://jira.shanqu.cc/browse/GHZSCY-6335 2024-12-16 14:04:38 +08:00
da6725e444 Merge branch 'feat/GHZSCY-6335' into 'dev'
feat:【光环助手】实名认证-实名状态更新——畅玩助手 https://jira.shanqu.cc/browse/GHZSCY-6335

See merge request halo/android/assistant-android!2010
2024-12-16 11:51:21 +08:00
2a2e887ddf feat:【光环助手】实名认证-实名状态更新——畅玩助手 https://jira.shanqu.cc/browse/GHZSCY-6335 2024-12-16 11:41:22 +08:00
cc39a754db build: 合并 vasdk 在 release 分支相关的内容 2024-12-11 17:03:15 +08:00
b14cd3d143 Merge remote-tracking branch 'origin/release' into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/SplashScreenActivity.kt
#	app/src/main/java/com/gh/vspace/VHelper.kt
#	dependencies.gradle
#	vasdk
2024-12-11 16:47:12 +08:00
dc5b354861 Merge branch 'feat/GHZSCY-7039' into 'dev'
fix: https://jira.shanqu.cc/browse/GHZSCY-7037 实名认证弹窗层级优化

See merge request halo/android/assistant-android!2009
2024-12-11 16:32:09 +08:00
64462ebdbe fix: https://jira.shanqu.cc/browse/GHZSCY-7037 实名认证弹窗层级优化 2024-12-11 16:31:23 +08:00
2e63257523 Merge branch 'fix/game_collection_square_crash' into 'release'
fix: 修复游戏单广场闪退问题...

See merge request halo/android/assistant-android!2007
2024-12-09 10:36:46 +08:00
c69d117ee7 Merge branch 'feat/remove-gitlab-test-branch' into 'dev'
feat:移除gitlab-ci测试分支

See merge request halo/android/assistant-android!2006
2024-12-09 10:30:56 +08:00
ddccb25559 feat:移除gitlab-ci测试分支 2024-12-09 10:30:27 +08:00
913ea39302 Merge branch 'feature-GHZS-5572' into 'dev'
feat: 搜索业务-新增搜索发现取代热门标签—客户端 https://jira.shanqu.cc/browse/GHZSCY-5572

See merge request halo/android/assistant-android!1922
2024-12-09 10:27:39 +08:00
1002d02f12 feat: 搜索业务-新增搜索发现取代热门标签—客户端 https://jira.shanqu.cc/browse/GHZSCY-5572 2024-12-09 10:27:39 +08:00
fa663cd2f6 fix: 修复游戏单广场闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/379887/?project=22&query=is%3Aunresolved+assigned%3Ame&referrer=issue-stream&statsPeriod=14d 2024-12-09 09:59:53 +08:00
19af061311 Merge branch 'feat/GHZSCY-7123' into 'release'
feat:【光环助手】游戏搜索-排序专题 显示问题 https://jira.shanqu.cc/browse/GHZSCY-7123

See merge request halo/android/assistant-android!2004
2024-12-06 17:22:38 +08:00
d643795fa3 feat:【光环助手】游戏搜索-排序专题 显示问题 https://jira.shanqu.cc/browse/GHZSCY-7123 2024-12-06 17:22:38 +08:00
44d93b7527 Merge branch 'fix/sentry-va' into 'dev'
fix: sentry 捕获的异常 https://sentry.shanqu.cc/organizations/lightgame/issues/398398/?project=22

See merge request halo/android/assistant-android!2005
2024-12-06 16:55:03 +08:00
c3d55d4ff9 fix: sentry crash[https://sentry.shanqu.cc/organizations/lightgame/issues/399032/?project=22] 2024-12-06 16:46:46 +08:00
d6f35c5942 Merge branch 'fix/GHZSCY-7121' into 'dev'
fix: 【光环助手】深色模式显示问题 https://jira.shanqu.cc/browse/GHZSCY-7121

See merge request halo/android/assistant-android!2003
2024-12-05 11:07:45 +08:00
c53c1b8228 fix: 【光环助手】深色模式显示问题 https://jira.shanqu.cc/browse/GHZSCY-7121 2024-12-05 11:07:45 +08:00
61b967e533 fix: sentry 捕获的异常 https://sentry.shanqu.cc/organizations/lightgame/issues/398398/?project=22
https://sentry.shanqu.cc/organizations/lightgame/issues/397892/?project=22
2024-12-03 18:01:30 +08:00
b1f2d0a303 Merge branch 'fix/sentry-621063' into 'release'
fix: Sentry-421063 畅玩游戏启动弹窗异步更新下载游戏数量UI时导致的崩溃问题...

See merge request halo/android/assistant-android!2002
2024-12-03 14:10:47 +08:00
bb906f0bb8 fix: Sentry-421063 畅玩游戏启动弹窗异步更新下载游戏数量UI时导致的崩溃问题... 2024-12-03 14:10:47 +08:00
6f242dcc95 Merge branch 'fix/view_stub_crash' into 'release'
fix: 补充ViewStub闪退Sentry埋点

See merge request halo/android/assistant-android!2001
2024-12-03 13:42:44 +08:00
b47a64c63d fix: 补充ViewStub闪退Sentry埋点 2024-12-03 13:40:45 +08:00
948df2582c Merge branch 'fix/view_stub_crash' into 'release'
fix: 捕获ViewStub偶发的空指针闪退问题...

See merge request halo/android/assistant-android!2000
2024-12-03 12:04:31 +08:00
35edcf1d68 fix: 捕获ViewStub偶发的空指针闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418647/events/1d426e3ceda5477c9afbc6712d335b22/?project=22 2024-12-03 11:40:14 +08:00
286d7650f2 Merge branch 'hotfix/v5.38.6-1116/crashes' into 'release'
修复部分线上闪退问题

See merge request halo/android/assistant-android!1999
2024-12-03 10:43:39 +08:00
e566ab838f fix: 捕抓磁盘满了时的闪退 https://sentry.shanqu.cc/organizations/lightgame/issues/397785 2024-12-03 09:31:09 +08:00
cae720d4ec Merge branch 'fix/auth' into 'release'
fix: 修复未打开过光环时无法获取登录状态并授权的问题

See merge request halo/android/assistant-android!1998
2024-12-02 17:21:28 +08:00
925516724f fix: 修复未打开过光环时无法获取登录状态并授权的问题 2024-12-02 17:21:27 +08:00
a5f807c038 fix: 修复下载完成清理资源时因为磁盘满了引起的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/397443/ 2024-12-02 14:52:37 +08:00
f442a70bd3 Merge branch 'fix/delete_appointment_crash' into 'release'
fix:https://sentry.shanqu.cc/organizations/lightgame/issues/423693/?project=22...

See merge request halo/android/assistant-android!1997
2024-12-02 14:42:27 +08:00
9b3dab9897 fix:https://sentry.shanqu.cc/organizations/lightgame/issues/423693/?project=22... 2024-12-02 14:42:27 +08:00
d939aae901 fix: 移除为了能正常收取 BroadcastReceiver 而创建的 InstallService (后续已改为回到应用刷新列表) https://sentry.shanqu.cc/organizations/lightgame/issues/389377/ 2024-12-02 14:31:29 +08:00
028974ec0d fix: 捕抓磁盘已满时下载简单内容造成的闪退 https://sentry.shanqu.cc/organizations/lightgame/issues/401379 2024-12-02 11:42:18 +08:00
ecd4610186 fix: 捕抓磁盘已满时下载广告插件造成的闪退 https://sentry.shanqu.cc/organizations/lightgame/issues/418801/ 2024-12-02 11:17:02 +08:00
21e5f2c98d Merge branch 'fix/webview_crash' into 'release'
fix: 修复某些机型启用WebView深色模式出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/421910

See merge request halo/android/assistant-android!1996
2024-12-02 10:57:52 +08:00
71c0cfe350 fix: 修复某些机型启用WebView深色模式出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/421910 2024-12-02 10:55:37 +08:00
3b8b60bc6b Merge branch 'fix/GHZSCY-7019' into 'release'
fix:【光环助手】自定义页面的搜索显示问题 https://jira.shanqu.cc/browse/GHZSCY-7019

See merge request halo/android/assistant-android!1995
2024-11-27 14:07:54 +08:00
ac59158dbb fix:【光环助手】自定义页面的搜索显示问题 https://jira.shanqu.cc/browse/GHZSCY-7019 2024-11-27 14:07:54 +08:00
5becdf2095 chore: 版本更新至 5.38.6 2024-11-27 11:42:36 +08:00
a88b49344f Merge branch 'hotfix/v5.38.5-1115/remove_registeraion_id' into 'release'
fix: 移除极光 registration_id

See merge request halo/android/assistant-android!1994
2024-11-27 10:43:19 +08:00
f34646cde8 fix: 移除极光 registration_id 2024-11-27 10:42:15 +08:00
bc4bb9b7c6 feat: 关于投诉邮箱部分数据遗失的对外说明 https://jira.shanqu.cc/browse/GHZSCY-7033 2024-11-25 17:46:05 +08:00
9e8ffce772 Merge branch 'hotfix/v5.38.5-1115/vgame_config' into 'release'
fix: 修复接口请求失败时会把畅玩入口关闭的问题

See merge request halo/android/assistant-android!1993
2024-11-25 16:07:13 +08:00
008985489a fix: 修复接口请求失败时会把畅玩入口关闭的问题 2024-11-25 16:01:07 +08:00
2f3fbd3e7c Merge branch 'fix/custom_page_missing_required_view_id' into 'release'
fix:https://sentry.shanqu.cc/organizations/lightgame/issues/408589/events/edfa...

See merge request halo/android/assistant-android!1992
2024-11-25 09:26:26 +08:00
abef224830 fix:https://sentry.shanqu.cc/organizations/lightgame/issues/408589/events/edfa... 2024-11-25 09:26:26 +08:00
8feb9b788e Merge branch 'hotfix/v5.35.5-1115/auth_crash' into 'release'
fix: 修复授权登录页面的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/373402/?project=22

See merge request halo/android/assistant-android!1991
2024-11-25 09:22:52 +08:00
0a059deb44 fix: 修复授权登录页面的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/373402/?project=22 2024-11-22 10:14:27 +08:00
448160d255 Merge branch 'hotfix/v5.38.4-1114/va' into 'release'
fix: 修复混淆把这个方法移除了。

See merge request halo/android/assistant-android!1990
2024-11-21 14:45:54 +08:00
533f93a340 fix: 修复混淆把这个方法移除了。 2024-11-21 14:44:58 +08:00
d80b8a97a3 chore: 版本更新至 5.38.5 2024-11-21 11:50:17 +08:00
f2e6d98788 Merge branch 'feat/GHZSCY-6923' into 'release'
feat: CPM微信小游戏优化第二期—客户端 https://jira.shanqu.cc/browse/GHZSCY-6923

See merge request halo/android/assistant-android!1986
2024-11-21 11:27:25 +08:00
238a83c5fe feat: CPM微信小游戏优化第二期—客户端 https://jira.shanqu.cc/browse/GHZSCY-6923 2024-11-21 11:27:25 +08:00
ca71f23363 Merge branch 'hotfix/v5.38.4-1114/GHZSCY-7004' into 'release'
fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004

See merge request halo/android/assistant-android!1989
2024-11-21 09:57:59 +08:00
c96b41c621 fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004 2024-11-21 09:57:59 +08:00
9afb35bbb9 feat: 将与服务器校对时间的间隔改为 24 小时一次 2024-11-20 16:49:04 +08:00
e8ee63d52c Merge branch 'hotfix/v5.38.4-1114/GHZSCY-7004' into 'release'
fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004

See merge request halo/android/assistant-android!1987
2024-11-20 11:34:56 +08:00
90359cfffd fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004 2024-11-20 10:05:28 +08:00
a3da883033 Merge branch 'revert-8c95286f' into 'release'
Revert "Merge branch 'feat/GHZSCY-6923' into 'release'"

See merge request halo/android/assistant-android!1984
2024-11-19 18:16:53 +08:00
a9f1437a52 Revert "Merge branch 'feat/GHZSCY-6923' into 'release'" 2024-11-19 18:16:53 +08:00
8c95286fe5 Merge branch 'feat/GHZSCY-6923' into 'release'
feat: CPM微信小游戏优化第二期—客户端 https://jira.shanqu.cc/browse/GHZSCY-6923

See merge request halo/android/assistant-android!1982
2024-11-19 18:12:55 +08:00
8a835a94e3 feat: CPM微信小游戏优化第二期—客户端 https://jira.shanqu.cc/browse/GHZSCY-6923 2024-11-19 16:46:05 +08:00
14ec4aed3a Merge branch 'hotfix/v5.38.4-1114/GHZSCY-7004' into 'release'
fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004

See merge request halo/android/assistant-android!1981
2024-11-19 15:37:52 +08:00
07f956a1f0 fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004 2024-11-19 15:26:12 +08:00
6ef8d04e57 Merge branch 'fix/jg_push' into 'release'
fix: 神策上报极光推送ID改为profileSet方法

See merge request halo/android/assistant-android!1980
2024-11-18 18:21:45 +08:00
30248ef205 fix: 神策上报极光推送ID改为profileSet方法 2024-11-18 18:20:40 +08:00
87b9bb0bf3 fix: 修复下载过程中 response code 为 304 时造成下载异常的问题 2024-11-18 11:35:56 +08:00
b346882bfa Merge branch 'fix/GHZSCY-6939-merge' into 'release'
fix:【光环助手】“视频横屏滑动”专题视频播放问题 https://jira.shanqu.cc/browse/GHZSCY-6939

See merge request halo/android/assistant-android!1979
2024-11-15 17:51:24 +08:00
eeddb5ea51 fix:【光环助手】“视频横屏滑动”专题视频播放问题 https://jira.shanqu.cc/browse/GHZSCY-6939 2024-11-15 16:55:35 +08:00
2ccdd93e47 build: 处理编译问题
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-11-14 16:31:49 +08:00
d98466f60f build: 路由文档仅手动启用时生成 2024-11-14 16:19:42 +08:00
2afc2bc9d6 Merge remote-tracking branch 'origin/release' into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/search/viewmodel/SearchGameListViewModel.kt
#	dependencies.gradle
#	feature/floating-window/src/demo/java/com/gh/gamecenter/feedback/view/help/QaFeedbackDialogFragment.kt
#	vasdk
2024-11-14 15:21:44 +08:00
243b0ccbd4 Merge branch 'fix/GHZSCY-6575' into 'dev'
fix: 下载按钮由双下载切换回单下载时的问题 https://jira.shanqu.cc/browse/GHZSCY-6575

See merge request halo/android/assistant-android!1878
2024-11-14 15:15:46 +08:00
78f9aa3ee4 Merge branch 'hotfix/v5.38.4-1114/GHZSCY-6927' into 'release'
fix: 深色模式下富文本指定颜色无法显示的问题 https://jira.shanqu.cc/browse/GHZSCY-6927

See merge request halo/android/assistant-android!1978
2024-11-14 10:21:48 +08:00
f355eae99b Merge branch 'feat/GHZSCY-6985' into 'dev'
fix:【光环助手】包名检测及搜索页面在深色模式下的显示问题 https://jira.shanqu.cc/browse/GHZSCY-6985

See merge request halo/android/assistant-android!1977
2024-11-13 17:39:06 +08:00
3c1af6e02d fix:【光环助手】包名检测及搜索页面在深色模式下的显示问题 https://jira.shanqu.cc/browse/GHZSCY-6985 2024-11-13 17:37:23 +08:00
57a8b96f56 Merge branch 'feat/GHZSCY-6984' into 'dev'
feat:搜索业务:神策埋点相关搜索结果点击事件新增序号属性position—客户端 https://jira.shanqu.cc/browse/GHZSCY-6984

See merge request halo/android/assistant-android!1976
2024-11-13 16:49:15 +08:00
71265e0ea7 feat:搜索业务:神策埋点相关搜索结果点击事件新增序号属性position—客户端 https://jira.shanqu.cc/browse/GHZSCY-6984 2024-11-13 16:46:09 +08:00
b007e63b5e Merge branch 'fix/GHZSCY-6971' into 'dev'
fix:【光环助手】2410后台优化-游戏专题-1112-测试-客户端 https://jira.shanqu.cc/browse/GHZSCY-6971

See merge request halo/android/assistant-android!1975
2024-11-12 17:40:35 +08:00
c281ea7ac5 fix:【光环助手】2410后台优化-游戏专题-1112-测试-客户端 https://jira.shanqu.cc/browse/GHZSCY-6971 2024-11-12 17:39:02 +08:00
f34ad0675d Merge branch 'hotfix/v5.38.4-1114/va' into 'release'
feat: 1. Android 8.0 以下不初始化VA。2.去掉VA的javahook。3. 去掉VA外部应用监听。

See merge request halo/android/assistant-android!1974
2024-11-12 17:24:03 +08:00
36abcc9f19 feat: 1. Android 8.0 以下不初始化VA。2.去掉VA的javahook。3. 去掉VA外部应用监听。 2024-11-12 11:17:02 +08:00
d6443a401a Merge branch 'feat/GHZSCY-5738' into 'dev'
fix:【光环助手】客户端UI组件规范更新同步2024/06/17 https://jira.shanqu.cc/browse/GHZSCY-5738

See merge request halo/android/assistant-android!1973
2024-11-12 09:28:36 +08:00
6c8ea6ffb2 fix:【光环助手】客户端UI组件规范更新同步2024/06/17 https://jira.shanqu.cc/browse/GHZSCY-5738 2024-11-11 18:04:22 +08:00
ae878eddf1 Merge branch 'hotfix/v5.38.4-1114/remove_useless_import' into 'release'
fix: 移除无用 import

See merge request halo/android/assistant-android!1971
2024-11-11 18:03:45 +08:00
ece519115b fix: 移除无用 import 2024-11-11 18:03:01 +08:00
b9e0a8e37a Merge branch 'hotfix/v5.38.4-1114/deadobject-crash' into 'release'
fix: 修复部分调用 PackageManager 相关的方法的闪退(提供异常时的回落)...

See merge request halo/android/assistant-android!1970
2024-11-11 17:35:26 +08:00
34ca8896ae fix: 修复部分调用 PackageManager 相关的方法的闪退(提供异常时的回落) https://sentry.shanqu.cc/organizations/lightgame/issues/418276/ https://sentry.shanqu.cc/organizations/lightgame/issues/417950/ 2024-11-11 17:24:40 +08:00
d6e19bfaff Merge branch 'fix/GHZSCY-6944' into 'release'
fix:【光环助手】神策埋点游戏单搜索结果点击事件游戏单标题的内容错误 https://jira.shanqu.cc/browse/GHZSCY-6944

See merge request halo/android/assistant-android!1969
2024-11-08 09:26:58 +08:00
943fb4d4e0 fix:【光环助手】神策埋点游戏单搜索结果点击事件游戏单标题的内容错误 https://jira.shanqu.cc/browse/GHZSCY-6944 2024-11-08 09:23:42 +08:00
2c5471d524 Merge branch 'fix/sentry-418688' into 'release'
fix: Sentry-418688 SearchActivity回调onSavedInstance后,调用FragmentManager的popBackStack引发的崩溃问题

See merge request halo/android/assistant-android!1968
2024-11-07 13:42:39 +08:00
cf527db60e fix: Sentry-418688 SearchActivity回调onSavedInstance后,调用FragmentManager的popBackStack引发的崩溃问题 2024-11-07 13:42:39 +08:00
f261991a55 fix: 深色模式下富文本指定颜色无法显示的问题 https://jira.shanqu.cc/browse/GHZSCY-6927
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-11-06 15:49:31 +08:00
ab66621751 chore: 版本更新至 5.38.4 2024-11-04 17:59:19 +08:00
af262c624a Merge branch 'feat/GHZSCY-6904' into 'release'
feat:【光环助手】搜索bug https://jira.shanqu.cc/browse/GHZSCY-6904

See merge request halo/android/assistant-android!1966
2024-11-04 16:28:48 +08:00
d2813ecbda feat:【光环助手】搜索bug https://jira.shanqu.cc/browse/GHZSCY-6904 2024-11-04 16:28:48 +08:00
0ea932e36d Merge branch 'hotfix/v5.38.3-1113/aidl_npe_crash' into 'release'
fix: 尝试修复aidl获取对象为空导致NPE。https://sentry.shanqu.cc/organizations/lightgame/issues/399032/?project=22

See merge request halo/android/assistant-android!1965
2024-11-04 14:35:50 +08:00
68151ed6f9 fix: 尝试修复aidl获取对象为空导致NPE。https://sentry.shanqu.cc/organizations/lightgame/issues/399032/?project=22 2024-11-04 14:34:53 +08:00
e6d2361008 Merge branch 'hotfix/v5.38.3-1113/concurrent_crash' into 'release'
fix: 修复部分 5.38.3 的线上闪退问题

See merge request halo/android/assistant-android!1964
2024-11-04 13:43:00 +08:00
570b777c8e Merge branch 'hotfix/v5.38.3-1113/crashes' into 'release'
修复Sentry上的闪退问题

See merge request halo/android/assistant-android!1963
2024-11-04 11:50:45 +08:00
0e557b2246 fix: 修复启动游戏时多线程操作闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/406116/?project=22
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-11-04 11:50:41 +08:00
f155440814 fix: 修复下载 exception 异常为空时的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/416995/?project=22
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-11-04 11:49:57 +08:00
62ba9fc7bf fix: 修复游戏详情评论页面重建时出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/379887/events/aa3bbc5102ed4a57b66c3c7fed5d7b34/?project=22 2024-11-04 11:26:00 +08:00
4637aa8808 fix: 修复下拉推送偶发的空指针闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418647/events/1d426e3ceda5477c9afbc6712d335b22/?project=22 2024-11-04 11:24:08 +08:00
81998e3aad Merge branch 'fix/sentry-418235' into 'release'
fix: 畅玩启动提示弹窗游戏列表数组越界问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418304/?project=22

See merge request halo/android/assistant-android!1962
2024-11-01 16:15:14 +08:00
82a8aa03ba fix: 畅玩启动提示弹窗游戏列表数组越界问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418304/?project=22 2024-11-01 16:13:05 +08:00
c876711578 chore: 版本更新至 5.38.3 2024-11-01 09:37:56 +08:00
41fcee7f4d Merge branch 'feat/GHZSCY-6876' into 'release'
Resolve GHZSCY-6876 "Feat/"

See merge request halo/android/assistant-android!1961
2024-11-01 09:37:04 +08:00
0ccbc4d581 feat:一键登录SDK更新—客户端 https://jira.shanqu.cc/browse/GHZSCY-6876 2024-11-01 09:37:04 +08:00
f05fc73e3a Merge branch 'hotfix/v5.38.2-1112/binding_crash' into 'release'
fix: 修复 SearchToolbarTabWrapperFragment 页面 binding bindView 时的闪退问题...

See merge request halo/android/assistant-android!1959
2024-10-31 10:31:26 +08:00
ca3c545f26 Merge branch 'hotfix/v5.38.1-1111/GHZSCY-6855' into 'release'
fix: 神策下载按钮点击事件相关字段上报异常排查 https://jira.shanqu.cc/browse/GHZSCY-6855

See merge request halo/android/assistant-android!1958
2024-10-31 10:28:28 +08:00
226539328e fix: 修复 SearchToolbarTabWrapperFragment 页面 binding bindView 时的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418028/?project=22
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-10-31 10:13:36 +08:00
bb7db78b0c Merge branch 'hotfix/v5.38.2-1112/va_launch_crash' into 'release'
fix: 修复点击畅玩启动插屏广告出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418073/?project=22

See merge request halo/android/assistant-android!1957
2024-10-31 09:47:03 +08:00
ede62c5363 fix: 修复点击畅玩启动插屏广告出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418073/?project=22 2024-10-31 09:44:40 +08:00
12bb6824ea Merge branch 'fix/wx_subscribe_msg_response_handle' into 'release'
fix: 修复微信开服提醒消息回调处理异常问题

See merge request halo/android/assistant-android!1955
2024-10-30 14:44:16 +08:00
15c0950754 fix: 修复微信开服提醒消息回调处理异常问题 2024-10-30 14:42:55 +08:00
f86b7fe12a Merge branch 'hotfix/v5.38.2-1112/emulator_auth' into 'release'
fix: 修复雷电模拟器网游插件登录后跳转回游戏出现的闪退问题

See merge request halo/android/assistant-android!1954
2024-10-30 14:31:22 +08:00
d12cdbd34b fix: 修复雷电模拟器网游插件登录后跳转回游戏出现的闪退问题 2024-10-30 14:31:22 +08:00
8436d4eda3 Merge branch 'hotfix/v5.38.2-1112/multi_tab_loading' into 'release'
fix: 修复多tab导航页loading动画没有显示的问题

See merge request halo/android/assistant-android!1952
2024-10-29 13:51:10 +08:00
be832037a7 fix: 修复多tab导航页loading动画没有显示的问题 2024-10-29 13:41:36 +08:00
b620257825 Merge branch 'hotfix/v5.38.2-1112/GHZSCY-6859' into 'release'
fix:【光环助手】深色模式切换显示问题 https://jira.shanqu.cc/browse/GHZSCY-6859

See merge request halo/android/assistant-android!1951
2024-10-28 17:13:30 +08:00
6c88cace99 fix:【光环助手】深色模式切换显示问题 https://jira.shanqu.cc/browse/GHZSCY-6859 2024-10-28 17:11:23 +08:00
f875fa1b14 Merge branch 'feat/GHZSCY-6828' into 'release'
feat: CPM微信小游戏一期优化—客户端 https://jira.shanqu.cc/browse/GHZSCY-6828

See merge request halo/android/assistant-android!1948
2024-10-28 14:54:49 +08:00
8076c3a70a feat: CPM微信小游戏一期优化—客户端 https://jira.shanqu.cc/browse/GHZSCY-6828 2024-10-28 14:54:49 +08:00
bebab317a3 fix: 神策下载按钮点击事件相关字段上报异常排查 https://jira.shanqu.cc/browse/GHZSCY-6855 2024-10-28 14:38:06 +08:00
c450ca570d Merge branch 'hotfix/v5.38.2-1112/GHZSCY-6854' into 'release'
fix:【光环助手】切换深色/普通模式tab字体颜色变化问题 https://jira.shanqu.cc/browse/GHZSCY-6854

See merge request halo/android/assistant-android!1950
2024-10-28 10:23:56 +08:00
d239b0755f fix:【光环助手】切换深色/普通模式tab字体颜色变化问题 https://jira.shanqu.cc/browse/GHZSCY-6854 2024-10-28 10:20:53 +08:00
0a187b2242 fix: 下载按钮由双下载切换回单下载时的问题 https://jira.shanqu.cc/browse/GHZSCY-6575
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-08-26 14:16:37 +08:00
215 changed files with 3229 additions and 1128 deletions

View File

@ -72,8 +72,6 @@ android_build:
only:
- dev
- release
- feat/GHZSCY-6866
- fix/GHZSCY-6939
# 代码检查
sonarqube_analysis:
@ -159,5 +157,3 @@ oss-upload&send-email:
only:
- dev
- release
- feat/GHZSCY-6866
- fix/GHZSCY-6939

View File

@ -372,8 +372,6 @@ dependencies {
// debugImplementation "com.gu.android:toolargetool:${toolargetool}" // 需要使用调试时才启用
debugImplementation "com.github.nichbar:WhatTheStack:${whatTheStack}"
ksp project(":feature:route_doc")
implementation "androidx.multidex:multidex:${multiDex}"
implementation "androidx.fragment:fragment-ktx:${fragment}"
@ -449,14 +447,14 @@ dependencies {
exclude group: 'androidx.swiperefreshlayout'
}
// implementation(project(':module_setting')) {
implementation(project(':module_setting')) {
exclude group: 'androidx.swiperefreshlayout'
}
// implementation(project(':module_setting_compose')) {
// exclude group: 'androidx.swiperefreshlayout'
// }
implementation(project(':module_setting_compose')) {
exclude group: 'androidx.swiperefreshlayout'
}
if (!gradle.ext.excludeOptionalModules || gradle.ext.enablePkg) {
implementation(project(':feature:pkg'))
}
@ -512,6 +510,10 @@ dependencies {
implementation(project(':feature:sentry'))
}
if (gradle.ext.enableRouteDoc) {
ksp project(":feature:route_doc")
}
implementation(project(':feature:media_select'))
implementation(project(":module_va_api"))

View File

@ -68,6 +68,9 @@
<!-- 悬浮窗 -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!-- 适配 双开/分身 游戏授权登录 -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-sdk tools:overrideLibrary="
com.shuyu.gsyvideoplayer,
com.shuyu.gsyvideoplayer.lib,
@ -636,6 +639,7 @@
<activity
android:name="com.gh.gamecenter.SkipCompatActivity"
android:exported="true"
android:launchMode="singleTask"
android:theme="@style/Theme.AppCompat.Light.Fullscreen.Transparent">
<intent-filter>
<data android:scheme="ghzhushou" />
@ -659,7 +663,8 @@
android:name=".authorization.AuthorizationActivity"
android:exported="true"
android:launchMode="singleTask"
android:screenOrientation="portrait">
android:screenOrientation="portrait"
android:taskAffinity=".auth">
<intent-filter>
<data android:scheme="ghzhushou_authorization" />
<category android:name="android.intent.category.DEFAULT" />
@ -864,10 +869,6 @@
<!-- tools:node="remove" />-->
<!-- </provider>-->
<service android:name="com.gh.gamecenter.install.InstallService" />
<service android:name="com.gh.download.suspendwindow.DownloadSuspendWindowService" />
<receiver
android:name="com.gh.gamecenter.receiver.DownloadReceiver"
android:exported="false">

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.SharedPreferences
import android.graphics.drawable.Animatable
import android.os.Message
import android.text.TextUtils
import android.view.View
@ -13,11 +14,13 @@ import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.fragment.app.Fragment
import com.therouter.TheRouter
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.image.ImageInfo
import com.gh.common.exposure.ExposureManager
import com.gh.common.util.DirectUtils.directToLinkPage
import com.gh.common.util.LogUtils
import com.gh.common.util.NewFlatLogUtils.logOpenScreenAdSkip
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.MainActivity
@ -59,6 +62,8 @@ object AdDelegateHelper {
private val mGameSearchAdList: ArrayList<AdConfig> by lazy { arrayListOf() }
private var mVGameLaunchAd: AdConfig? = null
private var ownerSplashAdLoadTime = 0L
val vGameLaunchAd: AdConfig?
get() = mVGameLaunchAd
@ -76,6 +81,7 @@ object AdDelegateHelper {
}
var isShowingSplashAd = false // 是否正在显示开屏广告
var isOwnerSplashAdShown = false // 自有开屏广告是否展示
var gameSearchKeyword = ""
fun initAdSdk(context: Context) {
@ -302,6 +308,7 @@ object AdDelegateHelper {
) {
val hideCallback = {
isShowingSplashAd = false
isOwnerSplashAdShown = false
hideAction.invoke()
}
if (mSplashAd != null) {
@ -574,6 +581,8 @@ object AdDelegateHelper {
handler: BaseActivity.BaseHandler,
hideCallback: () -> Unit
) {
isOwnerSplashAdShown = false
val jumpBtn = startAdContainer.findViewById<TextView>(R.id.jumpBtn)
val jumpDetailBtn: TextView = startAdContainer.findViewById(R.id.jumpDetailBtn)
val adImage: SimpleDraweeView = startAdContainer.findViewById(R.id.adImage)
@ -592,38 +601,62 @@ object AdDelegateHelper {
)
adImage.visibleIf(true)
ImageUtils.display(adImage, ad.img)
ImageUtils.displayWithCallback(adImage, ad.img, true, object : BaseControllerListener<ImageInfo>() {
override fun onSubmit(id: String?, callerContext: Any?) {
super.onSubmit(id, callerContext)
adImage.post {
ownerSplashAdLoadTime = System.currentTimeMillis()
NewFlatLogUtils.logSplashAdLoad(ad.id)
}
}
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
isOwnerSplashAdShown = true
adImage.post {
NewFlatLogUtils.logSplashAdShow(ad.id, System.currentTimeMillis() - ownerSplashAdLoadTime)
}
}
override fun onFailure(id: String?, throwable: Throwable?) {
super.onFailure(id, throwable)
NewFlatLogUtils.logSplashAdFail(ad.id, "启动广告图加载失败")
}
})
if (ad.isImageType) {
adVideo.visibleIf(false)
} else {
adVideo.visibleIf(true)
adVideo.startPlay(ad.video.url)
}
startAdContainer.setOnClickListener {
// 拦截点击事件传递
}
jumpBtn.setOnClickListener {
handler.removeMessages(MainActivity.COUNTDOWN_AD)
hideCallback.invoke()
val linkEntity = ad.jump
logOpenScreenAdSkip(
ad.id,
(if (linkEntity.text != null) linkEntity.text else "")!!,
(if (linkEntity.type != null) linkEntity.type else "")!!,
(if (linkEntity.link != null) linkEntity.link else "")!!
)
SensorsBridge.trackEvent(
"SplashAdOwnSkip",
"splash_ad_id",
ad.id,
"link_type",
linkEntity.type ?: "",
"link_id",
linkEntity.link ?: "",
"link_text",
linkEntity.text ?: ""
)
it.debounceActionWithInterval(1000L) {
if (!isOwnerSplashAdShown) {
NewFlatLogUtils.logSplashAdFail(ad.id, "加载过程中点击跳过广告")
}
handler.removeMessages(MainActivity.COUNTDOWN_AD)
hideCallback.invoke()
val linkEntity = ad.jump
NewFlatLogUtils.logOpenScreenAdSkip(
ad.id,
(if (linkEntity.text != null) linkEntity.text else "")!!,
(if (linkEntity.type != null) linkEntity.type else "")!!,
(if (linkEntity.link != null) linkEntity.link else "")!!
)
SensorsBridge.trackEvent(
"SplashAdOwnSkip",
"splash_ad_id",
ad.id,
"link_type",
linkEntity.type ?: "",
"link_id",
linkEntity.link ?: "",
"link_text",
linkEntity.text ?: ""
)
}
}
val sources: MutableList<ExposureSource> = ArrayList()
sources.add(ExposureSource("开屏广告", ad.id))

View File

@ -44,6 +44,16 @@ class SplashAdVideoView @JvmOverloads constructor(
return R.layout.layout_splash_ad_video
}
override fun touchSurfaceMoveFullLogic(absDeltaX: Float, absDeltaY: Float) {
// no nothing
}
override fun onPrepared() {
super.onPrepared()
visibility = VISIBLE
}
override fun onAutoCompletion() {
setStateAndUi(CURRENT_STATE_AUTO_COMPLETE);

View File

@ -17,7 +17,7 @@ import kotlin.concurrent.fixedRateTimer
object FixedRateJobHelper {
private const val CHECKER_PERIOD: Long = 15 * 1000L
private const val TIME_PERIOD: Long = 10 * 60 * 1000L
private const val TIME_PERIOD: Long = 24 * 60 * 60 * 1000L
private const val LOGHUB_PERIOD: Long = 2 * 60 * 1000L
private const val EXPOSURE_PERIOD: Long = 1 * 60 * 1000L
private const val REGION_SETTING_PERIOD: Long = 60 * 1000L
@ -35,7 +35,7 @@ object FixedRateJobHelper {
// 时间检查每15秒检查一次
fixedRateTimer("Global-Fixed-Rate-Timer", initialDelay = 100, period = CHECKER_PERIOD) {
val elapsedTime = mExecuteCount * CHECKER_PERIOD
// 时间校对,10分钟一次
// 时间校对,24 小时一次
if (elapsedTime % TIME_PERIOD == 0L) {
RetrofitManager.getInstance().api.time
.subscribeOn(Schedulers.io())

View File

@ -4,6 +4,7 @@ import android.app.Activity
import android.content.Context
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
import com.gh.common.util.PackageChangeHelper
import com.gh.common.util.TempCertificationUtils
import com.gh.gamecenter.feature.entity.GameEntity
@ -25,6 +26,10 @@ class LandPageAddressHandler : DownloadChainHandler() {
processEndCallback?.invoke(asVGame, null)
}
} else {
val packageName = gameEntity.getApk().firstOrNull()?.packageName
if (packageName?.isNotEmpty() == true) {
PackageChangeHelper.addInstallPendingPackage(packageName)
}
DirectUtils.directToExternalBrowser(context, gameEntity.landPageAddressDialog!!.link!!)
}
}

View File

@ -114,8 +114,6 @@ public class Config {
if (!TextUtils.isEmpty(json)) {
mSettingsEntity = GsonUtils.fromJson(json, SettingsEntity.class);
}
mSettingsEntity.setGameSmooth("off");
} catch (Exception e) {
e.printStackTrace();
}
@ -263,8 +261,7 @@ public class Config {
public void onSuccess(VSetting data) {
mVSetting = data;
SPUtils.setString(Constants.SP_V_SETTINGS, GsonUtils.toJson(data));
VHelper.init(HaloApp.getInstance());
VHelper.checkVspaceUpdate(HaloApp.getInstance());
}
});
}

View File

@ -15,10 +15,10 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.gh.common.chain.BrowserInstallHandler;
import com.gh.common.chain.DownloadChainBuilder;
import com.gh.common.chain.DownloadChainHandler;
import com.gh.common.chain.CheckDownloadHandler;
import com.gh.common.chain.CheckStoragePermissionHandler;
import com.gh.common.chain.DownloadChainBuilder;
import com.gh.common.chain.DownloadChainHandler;
import com.gh.common.chain.DownloadDialogHelperHandler;
import com.gh.common.chain.GamePermissionHandler;
import com.gh.common.chain.LandPageAddressHandler;
@ -287,19 +287,11 @@ public class BindingAdapters {
});
break;
case RESERVED:
if ("download".equals(gameEntity.getReserveStatus())) {
ReservationHelper.showDeleteReservationDialog(progressBar.getContext(), () -> {
ReservationHelper.deleteReservation(gameEntity, () -> {
updateReservation(progressBar, gameEntity);
});
ReservationHelper.showCancelReservationDialog(progressBar.getContext(),gameEntity, () -> {
ReservationHelper.cancelReservation(gameEntity, () -> {
updateReservation(progressBar, gameEntity);
});
} else {
ReservationHelper.showCancelReservationDialog(progressBar.getContext(),gameEntity, () -> {
ReservationHelper.cancelReservation(gameEntity, () -> {
updateReservation(progressBar, gameEntity);
});
});
}
});
break;
case H5_GAME:
LinkEntity linkEntity = gameEntity.getH5Link();
@ -345,9 +337,9 @@ public class BindingAdapters {
}
progressBar.setButtonStyle(DownloadButton.ButtonStyle.H5_GAME);
} else {
if (offStatus != null && "dialog".equals(offStatus)) {
if (("dialog".equals(offStatus) || "third_party".equals(offStatus))) {
progressBar.setText("查看");
progressBar.setButtonStyle(DownloadButton.ButtonStyle.NONE);
progressBar.setButtonStyle(DownloadButton.ButtonStyle.NONE_WITH_HINT);
} else if ("updating".equals(offStatus)) {
progressBar.setText("更新中");
progressBar.setButtonStyle(DownloadButton.ButtonStyle.UPDATING);

View File

@ -3,7 +3,6 @@ package com.gh.common.dialog
import android.animation.ValueAnimator
import android.content.Context
import android.content.DialogInterface
import android.content.pm.PackageInfo
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -19,7 +18,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.DirectUtils
import com.gh.common.util.LogUtils
import com.gh.common.util.PackageHelper
import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
@ -59,7 +57,6 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
private val mDuration = 3000
private var mDisposable: Disposable? = null
private var mAdapter: PackageCheckAdapter? = null
private var mAllInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0)
var gameEntity: GameEntity? = null
var callBack: ConfirmListener? = null
@ -195,7 +192,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
if (binding.noRemindAgainCb.isChecked) {
saveRecord(entity)
}
val isAllPackageInstalled = isAllPackageInstalled(mAllInstalledPackages, entity)
val isAllPackageInstalled = isAllPackageInstalled(entity)
if (isAllPackageInstalled) {
mDismissByTouchInside = true
callBack?.onConfirm()
@ -299,7 +296,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
private fun getNotInstalledLink(packageDialogEntity: PackageDialogEntity): LinkEntity? {
val links = LinkedHashSet<LinkEntity>()
packageDialogEntity.detectionObjects.forEach { obj ->
if (!checkDetectionsInstalled(mAllInstalledPackages, obj.packages)) {
if (!checkDetectionsInstalled(obj.packages)) {
obj.assignDownload.forEach {
links.add(packageDialogEntity.links[it])
}
@ -325,9 +322,8 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
override fun onResume() {
super.onResume()
mAllInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0)
gameEntity?.packageDialog?.let {
if (isAllPackageInstalled(mAllInstalledPackages, it)) {
if (isAllPackageInstalled(it)) {
callBack?.onConfirm()
dismissAllowingStateLoss()
}
@ -363,7 +359,6 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) {
if (busFour.isInstalledOrUninstalled()) {
mAllInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0)
mAdapter?.notifyDataSetChanged()
}
}
@ -388,7 +383,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
val entity = entities[position]
holder.binding.gameNameTv.text = entity.text
if (position <= index) {
val isAllInstalled = checkDetectionsInstalled(mAllInstalledPackages, entity.packages)
val isAllInstalled = checkDetectionsInstalled(entity.packages)
if (isAllInstalled) {
holder.binding.statusTv.text = "已安装"
holder.binding.statusTv.setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.text_theme))
@ -416,8 +411,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
return
}
val allInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0)
if (isAllPackageInstalled(allInstalledPackages, packageDialogEntity)) {
if (isAllPackageInstalled(packageDialogEntity)) {
callBack.onConfirm()
return
}
@ -453,13 +447,11 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
}
private fun checkDetectionsInstalled(
allInstalledPackages: List<String>,
packages: ArrayList<String>
): Boolean {
var isPackagesInstalled = false
packages.forEach { packageName ->
val isInstalled = allInstalledPackages.find { it == packageName } != null
if (isInstalled) {
if (PackageUtils.isInstalledFromAllPackage(HaloApp.getInstance(), packageName)) {
isPackagesInstalled = true
return@forEach
}
@ -469,17 +461,14 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
fun isAllPackageInstalled(
allInstalledPackages: List<String>,
packageDialogEntity: PackageDialogEntity
): Boolean {
var isAllInstalled = true
packageDialogEntity.detectionObjects.forEach loop@{ obj ->
if (!checkDetectionsInstalled(allInstalledPackages, obj.packages)) {
isAllInstalled = false
return isAllInstalled
if (!checkDetectionsInstalled(obj.packages)) {
return false
}
}
return isAllInstalled
return true
}
}
}

View File

@ -17,7 +17,7 @@ import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.databinding.DialogWechatBindingFailedBinding
import com.gh.gamecenter.login.user.UserRepository
import com.gh.gamecenter.login.user.UserManager
import com.lightgame.utils.Utils
class WechatBindingFailedDialogFragment : BaseDialogFragment() {
@ -48,10 +48,10 @@ class WechatBindingFailedDialogFragment : BaseDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
UserRepository.getInstance().loginUserInfo.observe(viewLifecycleOwner) {
currentUserId = it.data.getShortUserId()
binding.tvCurrentName.text = it.data.name
binding.ivCurrentAvatar.displayAvatar(it.data.icon)
UserManager.getInstance().userInfoEntity?.let {
currentUserId = it.getShortUserId()
binding.tvCurrentName.text = it.name ?: ""
binding.ivCurrentAvatar.displayAvatar(it.icon)
binding.tvUserId.text = getString(R.string.user_id, currentUserId)
}

View File

@ -31,6 +31,7 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
override fun onFragmentPaused(fm: FragmentManager, f: Fragment) {
if (fragment == f) {
visibleState?.let { commitExposure(it) }
visibleState?.let { commitWXCPMExposure(it) }
throttleBus.clear()
}
}

View File

@ -0,0 +1,45 @@
package com.gh.common.fragment
import androidx.fragment.app.FragmentManager
import java.lang.reflect.Field
fun FragmentManager.popBackStackAllowStateLoss() {
popBackStackAllowStateLoss(-1, 0)
}
fun FragmentManager.popBackStackAllowStateLoss(id: Int, flags: Int) {
if (!isStateSaved) {
popBackStack(id, flags)
}
}
fun FragmentManager.popBackStackAllowStateLoss(name: String?, flags: Int) {
if (!isStateSaved) {
popBackStack(name, flags)
}
}
fun FragmentManager.popBackStackImmediateAllowStateLoss() = popBackStackAllowStateLoss(-1, 0)
fun FragmentManager.popBackStackImmediateAllowStateLoss(id: Int, flags: Int) =
if (!isStateSaved) {
popBackStackImmediate(id, flags)
} else {
false
}
@Throws(NoSuchFieldException::class)
private fun getField(clazz: Class<*>, name: String): Field {
var cls: Class<*>? = clazz
while (cls != null) {
try {
val declaredField = cls.getDeclaredField(name)
declaredField.isAccessible = true
return declaredField
} catch (e: NoSuchFieldException) {
e.printStackTrace()
}
cls = cls.superclass
}
throw NoSuchFieldException()
}

View File

@ -112,6 +112,12 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
"本地下载"
}
// 小游戏的启动不需要上报下载点击事件
// @see https://jira.shanqu.cc/browse/GHZSCY-7013
if (boundedObject is GameEntity && boundedObject.isMiniGame()) {
return
}
// 上报神策点击事件
val customPageKV = customPageTrackData?.toKV() ?: arrayOf()
SensorsBridge.trackEventWithExposureSource(
@ -121,7 +127,7 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
"game_name", gameName,
"game_type", gameTypeInChinese,
"download_status", downloadStatusInChinese,
"button_name", downloadButton.text,
"button_name", text,
"game_schema_type", gameSchemaType,
"download_type", downloadType,
"page_name", GlobalActivityManager.getCurrentPageEntity().pageName,

View File

@ -2,18 +2,16 @@ package com.gh.common.provider
import android.content.Context
import android.content.Intent
import com.therouter.router.Route
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.feature.provider.IGameCollectionDetailProvider
import com.gh.gamecenter.gamecollection.detail.GameCollectionDetailActivity
@com.therouter.inject.ServiceProvider
class GameCollectionDetailProviderImpl : IGameCollectionDetailProvider {
override fun getIntent(context: Context, gameCollectionId: String, isFromSquare: Boolean): Intent {
return GameCollectionDetailActivity.getIntent(context, gameCollectionId, isFromSquare)
override fun getIntent(context: Context, gameCollectionId: String, isFromSquare: Boolean, entrance: String): Intent {
return GameCollectionDetailActivity.getIntent(context, gameCollectionId, isFromSquare, entrance)
}
override fun getSpecifiedCommentIntent(context: Context, gameCollectionId: String, topCommentId: String): Intent {
return GameCollectionDetailActivity.getSpecifiedCommentIntent(context, gameCollectionId, topCommentId)
override fun getSpecifiedCommentIntent(context: Context, gameCollectionId: String, topCommentId: String, entrance: String): Intent {
return GameCollectionDetailActivity.getSpecifiedCommentIntent(context, gameCollectionId, topCommentId, entrance)
}
}

View File

@ -4,6 +4,8 @@ import android.annotation.SuppressLint
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.database.sqlite.SQLiteDiskIOException
import android.database.sqlite.SQLiteException
import android.graphics.Bitmap
import android.net.Uri
import android.text.TextUtils
@ -284,7 +286,11 @@ object SimulatorGameManager {
entity.isRecentlyPlayed = it.id == gameId
simulatorGameRecordList.add(entity)
}
simulatorGameDao.addSimulatorGameList(simulatorGameRecordList)
try {
simulatorGameDao.addSimulatorGameList(simulatorGameRecordList)
} catch (e: SQLiteException) {
e.printStackTrace()
}
}
})
}

View File

@ -16,6 +16,7 @@ import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.constant.RouteConsts;
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.common.retrofit.BiResponse;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.core.AppExecutor;
import com.gh.gamecenter.core.provider.ISentryProvider;
import com.gh.gamecenter.core.utils.GsonUtils;
@ -39,6 +40,11 @@ import io.reactivex.schedulers.Schedulers;
*/
public class DataUtils {
// 神策 OAID 是否已绑定
private static boolean isSensorOAIDBounded = false;
// 原始的 OAID 是否已成功获取
private static boolean originalOAIDIsReceived = false;
private DataUtils() {
throw new IllegalStateException("Utility class");
}
@ -65,7 +71,6 @@ public class DataUtils {
// 默认用 APP 级已存储的 GID 来使用,不使用外部 GID
String savedGid = SPUtils.getString(Constants.GID);
if (!TextUtils.isEmpty(savedGid)) {
HaloApp.getInstance().setGid(savedGid);
onGidReceived(savedGid);
} else {
GidHelper.getInstance().registerDevice(HaloApp.getInstance().getApplication(), new GidCallback() {
@ -89,6 +94,8 @@ public class DataUtils {
}
private static void onGidReceived(String gid) {
bindValidOaidToSensor(false);
HaloApp.getInstance().setGid(gid);
// 更新广告配置
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
@ -111,6 +118,35 @@ public class DataUtils {
});
}
/**
* 为神策绑定有效的 OAID
*/
public static void bindValidOaidToSensor(boolean fromOaidResult) {
if (isSensorOAIDBounded) return;
String oaid = HaloApp.getInstance().getOAID();
// 来自于 oaid 获取回调,或者说原始 oaid 已经获取成功
if (fromOaidResult || originalOAIDIsReceived) {
originalOAIDIsReceived = true;
// 遇到异常的 OAID
if (Constants.INVALID_OAID_1.equals(oaid)
|| Constants.INVALID_OAID_2.equals(oaid)
|| Constants.INVALID_OAID_3.equals(oaid)
|| TextUtils.isEmpty(oaid)) {
// 若 gid 不为空,那么整合 gid 作为 oaid https://jira.shanqu.cc/browse/GHZSCY-7004
if (HaloApp.getInstance().getGid() != null) {
oaid = "GID" + HaloApp.getInstance().getGid();
SensorsBridge.INSTANCE.setOAID(oaid);
isSensorOAIDBounded = true;
}
} else {
SensorsBridge.INSTANCE.setOAID(oaid);
isSensorOAIDBounded = true;
}
}
}
/**
* 获取应用 gid 绑定的实名信息
*/

View File

@ -139,6 +139,7 @@ public class DetailDownloadUtils {
// 游戏包含多 APK 的情况
viewHolder.getMultiVersionDownloadTv().setText("选择下载你的版本" + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord));
viewHolder.getMultiVersionDownloadTv().setVisibility(View.VISIBLE);
viewHolder.getDownloadPb().setTag(com.gh.gamecenter.feature.R.string.download, viewHolder.getMultiVersionDownloadTv().getText());
viewHolder.getDownloadPb().setText("");
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity);
@ -457,7 +458,7 @@ public class DetailDownloadUtils {
}
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.H5_GAME);
} else {
if ("dialog".equals(gameEntity.getDownloadOffStatus())) {
if ("dialog".equals(gameEntity.getDownloadOffStatus()) || "third_party".equals(gameEntity.getDownloadOffStatus())) {
viewHolder.getDownloadPb().setText(TextUtils.isEmpty(gameEntity.getDownloadOffText()) ? "查看详情" : gameEntity.getDownloadOffText());
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.NONE_WITH_HINT);
} else if ("updating".equals(gameEntity.getDownloadOffStatus())) {

View File

@ -11,7 +11,6 @@ import android.os.Bundle
import android.text.TextUtils
import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf
import com.therouter.TheRouter
import com.gh.ad.AdPluginDownloadHelper
import com.gh.common.constant.Config
import com.gh.common.exposure.ExposureManager.log
@ -57,7 +56,6 @@ import com.gh.gamecenter.gamecollection.hotlist.GameCollectionHotListActivity
import com.gh.gamecenter.gamecollection.hotlist.GameCollectionListDetailActivity
import com.gh.gamecenter.gamecollection.square.GameCollectionSquareActivity
import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity
import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarManagementActivity
import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersSubscribedGameListActivity
import com.gh.gamecenter.gamedetail.history.HistoryApkListActivity
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
@ -77,7 +75,6 @@ import com.gh.gamecenter.qa.questions.newdetail.NewQuestionDetailActivity
import com.gh.gamecenter.qa.subject.CommunitySubjectActivity
import com.gh.gamecenter.qa.video.detail.ForumVideoDetailActivity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.servers.GameServerTestActivity
import com.gh.gamecenter.servers.GameServersActivity
import com.gh.gamecenter.servers.gametest2.GameServerTestV2Activity
@ -98,6 +95,7 @@ import com.halo.assistant.fragment.WebFragment
import com.lightgame.utils.Utils
import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import com.therouter.TheRouter
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import retrofit2.HttpException
@ -178,7 +176,23 @@ object DirectUtils {
"qa",
"feedback",
"toolkit",
"float_window_game"
"float_window_game",
"my_halo",
"my_game",
"server_manager",
"receiving_information",
"game_archive",
"game_dynamics",
"game_upload",
"certification",
"wechat_reminder",
"apk_clean",
"personal_center",
"video_upload",
"account_security",
"simulator",
"teen_mode",
"message_center",
)
fun directToLinkPage(
@ -383,8 +397,8 @@ object DirectUtils {
}
}
"authentication" -> {
context.startActivity(ShellActivity.getIntent(context, ShellActivity.Type.REAL_NAME_INFO, null))
"authentication", "certification" -> {
directToRealName(context)
}
"user_background" -> {
@ -442,7 +456,7 @@ object DirectUtils {
} ?: ""
}
"halo_tab" -> directToHomeMyHaloTab(context)
"my_halo", "halo_tab" -> directToHomeMyHaloTab(context)
"common_collection" -> directToCommonCollectionDetail(
context,
@ -524,7 +538,8 @@ object DirectUtils {
ToolbarWrapperActivity.getMultiTabNavIntent(
context,
linkEntity.link ?: "",
linkEntity.text ?: ""
linkEntity.text ?: "",
entrance
)
)
@ -532,16 +547,20 @@ object DirectUtils {
ToolbarWrapperActivity.getCustomPageIntent(
context,
linkEntity.link ?: "",
linkEntity.text ?: ""
linkEntity.text ?: "",
entrance
)
)
// 选中首页底部 tab
"bottom_tab" -> {
val intent = Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
if (HaloApp.getInstance().isRunningForeground) {
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
context.startActivity(intent)
} else {
jumpActivity(context, Bundle())
}
context.startActivity(intent)
if (linkEntity is LaunchRedirect) {
MainWrapperRepository.getInstance().sendSelectTabEvent(linkEntity)
@ -568,6 +587,32 @@ object DirectUtils {
}
}
"my_game" -> directToMyGame(0, entrance)
"server_manager" -> directToServersCalendarManagement(entrance)
"receiving_information" -> directToDeliveryInfo(entrance)
"game_archive" -> directToGameArchive(entrance)
"game_dynamics" -> directToConcernInfo(context, entrance)
"wechat_reminder" -> CheckLoginUtils.checkLogin(context, entrance) {
context.startActivity(WebActivity.getBindWechatIntent(context))
}
"apk_clean" -> directToCleanApk(context, entrance)
"personal_center" -> directToUserInfo(entrance)
"simulator" -> directToSimulatorGame(entrance)
"account_security" -> directToAccountSecurity(entrance)
"teen_mode" -> directToTeenMode(entrance)
"message_center" -> directToMessageCenter(0, entrance)
"" -> {
// do nothing
}
@ -2083,13 +2128,17 @@ object DirectUtils {
/**
* 跳转到开服订阅页面
* @param context 上下文
*/
@JvmStatic
fun directToServersCalendarManagement(context: Context, entrance: String) {
CheckLoginUtils.checkLogin(context, entrance) {
context.startActivity(ServersCalendarManagementActivity.getIntent(context))
}
fun directToServersCalendarManagement(entrance: String) {
val uri = Uri.Builder()
.path(RouteConsts.activity.serversCalendarManagementActivity)
.appendQueryParameter(RouteConsts.QueryParams.REQUIRE_LOGIN, "true")
.appendQueryParameter(RouteConsts.QueryParams.SOURCE, entrance)
.build()
TheRouter.build(uri.toString())
.navigation()
}
fun directToSearch(
@ -2149,4 +2198,100 @@ object DirectUtils {
)
}
}
@JvmStatic
fun directToMyGame(defaultTabIndex: Int, source: String) {
val uri = Uri.Builder()
.path(RouteConsts.activity.myGameActivity)
.appendQueryParameter(RouteConsts.QueryParams.SOURCE, source)
.build()
TheRouter.build(uri.toString())
.withInt(BaseActivity_TabLayout.PAGE_INDEX, defaultTabIndex)
.navigation()
}
@JvmStatic
fun directToDeliveryInfo(source: String) {
val uri = Uri.Builder()
.path(RouteConsts.activity.deliveryInfoActivity)
.appendQueryParameter(RouteConsts.QueryParams.REQUIRE_LOGIN, "true")
.appendQueryParameter(RouteConsts.QueryParams.SOURCE, source)
.build()
TheRouter.build(uri.toString())
.navigation()
}
@JvmStatic
fun directToGameArchive(source: String) {
val uri = Uri.Builder()
.path(RouteConsts.activity.gameArchiveListActivity)
.appendQueryParameter(RouteConsts.QueryParams.SOURCE, source)
.build()
TheRouter.build(uri.toString())
.navigation()
}
@JvmStatic
fun directToSimulatorGame(source: String) {
val uri = Uri.Builder()
.path(RouteConsts.activity.simulatorGameActivity)
.appendQueryParameter(RouteConsts.QueryParams.SOURCE, source)
.build()
TheRouter.build(uri.toString())
.navigation()
}
@JvmStatic
fun directToTeenMode(source: String) {
val uri = Uri.Builder()
.path(RouteConsts.activity.teenagerModeActivity)
.appendQueryParameter(RouteConsts.QueryParams.SOURCE, source)
.build()
TheRouter.build(uri.toString())
.navigation()
}
@JvmStatic
fun directToUserInfo(source: String) {
val uri = Uri.Builder()
.path(RouteConsts.activity.userInfoActivity)
.appendQueryParameter(RouteConsts.QueryParams.REQUIRE_LOGIN, "true")
.appendQueryParameter(RouteConsts.QueryParams.SOURCE, source)
.build()
TheRouter.build(uri.toString())
.navigation()
}
@JvmStatic
fun directToCleanApk(context: Context, source: String) {
val uri = Uri.Builder()
.path(RouteConsts.activity.cleanApkActivity)
.appendQueryParameter(RouteConsts.QueryParams.SOURCE, source)
.build()
PermissionHelper.checkManageAllFilesOrStoragePermissionBeforeAction(context) {
TheRouter.build(uri.toString())
.navigation()
}
}
@JvmStatic
fun directToAccountSecurity(source: String, isLogoutStyle: Boolean = false) {
val uri = Uri.Builder()
.path(RouteConsts.activity.securityActivity)
.appendQueryParameter(RouteConsts.QueryParams.REQUIRE_LOGIN, "true")
.appendQueryParameter(RouteConsts.QueryParams.SOURCE, source)
.build()
TheRouter.build(uri.toString())
.withString(KEY_ENTRANCE, source)
.withBoolean(KEY_DISPLAY_TYPE, isLogoutStyle)
.navigation()
}
}

View File

@ -280,9 +280,9 @@ object DownloadItemUtils {
isClickable = true
buttonStyle = DownloadButton.ButtonStyle.NORMAL
} else {
if ("dialog" == offStatus) {
if ("dialog" == offStatus || "third_party" == offStatus) {
text = context.getString(com.gh.gamecenter.feature.R.string.check)
buttonStyle = DownloadButton.ButtonStyle.NORMAL
buttonStyle = DownloadButton.ButtonStyle.NONE_WITH_HINT
} else if ("updating" == offStatus) {
text = context.getString(com.gh.gamecenter.feature.R.string.updating)
buttonStyle = DownloadButton.ButtonStyle.UPDATING
@ -839,34 +839,25 @@ object DownloadItemUtils {
} else {
allStateClickCallback?.onCallback()
clickCallback?.onCallback()
if ("download" == gameEntity.reserveStatus) {
ReservationHelper.showDeleteReservationDialog(context) {
ReservationHelper.deleteReservation(gameEntity) {
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}
ReservationHelper.showCancelReservationDialog(context, gameEntity, {
NewFlatLogUtils.logMyGameCancelReserveDialogClick(
"确定取消",
gameEntity.id,
gameEntity.name ?: ""
)
ReservationHelper.cancelReservation(gameEntity) {
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}
} else {
ReservationHelper.showCancelReservationDialog(context, gameEntity,{
}, object : CancelListener {
override fun onCancel() {
NewFlatLogUtils.logMyGameCancelReserveDialogClick(
"确定取消",
"关闭弹窗",
gameEntity.id,
gameEntity.name ?: ""
)
ReservationHelper.cancelReservation(gameEntity) {
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}
}, object : CancelListener {
override fun onCancel() {
NewFlatLogUtils.logMyGameCancelReserveDialogClick(
"关闭弹窗",
gameEntity.id,
gameEntity.name ?: ""
)
}
})
}
}
})
}
}
return

View File

@ -53,6 +53,7 @@ object DownloadObserver {
private const val CORE_EVENT_DOWNLOAD_COMPLETE_LOGGED = "CORE_EVENT_DOWNLOAD_COMPLETE_LOGGED"
private val mRetryableHashMap = hashMapOf<String, Boolean>()
private val mRetryableProgressMap = hashMapOf<String, Long>()
/**
* 当下载任务是 预约上线提醒 触发的,则所有弹窗均不显示
@ -146,7 +147,8 @@ object DownloadObserver {
|| DownloadStatus.timeout == status
) {
if (mRetryableHashMap[downloadEntity.url] == true
&& NetworkUtils.isWifiConnected(HaloApp.getInstance().application)
&& (NetworkUtils.isWifiConnected(HaloApp.getInstance().application)
|| NDownloadBridge.isDownloadViaTrafficAllowed(downloadEntity))
) {
downloadManager.resumeDownload(downloadEntity.url)
mRetryableHashMap[downloadEntity.url] = false
@ -257,6 +259,7 @@ object DownloadObserver {
}
mRetryableHashMap.remove(downloadEntity.url)
mRetryableProgressMap.remove(downloadEntity.url)
EventBus.getDefault().post(EBDownloadStatus("done", "", "", "", downloadEntity.packageName, ""))
}
@ -264,7 +267,9 @@ object DownloadObserver {
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
// 如果已下载大小发生变化,表示成功恢复下载,则重置重试标记
if (status == DownloadStatus.downloading) {
if (status == DownloadStatus.downloading
&& downloadEntity.progress != mRetryableProgressMap[downloadEntity.url]) {
mRetryableProgressMap[downloadEntity.url] = downloadEntity.progress
mRetryableHashMap[downloadEntity.url] = true
}
}

View File

@ -135,12 +135,16 @@ object GameUtils {
// 畅玩状态优先,且畅玩实体不为空时将 downloadEntity 置为畅玩实体
if (performAsVGame && vGameDownloadEntity != null) {
downloadEntity = vGameDownloadEntity
} else if (!performAsVGame && !isFromList && downloadEntity?.isVGameDownloadInDualDownloadMode() == true) {
// 下载的任务是由畅玩触发的,游戏详情页不需判定为需要安装
downloadEntity = null
} else if (performAsVGame && !isFromList && downloadEntity?.isLocalDownloadInDualDownloadMode() == true) {
// 下载的任务是由下载安装触发的,游戏详情页不需判定为需要安装
downloadEntity = null
} else if (!isFromList) {
if (!performAsVGame
&& gameEntity.isDualBtnModeEnabled()
&& downloadEntity?.isVGameDownloadInDualDownloadMode() == true) {
// 下载的任务是由畅玩触发的,并且双下载按钮启用,游戏详情页不需判定为需要安装
downloadEntity = null
} else if (performAsVGame && downloadEntity?.isLocalDownloadInDualDownloadMode() == true) {
// 下载的任务是由下载安装触发的,游戏详情页不需判定为需要安装
downloadEntity = null
}
}
if (downloadEntity != null) {

View File

@ -2778,4 +2778,34 @@ object NewFlatLogUtils {
parseAndPutMeta()(this)
}.let(::log)
}
// 自有开屏广告加载
fun logSplashAdLoad(id: String) {
json {
KEY_EVENT to "splash_ad_load"
"ad_id" to id
parseAndPutMeta()(this)
}.let(::log)
}
// 自有开屏广告展示
fun logSplashAdShow(id: String, duration: Long) {
json {
KEY_EVENT to "splash_ad_show"
"ad_id" to id
"duration" to duration
parseAndPutMeta()(this)
}.let(::log)
}
// 自有开屏广告加载/展示失败
@JvmStatic
fun logSplashAdFail(id: String, error: String) {
json {
KEY_EVENT to "splash_ad_fail"
"ad_id" to id
"error" to error
parseAndPutMeta()(this)
}.let(::log)
}
}

View File

@ -578,7 +578,6 @@ object PackageHelper {
Utils.log(TAG, "refreshWrongInstallStatus 检查安装状态异常的应用")
val uninstalledButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
val updatedButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
for (packageName in packageNameSet) {
val installedVersionName = PackageUtils.getVersionNameByPackageName(packageName)
@ -587,18 +586,9 @@ object PackageHelper {
&& installedVersionName == null
) {
uninstalledButKeepingWrongStatusPackageNameSet.add(packageName)
} else if (PackagesManager.isInstalled(packageName)
&& installedVersionName != null
&& !PackagesManager.isInstalledWithSpecificVersion(packageName, installedVersionName)
) {
updatedButKeepingWrongStatusPackageNameSet.add(packageName)
}
}
Utils.log(
TAG,
"refreshWrongInstallStatus 需要更新已更新状态的包数量为 ${updatedButKeepingWrongStatusPackageNameSet.size}"
)
Utils.log(
TAG,
"refreshWrongInstallStatus 需要移除已安装的包数量为 ${uninstalledButKeepingWrongStatusPackageNameSet.size}"
@ -616,12 +606,6 @@ object PackageHelper {
additionalWhiteListPackageNameSet.toString()
)
}
if (updatedButKeepingWrongStatusPackageNameSet.isNotEmpty()) {
for (packageName in updatedButKeepingWrongStatusPackageNameSet) {
PackageChangeHelper.addUpdate(packageName)
}
}
}
}
}
@ -635,7 +619,6 @@ object PackageHelper {
val installedButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
val uninstalledButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
val updatedButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
for (game in gameEntityList) {
for (apk in game.getApk()) {
@ -651,13 +634,6 @@ object PackageHelper {
&& installedVersionName == null
) {
uninstalledButKeepingWrongStatusPackageNameSet.add(packageName)
} else if (PackagesManager.isInstalled(packageName)
&& installedVersionName != null
&& !PackagesManager.isInstalledWithSpecificVersion(packageName, installedVersionName)
&& !PackagesManager.isCanUpdate(game.id, packageName, false)
) {
cachedPkgNameAndGameEntityMap.put(packageName, game)
updatedButKeepingWrongStatusPackageNameSet.add(packageName)
}
}
}
@ -666,10 +642,6 @@ object PackageHelper {
TAG,
"refreshWrongInstallStatus 需要更新已安装状态的包数量为 ${installedButKeepingWrongStatusPackageNameSet.size}"
)
Utils.log(
TAG,
"refreshWrongInstallStatus 需要更新已更新状态的包数量为 ${updatedButKeepingWrongStatusPackageNameSet.size}"
)
Utils.log(
TAG,
"refreshWrongInstallStatus 需要移除已安装的包数量为 ${uninstalledButKeepingWrongStatusPackageNameSet.size}"
@ -699,12 +671,6 @@ object PackageHelper {
additionalWhiteListPackageNameSet.toString()
)
}
if (updatedButKeepingWrongStatusPackageNameSet.isNotEmpty()) {
for (packageName in updatedButKeepingWrongStatusPackageNameSet) {
PackageChangeHelper.addUpdate(packageName, cachedPkgNameAndGameEntityMap.remove(packageName))
}
}
}
}
}

View File

@ -18,7 +18,6 @@ import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.install.InstallService
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
@ -194,12 +193,6 @@ object PackageInstaller {
private fun install(context: Context, pkgPath: String, pkgName: String?) {
HaloApp.put(Constants.LAST_INSTALL_GAME, pkgPath)
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU && Build.MANUFACTURER.lowercase().contains("xiaomi")) {
val foregroundServiceIntent = Intent(context, InstallService::class.java)
foregroundServiceIntent.putExtra(InstallService.KEY_SERVICE_ACTION, InstallService.START_FOREGROUND)
context.startForegroundService(foregroundServiceIntent)
}
val installIntent = getInstallIntent(context, pkgPath)
context.startActivity(installIntent)
@ -284,7 +277,12 @@ object PackageInstaller {
installIntent.setDataAndType(uri, "application/vnd.android.package-archive")
}
updateSystemInstallerIfAvailable(context, installIntent)
// 优选系统的安装器(遇到 Exception 就回落到正常的安装器)
try {
updateSystemInstallerIfAvailable(context, installIntent)
} catch (ignored: Exception) {
// ignored
}
InstallUtils.getInstance()
.addInstall(PackageUtils.getPackageNameByPath(context, path))

View File

@ -7,7 +7,7 @@ import com.gh.gamecenter.common.utils.isVGameDownloadInDualDownloadMode
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.GameInstall
import com.gh.gamecenter.packagehelper.PackageRepository
import com.gh.gamecenter.manager.PackagesManager
import com.gh.vspace.VHelper
object PackageLauncher {
@ -81,28 +81,11 @@ object PackageLauncher {
gameEntity: GameEntity? = null,
packageName: String?
) {
if (packageName.isNullOrEmpty()) {
ToastUtils.toast("启动失败")
return
}
// 获取 GameInstall 实体,用于记录启动日志用
val gameInstall = if (gameEntity != null) {
GameInstall.transformGameInstall(gameEntity, packageName)
} else {
PackageRepository.gameInstalled.find { it.packageName == packageName }
}
if (gameInstall != null) {
NewFlatLogUtils.logGameLaunch(
gameId = gameInstall.id ?: "unknown",
gameName = gameInstall.name ?: "unknown",
gameCategory = gameInstall.category ?: "unknown",
downloadStatus = if (gameInstall.downloadStatus == "demo") "试玩" else "下载"
)
}
try {
val intent = context.applicationContext.packageManager.getLaunchIntentForPackage(packageName)
if (intent != null) {
@ -113,6 +96,26 @@ object PackageLauncher {
} catch (e: Exception) {
ToastUtils.toast( "启动失败")
}
try {
// 获取 GameInstall 实体,用于记录启动日志用
val gameInstall = if (gameEntity != null) {
GameInstall.transformGameInstall(gameEntity, packageName)
} else {
PackagesManager.getInstalledList().find { it.packageName == packageName }
}
if (gameInstall != null) {
NewFlatLogUtils.logGameLaunch(
gameId = gameInstall.id ?: "unknown",
gameName = gameInstall.name ?: "unknown",
gameCategory = gameInstall.category ?: "unknown",
downloadStatus = if (gameInstall.downloadStatus == "demo") "试玩" else "下载"
)
}
} catch (e: RuntimeException) {
// 都 DeadSystemException 了,还想啥日志上报
}
}
}

View File

@ -14,7 +14,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.text.TextUtils;
import android.util.AndroidException;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -29,9 +28,9 @@ import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.core.utils.MD5Utils;
import com.gh.gamecenter.entity.GameUpdateEntity;
import com.gh.gamecenter.feature.entity.ApkEntity;
import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.entity.GameUpdateEntity;
import com.gh.gamecenter.feature.utils.SentryHelper;
import com.gh.gamecenter.manager.PackagesManager;
import com.gh.vspace.VHelper;
@ -302,7 +301,7 @@ public class PackageUtils {
Signature[] signatures = packageInfo.signatures;
// 使用幸运破解器破解安卓签名认证可能会出现不用签名也能装的情况,这里有可能是空的
if (signatures[0] != null) {
if (signatures.length > 0 && signatures[0] != null) {
return parseSignature(signatures[0].toByteArray());
} else {
return new String[]{null, null};
@ -542,10 +541,8 @@ public class PackageUtils {
try {
Intent intent = context.getApplicationContext().getPackageManager().getLaunchIntentForPackage(packageName);
return intent != null;
} catch (IllegalArgumentException exception) {
// 一些设备调用获取 intent 的时候会触发 Parcel.readException !
exception.printStackTrace();
return false;
} catch (Exception exception) {
return PackageHelper.INSTANCE.getLocalPackageNameSet().contains(packageName);
}
}
@ -645,6 +642,19 @@ public class PackageUtils {
return 0;
}
/*
* 获取应用的名称
*/
public static CharSequence getNameByPackageName(Context context, String packageName) {
try {
PackageManager packageManager = context.getApplicationContext().getPackageManager();
return packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA));
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/*
* 获取应用的 icon

View File

@ -29,53 +29,31 @@ import okhttp3.ResponseBody
object ReservationHelper {
@JvmStatic
fun deleteReservation(game: GameEntity, refreshCallback: EmptyCallback) {
deleteOrCancelReservation(game, true, refreshCallback)
}
@JvmStatic
fun cancelReservation(game: GameEntity, refreshCallback: EmptyCallback) {
deleteOrCancelReservation(game, false, refreshCallback)
}
@SuppressLint("CheckResult")
private fun deleteOrCancelReservation(
@JvmStatic
fun cancelReservation(
game: GameEntity,
deleteReservation: Boolean,
refreshCallback: EmptyCallback
) {
val retrofit = RetrofitManager.getInstance()
val single = if (deleteReservation) {
retrofit.newApi
.deleteGameReservation(
game.id,
getReserveRequestBody(game, context = HaloApp.getInstance().application)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
} else {
retrofit.newApi
.cancelGameReservation(
game.id,
getReserveRequestBody(game, context = HaloApp.getInstance().application)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
retrofit.newApi
.cancelGameReservation(
game.id,
getReserveRequestBody(game, context = HaloApp.getInstance().application)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
ReservationRepository.removeReservationFromMemoryAndRefresh(game.id)
refreshCallback.onCallback()
}
single.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
ReservationRepository.removeReservationFromMemoryAndRefresh(game.id)
refreshCallback.onCallback()
}
override fun onFailure(exception: Exception) {
Utils.toast(HaloApp.getInstance().application, exception.message)
exception.printStackTrace()
}
})
override fun onFailure(exception: Exception) {
Utils.toast(HaloApp.getInstance().application, exception.message)
exception.printStackTrace()
}
})
}
@JvmStatic
@ -146,21 +124,6 @@ object ReservationHelper {
})
}
@JvmStatic
fun showDeleteReservationDialog(context: Context, emptyCallback: EmptyCallback) {
DialogUtils.showCancelOrDeleteReservationDialog(
context,
"删除预约",
"游戏已上线,你可以删除此预约记录,确定删除吗?",
"确定删除",
"暂不删除", object : ConfirmListener {
override fun onConfirm() {
emptyCallback.onCallback()
}
}, null
)
}
@JvmStatic
fun showCancelReservationDialog(context: Context, game: GameEntity?, emptyCallback: EmptyCallback) {
showCancelReservationDialog(context, game, emptyCallback, null)

View File

@ -2,6 +2,7 @@ package com.gh.download.simple
import android.annotation.SuppressLint
import android.database.sqlite.SQLiteException
import android.database.sqlite.SQLiteFullException
import com.gh.gamecenter.core.utils.ToastUtils
import com.lg.download.*
import com.lg.download.listener.InnerDownloadListener
@ -174,6 +175,9 @@ object DownloadMessageHandler : InnerDownloadListener {
DownloadError.CONTENT_LENGTH_IS_ZERO -> {
ToastUtils.toast("下载链接异常,请检查")
}
DownloadError.DISK_IS_FULL -> {
ToastUtils.toast("磁盘已满,请清理空间后获得更好的体验")
}
else -> {
// 想怎么处理就怎么处理
}
@ -264,18 +268,30 @@ object DownloadMessageHandler : InnerDownloadListener {
}
fun insertDownloadToDatabase(downloadEntity: SimpleDownloadEntity) {
mDownloadDao.insertDownloadEntity(downloadEntity)
updateDownloadList()
try {
mDownloadDao.insertDownloadEntity(downloadEntity)
updateDownloadList()
} catch (e: SQLiteException) {
if (e is SQLiteFullException) {
ToastUtils.showToast("磁盘已满,请清理空间获得更好的体验")
}
e.printStackTrace()
}
}
fun updateDownloadToDatabase(
downloadEntity: SimpleDownloadEntity,
updateDownloadList: Boolean = false
) {
mDownloadDao.updateDownloadEntity(downloadEntity)
try {
mDownloadDao.updateDownloadEntity(downloadEntity)
if (updateDownloadList) {
updateDownloadList()
if (updateDownloadList) {
updateDownloadList()
}
} catch (e: SQLiteFullException) {
// 底层的下载服务遇到 SQLiteFullException 时会自动暂停下载任务,上层这里就不用纠结处理方式了
e.printStackTrace()
}
}

View File

@ -166,8 +166,13 @@ public class MainActivity extends BaseActivity {
private final Handler handler = new Handler();
private boolean mShouldShowAd = false; // 是否显示广告
private Bundle mTempSavedInstanceState;
private boolean mFragmentIsCreated = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
mTempSavedInstanceState = savedInstanceState;
mShouldShowAd = getIntent().getBooleanExtra(SHOW_AD, false) && savedInstanceState == null
&& !HaloApp.getInstance().isAlreadyUpAndRunning;
HaloApp.getInstance().isAlreadyUpAndRunning = true;
@ -175,21 +180,12 @@ public class MainActivity extends BaseActivity {
mMainWrapperViewModel = new ViewModelProvider(this, new MainWrapperViewModel.Factory(HaloApp.getInstance()))
.get(MainWrapperViewModel.class);
DisplayUtils.transparentStatusBar(this);
DisplayUtils.updateGlobalScreen(this);
super.onCreate(savedInstanceState);
setStatusBarColor(Color.TRANSPARENT);
Fragment fragmentFromFM = getSupportFragmentManager().findFragmentById(com.gh.gamecenter.selector.R.id.layout_activity_content);
mMainWrapperFragment = fragmentFromFM != null ? (MainWrapperFragment) fragmentFromFM : new MainWrapperFragment();
if (savedInstanceState != null) {
mMainWrapperFragment.setArguments(savedInstanceState);
} else if (getIntent() != null) {
mMainWrapperFragment.setArguments(getIntent().getExtras());
}
replaceFragment(mMainWrapperFragment);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
if (HaloApp.getInstance().isNewForThisVersion) {
LunchType lunchType = HaloApp.getInstance().getLaunchType();
@ -215,7 +211,6 @@ public class MainActivity extends BaseActivity {
DataUtils.getGid();
}
mPackageViewModel = ViewModelProviders.of(this, new PackageViewModel.Factory()).get(PackageViewModel.class);
final boolean containsErrorMsg = com.gh.gamecenter.common.constant.Config.isContainsErrorMsg();
@ -273,6 +268,7 @@ public class MainActivity extends BaseActivity {
if (mShouldShowAd) {
showAd();
} else {
doInitMainFragment(mTempSavedInstanceState);
hideTextAd();
hideSplashAd();
}
@ -328,6 +324,23 @@ public class MainActivity extends BaseActivity {
CertificationSwitchHelper.getCertificationSwitch();
}
private void doInitMainFragment(Bundle savedInstanceState) {
if (mFragmentIsCreated) return;
mTempSavedInstanceState = null;
Fragment fragmentFromFM = getSupportFragmentManager().findFragmentById(com.gh.gamecenter.selector.R.id.layout_activity_content);
mMainWrapperFragment = fragmentFromFM != null ? (MainWrapperFragment) fragmentFromFM : new MainWrapperFragment();
if (savedInstanceState != null) {
mMainWrapperFragment.setArguments(savedInstanceState);
} else if (getIntent() != null) {
mMainWrapperFragment.setArguments(getIntent().getExtras());
}
replaceFragment(mMainWrapperFragment);
mFragmentIsCreated = true;
}
@SuppressLint("CheckResult")
private void getTeenagerMode() {
RetrofitManager.getInstance()
@ -541,19 +554,31 @@ public class MainActivity extends BaseActivity {
protected void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == COUNTDOWN_AD || msg.what == COUNTDOWN_SDK_AD) {
mCountdownCount++;
int maxCount;
if (msg.what == COUNTDOWN_AD) {
maxCount = mCountdownMaxCount;
} else {
maxCount = COUNTDOWN_SDK_MAX_COUNT;
}
// 读秒到一半的时候初始化 MainWrapperFragment
if (mCountdownCount == maxCount / 2) {
doInitMainFragment(mTempSavedInstanceState);
}
mCountdownCount++;
if (maxCount < mCountdownCount) {
AdDelegateHelper.INSTANCE.setShowingSplashAd(false);
hideSplashAd();
if (msg.what == COUNTDOWN_AD && msg.obj instanceof StartupAdEntity) {
StartupAdEntity ad = (StartupAdEntity) msg.obj;
if (!AdDelegateHelper.INSTANCE.isOwnerSplashAdShown()) {
com.gh.common.util.NewFlatLogUtils.logSplashAdFail(ad.getId(), "广告加载超时");
}
AdDelegateHelper.INSTANCE.setOwnerSplashAdShown(false);
LinkEntity linkEntity = ad.getJump();
SensorsBridge.trackEvent(
"SplashAdOwnSkip",
@ -633,10 +658,11 @@ public class MainActivity extends BaseActivity {
ExtensionsKt.removeFromParent(startSdkAdIcpContainer, true);
}
onSplashHidden();
onAdHidden();
}
private void onSplashHidden() {
private void onAdHidden() {
doInitMainFragment(mTempSavedInstanceState);
// 通知全局弹窗可以进行显示
AppExecutor.getUiExecutor().execute(GlobalPriorityChainHelper.INSTANCE::start);
}
@ -854,7 +880,9 @@ public class MainActivity extends BaseActivity {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0 && !mMainWrapperFragment.onHandleBackPressed()) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0
&& mMainWrapperFragment != null
&& !mMainWrapperFragment.onHandleBackPressed()) {
DownloadEntity downloadEntity = null;
for (DownloadEntity entity : DownloadManager.getInstance().getAllDownloadEntityExcludeSilentTask()) {
if (entity.getStatus().equals(DownloadStatus.done)) {
@ -1045,6 +1073,7 @@ public class MainActivity extends BaseActivity {
blackList.add(R.id.historyTv);
blackList.add(R.id.myCollectionTv);
blackList.add(R.id.searchTv);
blackList.add(R.id.subject_tab);
updateStaticView(view, blackList);
View communityHomeWrapper = view.findViewById(R.id.communityHomeContainer);

View File

@ -15,6 +15,7 @@ import androidx.core.widget.doAfterTextChanged
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import com.gh.common.fragment.popBackStackAllowStateLoss
import com.gh.common.util.DataCollectionUtils
import com.gh.common.util.LogUtils
import com.gh.gamecenter.DisplayType.*
@ -190,6 +191,7 @@ open class SearchActivity : BaseActivity() {
when (type) {
SearchType.AUTO -> handleAutoSearch(key)
SearchType.DEFAULT -> handleDefaultSearch(key)
SearchType.DISCOVERY -> handleDiscoverySearch(key)
SearchType.RANK -> handleRankSearch(key)
SearchType.HOT -> handleHotSearch(key)
SearchType.HISTORY -> handleHistorySearch(key)
@ -243,6 +245,22 @@ open class SearchActivity : BaseActivity() {
)
}
protected open fun handleDiscoverySearch(key: String?) {
mSearchKey = key
searchEt.setText(key)
searchEt.setSelection(searchEt.text.length)
updateDisplayType(GAME_DETAIL)
LogUtils.uploadSearchGame("searching", "搜索页", key, "搜索发现")
SensorsBridge.trackSearchButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
key ?: "",
TRACK_SEARCH_TYPE_DISCOVERY,
mSourceEntrance
)
}
protected open fun handleDefaultSearch(key: String?) {
mSearchKey = key
searchEt.setText(key)
@ -311,6 +329,19 @@ open class SearchActivity : BaseActivity() {
// MtaHelper.onEvent("游戏搜索", "主动搜索", newSearchKey)
}
override fun onResume() {
super.onResume()
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
if (newSearchKey.isBlank()) {
try {
popBackToFragment(SearchDefaultFragment::class.java.name)
} catch (e: Exception) {
// no implement
}
}
}
protected open fun provideDao(): ISearchHistoryDao = SearchHistoryDao(this)
open fun updateDisplayType(type: DisplayType) {
@ -381,7 +412,7 @@ open class SearchActivity : BaseActivity() {
}
protected fun popBackToFragment(tag: String) {
supportFragmentManager.popBackStack(tag, 0)
supportFragmentManager.popBackStackAllowStateLoss(tag, 0)
}
@Subscribe(threadMode = ThreadMode.MAIN)
@ -390,6 +421,7 @@ open class SearchActivity : BaseActivity() {
SearchType.HISTORY.value -> search(SearchType.HISTORY, search.key)
SearchType.HOT.value -> search(SearchType.HOT, search.key)
SearchType.RANK.value -> search(SearchType.RANK, search.key)
SearchType.DISCOVERY.value -> search(SearchType.DISCOVERY, search.key)
"click" -> DataCollectionUtils.uploadSearchClick(
this, mSearchKey, mSearchType.value, "搜索页面",
@ -434,6 +466,7 @@ open class SearchActivity : BaseActivity() {
const val TRACK_SEARCH_TYPE_DEFAULT = "默认搜索"
const val TRACK_SEARCH_TYPE_HISTORY = "历史搜索"
const val TRACK_SEARCH_TYPE_RANK = "榜单搜索"
const val TRACK_SEARCH_TYPE_DISCOVERY = "搜索发现"
@JvmStatic
fun toTrackSearchType(type: String) = when (type) {
@ -441,6 +474,7 @@ open class SearchActivity : BaseActivity() {
SearchType.MANUAL.value -> TRACK_SEARCH_TYPE_INPUT
SearchType.HISTORY.value -> TRACK_SEARCH_TYPE_HISTORY
SearchType.RANK.value -> TRACK_SEARCH_TYPE_RANK
SearchType.DISCOVERY.value -> TRACK_SEARCH_TYPE_DISCOVERY
else -> TRACK_SEARCH_TYPE_DEFAULT
}
@ -490,7 +524,8 @@ enum class SearchType(var value: String) {
HISTORY("history"),
MANUAL("initiative"),
HOT("remen"),
RANK("rank");
RANK("rank"),
DISCOVERY("dicovery");
fun toChinese() = when (this) {
AUTO -> "自动搜索"
@ -499,6 +534,7 @@ enum class SearchType(var value: String) {
MANUAL -> "主动搜索"
HOT -> "热门搜索"
RANK -> "榜单搜索"
DISCOVERY -> "搜索发现"
}
companion object {

View File

@ -62,16 +62,16 @@ import com.gh.gamecenter.common.base.activity.BaseActivity;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.constant.EntranceConsts;
import com.gh.gamecenter.common.entity.CommunityEntity;
import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.common.entity.LaunchRedirect;
import com.gh.gamecenter.common.entity.SimpleGameEntity;
import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.ToastUtils;
import com.gh.gamecenter.entity.SubjectData;
import com.gh.gamecenter.entity.SubjectRecommendEntity;
import com.gh.gamecenter.entity.VideoLinkEntity;
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper;
import com.gh.gamecenter.feature.utils.PlatformUtils;
import com.gh.gamecenter.login.view.LoginActivity;
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper;
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel;
import com.gh.gamecenter.video.videomanager.VideoManagerActivity;
import com.gh.vspace.VHelper;
@ -356,8 +356,8 @@ public class SkipActivity extends BaseActivity {
if (!TextUtils.isEmpty(dataString)) {
byte[] linkData = Base64.decode(dataString, Base64.DEFAULT);
String linkDataString = new String(linkData, "UTF-8");
LinkEntity le = GsonUtils.INSTANCE.getGson().fromJson(linkDataString, LinkEntity.class);
DirectUtils.directToLinkPage(this, le, entrance, "", "");
LaunchRedirect launchRedirect = GsonUtils.fromJson(linkDataString, LaunchRedirect.class);
DirectUtils.directToLinkPage(this, launchRedirect, entrance, "", "");
}
} catch (Exception e) {
e.printStackTrace();

View File

@ -282,11 +282,11 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
SensorsBridge.setOAID(HaloApp.getInstance().oaid)
val pushProvider = TheRouter.get(IPushProvider::class.java)
val registrationId = pushProvider?.getRegistrationId(this)
if (!registrationId.isNullOrEmpty()) {
SensorsBridge.profileAppend(KEY_REGISTRATION_ID, registrationId)
}
// val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
// val registrationId = pushProvider?.getRegistrationId(this)
// if (!registrationId.isNullOrEmpty()) {
// SensorsBridge.profileSet(KEY_REGISTRATION_ID, registrationId)
// }
}
private fun prefetchData() {

View File

@ -4,12 +4,15 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.utils.updateStatusBarColor
import com.halo.assistant.fragment.user.UserInfoFragment
import com.therouter.router.Route
/**
* 编辑资料
*/
@Route(
path = RouteConsts.activity.userInfoActivity,
description = "个人中心"
)
class UserInfoActivity : ToolBarActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@ -17,6 +20,14 @@ class UserInfoActivity : ToolBarActivity() {
updateStatusBarColor(com.gh.gamecenter.common.R.color.ui_surface, com.gh.gamecenter.common.R.color.ui_surface)
}
override fun provideNormalIntent(): Intent {
return getTargetIntent(
this,
UserInfoActivity::class.java,
UserInfoFragment::class.java
)
}
companion object {
fun getIntent(context: Context?): Intent? {
return getTargetIntent(

View File

@ -194,6 +194,10 @@ class DetailViewHolder(
if (mGameEntity.isLandPageAddressDialog() && !mGameEntity.isLandPageAddressDialogShowOnly()) {
// 第三方落地页为开启状态并且展示状态不为“仅显示弹窗”,需要在点击确认后显示弹窗
DialogUtils.showLandPageAddressDialog(mViewHolder.context, mGameEntity) {
val packageName = mGameEntity.getApk().firstOrNull()?.packageName
if (packageName?.isNotEmpty() == true) {
PackageChangeHelper.addInstallPendingPackage(packageName)
}
DirectUtils.directToExternalBrowser(mViewHolder.context, mGameEntity.landPageAddressDialog!!.link!!)
}
}
@ -271,14 +275,20 @@ class DetailViewHolder(
ButtonStyle.NONE_WITH_HINT, ButtonStyle.NONE -> {
val offStatus = mGameEntity.downloadOffStatus
if (offStatus != null && "off" != offStatus) {
if ("dialog" == offStatus) {
showOffServiceDialog(mGameEntity.downloadOffDialog) {
when (offStatus) {
"dialog" -> {
showOffServiceDialog(mGameEntity.downloadOffDialog) {
showLandPageAddressDialogIfNeeded()
}
}
"toast" -> {
EventBus.getDefault().post(EBReuse(GameDetailFragment.SKIP_RATING))
ToastUtils.toast("该游戏因故暂不提供下载,具体详情可在相关评论中查看,敬请谅解~")
showLandPageAddressDialogIfNeeded()
}
"third_party" -> {
showLandPageAddressDialogIfNeeded()
}
} else if ("toast" == offStatus) {
EventBus.getDefault().post(EBReuse(GameDetailFragment.SKIP_RATING))
ToastUtils.toast("该游戏因故暂不提供下载,具体详情可在相关评论中查看,敬请谅解~")
showLandPageAddressDialogIfNeeded()
}
} else {
ToastUtils.toast("该游戏已关闭下载")
@ -455,17 +465,9 @@ class DetailViewHolder(
}
ButtonStyle.RESERVED -> {
if ("download" == mGameEntity.reserveStatus) {
ReservationHelper.showDeleteReservationDialog(mViewHolder.context) {
ReservationHelper.deleteReservation(mGameEntity) {
DetailDownloadUtils.updateViewHolder(mViewHolder)
}
}
} else {
ReservationHelper.showCancelReservationDialog(mViewHolder.context, mGameEntity) {
ReservationHelper.cancelReservation(mGameEntity) {
DetailDownloadUtils.updateViewHolder(mViewHolder)
}
ReservationHelper.showCancelReservationDialog(mViewHolder.context, mGameEntity) {
ReservationHelper.cancelReservation(mGameEntity) {
DetailDownloadUtils.updateViewHolder(mViewHolder)
}
}
}

View File

@ -1,11 +1,16 @@
package com.gh.gamecenter.authorization
import android.app.Activity
import android.app.Application.ActivityLifecycleCallbacks
import android.app.Dialog
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.UserHandle
import com.gh.common.util.CheckLoginUtils
import com.gh.common.util.DialogUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.constant.EntranceConsts
@ -16,8 +21,10 @@ import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.databinding.ActivityAuthorizationBinding
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserRepository
import com.gh.gamecenter.login.view.LoginActivity
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
/**
@ -68,6 +75,13 @@ class AuthorizationActivity : ToolBarActivity() {
//授权token
private var mToken = ""
/**
* 游戏UID (适配双开/分身游戏)
*/
private var gameUid = -1
private var loadingDialog: Dialog? = null
override fun getLayoutId(): Int {
return R.layout.activity_authorization
}
@ -80,11 +94,16 @@ class AuthorizationActivity : ToolBarActivity() {
mBinding = ActivityAuthorizationBinding.bind(mContentView)
checkParam()
initView()
mBinding.authorizeBtn.postDelayed({
mBaseHandler.post {
if (loadingDialog == null) {
loadingDialog = DialogUtils.showWaitDialog(this, "请稍后...")
}
}
UserRepository.getInstance().loginUserInfo.observe(this) {
checkLogin {
initUserInfo()
}
}, 500)
}
NewFlatLogUtils.logLoginFromGHZSShow(
gameId = gameId,
gameName = gameName
@ -97,14 +116,21 @@ class AuthorizationActivity : ToolBarActivity() {
}
private fun initData() {
if (mToken.isNotEmpty() || isFinishing) return
val loadingDialog = DialogUtils.showWaitDialog(this, "请稍后...")
if (mToken.isNotEmpty() || isFinishing) {
loadingDialog?.dismiss()
return
}
if (loadingDialog == null) {
loadingDialog = DialogUtils.showWaitDialog(this, "请稍后...")
} else if (loadingDialog?.isShowing == false) {
loadingDialog?.show()
}
mViewModel.getAccessToken(listOf(mContent), {
mToken = it
loadingDialog.dismiss()
loadingDialog?.dismiss()
}, {
toast("获取token失败")
loadingDialog.dismiss()
loadingDialog?.dismiss()
})
}
@ -116,7 +142,7 @@ class AuthorizationActivity : ToolBarActivity() {
override fun onRestart() {
super.onRestart()
if (!CheckLoginUtils.isLogin()) {
finish()
finishAndRemoveTask()
} else {
initUserInfo()
initData()
@ -127,12 +153,12 @@ class AuthorizationActivity : ToolBarActivity() {
private fun checkParam() {
val uri = intent.data
if (uri == null) {
finish()
finishAndRemoveTask()
return
}
val host = uri.host
if (host != "authorize") {
finish()
finishAndRemoveTask()
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
@ -143,8 +169,9 @@ class AuthorizationActivity : ToolBarActivity() {
mContent = uri.getQueryParameter(EntranceConsts.KEY_CONTENT) ?: ""
gameId = uri.getQueryParameter(EntranceConsts.KEY_GAME_ID) ?: ""
gameName = uri.getQueryParameter(EntranceConsts.KEY_GAME_NAME) ?: ""
gameUid = uri.getQueryParameter(EntranceConsts.KEY_UID)?.toIntOrNull() ?: -1
if (mRemotePkgName == null) {
finish()
finishAndRemoveTask()
return
}
}
@ -152,8 +179,8 @@ class AuthorizationActivity : ToolBarActivity() {
private fun initView() {
//通过包名获取app图标和名称
val pkgName = mRemotePkgName ?: return
val icon = packageManager.getApplicationIcon(pkgName)
val name = packageManager.getApplicationLabel(packageManager.getApplicationInfo(pkgName, 0))
val icon = PackageUtils.getIconByPackageName(this, pkgName)
val name = PackageUtils.getNameByPackageName(this, pkgName)
mBinding.authorizeAppIcon.setImageDrawable(icon)
mBinding.authorizeAppName.text = name
mBinding.authorizeBtn.setOnClickListener {
@ -197,7 +224,7 @@ class AuthorizationActivity : ToolBarActivity() {
val remotePkgName = mRemotePkgName
if (remotePkgName == null) {
logAuthResult(false)
finish()
finishAndRemoveTask()
return
}
if (mToken.isEmpty()) {
@ -217,10 +244,45 @@ class AuthorizationActivity : ToolBarActivity() {
intent.putExtra(EntranceConsts.KEY_USER_ID, userId)
intent.putExtra(EntranceConsts.KEY_USER_NAME, username)
intent.putExtra(EntranceConsts.KEY_USER_AVATAR, userAvatar)
sendBroadcast(intent)
if (gameUid != -1 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
try {
sendBroadcastAsUser(intent, UserHandle.getUserHandleForUid(gameUid))
} catch (e: Exception) {
// 双开/分身游戏进行授权时,如果无 INTERACT_ACROSS_USERS 权限则使用Activity传递授权结果
authByActivity(intent)
return
}
} else {
sendBroadcast(intent)
}
logAuthResult(true)
backToLaunchApp()
finish()
finishAndRemoveTask()
}
private fun authByActivity(intent: Intent) {
intent.setClassName(mRemotePkgName!!, AUTHORIZATION_RESULT_ACTIVITY)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
HaloApp.getInstance().registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {
if (activity == this@AuthorizationActivity) {
HaloApp.getInstance().unregisterActivityLifecycleCallbacks(this)
finishAndRemoveTask()
}
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {
if (activity == this@AuthorizationActivity) {
HaloApp.getInstance().unregisterActivityLifecycleCallbacks(this)
}
}
})
startActivity(intent)
logAuthResult(true)
}
private fun logAuthResult(isSuccess: Boolean) {
@ -242,14 +304,14 @@ class AuthorizationActivity : ToolBarActivity() {
VHelper.launch(this, gamePkg, ignoreGApps = true, showLoading = showLoading)
return
}
val remotePkgName = this.mRemotePkgName
if (remotePkgName != null) {// 跳转回其他授权app
startActivity(packageManager.getLaunchIntentForPackage(remotePkgName))
}
// val remotePkgName = this.mRemotePkgName
// if (remotePkgName != null) {// 跳转回其他授权app
// startActivity(packageManager.getLaunchIntentForPackage(remotePkgName))
// }
}
override fun onBackPressed() {
super.onBackPressed()
finishAndRemoveTask()
backToLaunchApp(false)
@ -264,6 +326,7 @@ class AuthorizationActivity : ToolBarActivity() {
private const val BUTTON_TYPE_CONFIRM = "确定"
private const val BUTTON_TYPE_BACK = "返回"
private const val TYPE_PLUGIN = "plugin"
private const val AUTHORIZATION_RESULT_ACTIVITY = "com.gh.plugin.AuthorizationResultActivity"
}
}

View File

@ -132,6 +132,13 @@ class GamesCollectionAdapter(
)
mExposureEventArray?.put(position, exposureEvent)
val path = when (mViewModel.type) {
GamesCollectionFragment.TYPE_COLLECT -> "我的收藏-游戏单"
GamesCollectionFragment.TYPE_HISTORY -> "浏览记录-游戏单"
GamesCollectionFragment.TYPE_USER -> "个人主页-游戏单"
else -> ""
}
holder.binding.run {
ImageUtils.display(poster, itemEntity.cover)
nameTv.text = itemEntity.title
@ -249,12 +256,6 @@ class GamesCollectionAdapter(
}
userIcon.setOnClickListener {
val path = when (mViewModel.type) {
GamesCollectionFragment.TYPE_COLLECT -> "我的收藏-游戏单"
GamesCollectionFragment.TYPE_HISTORY -> "浏览记录-游戏单"
GamesCollectionFragment.TYPE_USER -> "个人主页-游戏单"
else -> ""
}
DirectUtils.directToHomeActivity(mContext, itemEntity.user?.id, "", path)
}
userName.setOnClickListener { userIcon.performClick() }
@ -266,7 +267,8 @@ class GamesCollectionAdapter(
mContext,
itemEntity.id,
isScrollToCommentArea = true,
exposureSourceList = ArrayList(exposureEvent.source)
exposureSourceList = ArrayList(exposureEvent.source),
entrance = path
)
)
}
@ -329,7 +331,8 @@ class GamesCollectionAdapter(
GameCollectionDetailActivity.getIntent(
mContext,
itemEntity.id,
exposureSourceList = ArrayList(exposureEvent.source)
exposureSourceList = ArrayList(exposureEvent.source),
entrance = path
)
)
} else {

View File

@ -12,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.gh.common.exposure.IExposable
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
import com.gh.common.util.PackageChangeHelper
import com.gh.common.util.PackageInstaller
import com.gh.common.util.PackageLauncher
import com.gh.download.DownloadManager
@ -398,6 +399,10 @@ class UpdatableGameAdapter(private var mViewModel: UpdatableGameViewModel) :
if (update.isLandPageAddressDialogShowOnly()) {
updateOrPluggable(updateBtn, update, downloadEntity, pluginDesc)
} else {
val packageName = update.packageName
if (packageName.isNotEmpty() == true) {
PackageChangeHelper.addInstallPendingPackage(packageName)
}
DirectUtils.directToExternalBrowser(it.context, update.landPageAddressDialog!!.link!!)
}
}

View File

@ -0,0 +1,16 @@
package com.gh.gamecenter.entity
import com.gh.gamecenter.feature.entity.SimpleGame
import com.google.gson.annotations.SerializedName
class GameServerTestTopGame(
@SerializedName("_id")
var id: String = "",
var game: SimpleGame? = null,
@SerializedName("column_test_v2_icon")
var icon: String = "",
@SerializedName("event_description")
var description: String = "",
@SerializedName("event_date")
var date: String = ""
)

View File

@ -18,7 +18,13 @@ data class SearchSubjectEntity(
@SerializedName("ad_icon_active")
val adIconActive: Boolean = false,
// 本地字段标记是否为微信小游戏CPM专题
var isWGameSubjectCPM: Boolean = false
var isWGameSubjectCPM: Boolean = false,
val type: String = ""
) : Parcelable {
companion object {
const val TYPE_WECHAT_GAME_CPM_COLUMN = "wechat_game_cpm_column"
}
fun getFilterGame() = RegionSettingHelper.filterGame(games)
}

View File

@ -288,7 +288,8 @@ class ForumContentSearchListFragment : LazyListFragment<AnswerEntity, ForumConte
mSearchKey,
SearchActivity.toTrackSearchType(mSearchType),
contentId ?: "",
title ?: ""
title ?: "",
sequence
)
NewFlatLogUtils.logSearchContentClick(

View File

@ -39,8 +39,8 @@ class ForumOrUserSearchDefaultFragment : SearchDefaultFragment() {
override fun initView() {
mBinding = FragmentSearchDefaultBinding.bind(mCachedView)
mBinding.hotTagHeadContainer.root.visibility = View.GONE
mBinding.hotTagFlexContainer.visibility = View.GONE
mBinding.hotAndDiscoveryTagHeadContainer.root.visibility = View.GONE
mBinding.hotAndDiscoveryTagFlexContainer.visibility = View.GONE
if (mEntrance == "论坛首页" || mEntrance == "搜索栏") {
mBinding.hotHeadContainer.headTitle.text = "热门论坛"
mViewModel.getForumSearchHotContent()

View File

@ -40,7 +40,8 @@ class UserSearchListFragment : LazyListFragment<FollowersOrFansEntity, UserSearc
mSearchKey,
SearchActivity.toTrackSearchType(mSearchType),
mListViewModel.sourceEntrance,
userId
userId,
position
)
NewFlatLogUtils.logSearchUserClick(
SearchType.fromString(mSearchType).toChinese(),

View File

@ -4,14 +4,18 @@ import android.os.Bundle
import android.view.View
import androidx.lifecycle.ViewModelProviders
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.baselist.LazyListFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.constant.EntranceConsts.KEY_SHOW_SUBJECT_TAB
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.json.json
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.observeNonNull
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.databinding.FragmentColumnCollectionDetailBinding
import com.gh.gamecenter.entity.GameColumnCollection
import com.gh.gamecenter.entity.SubjectData
import com.gh.gamecenter.subject.tab.SubjectTabFragment
@ -55,11 +59,37 @@ class ColumnCollectionDetailFragment : LazyListFragment<LinkEntity, ColumnCollec
mListViewModel.getGameColumnCollection()
mListViewModel.columnCollection.observeNonNull(this) {
setNavigationTitle(it.name)
mCachedView?.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
logPageShow(it)
}
}
private fun logPageShow(entity: GameColumnCollection) {
val tabIndex = arguments?.getInt(EntranceConsts.KEY_TAB_INDEX, -1) ?: -1
val tabName = arguments?.getString(EntranceConsts.KEY_TAB_NAME, "") ?: ""
val multiTabNavId = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, "") ?: ""
val multiTabNavName = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, "") ?: ""
val bottomTabName = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_NAME, "") ?: ""
mBaseHandler.postDelayed({
SensorsBridge.trackEvent("ColumnCollectionDetailPageShow", json {
"column_collection_name" to entity.name
"column_collection_id" to entity.id
"page_name" to GlobalActivityManager.getCurrentPageEntity().pageName
"page_id" to GlobalActivityManager.getCurrentPageEntity().pageId
"page_business_id" to GlobalActivityManager.getCurrentPageEntity().pageBusinessId
"last_page_name" to GlobalActivityManager.getLastPageEntity().pageName
"last_page_id" to GlobalActivityManager.getLastPageEntity().pageId
"last_page_business_id" to GlobalActivityManager.getLastPageEntity().pageBusinessId
"bottom_tab" to bottomTabName
"several_tab_page_name" to multiTabNavName
"several_tab_page_id" to multiTabNavId
"position" to tabIndex
"tab_content" to tabName
"source_entrance" to mEntrance
})
}, 3000L)
}
override fun onChanged(list: MutableList<LinkEntity>?) {
if (list != null && list.isNotEmpty()) {
showSubjectTab(list)

View File

@ -11,18 +11,22 @@ import com.gh.common.exposure.ExposureListener
import com.gh.common.exposure.IExposable
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.baselist.LazyListFragment
import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.json.json
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.common.view.FixGridLayoutManager
import com.gh.gamecenter.common.view.GridSpacingItemDecoration
import com.gh.gamecenter.common.view.VerticalItemDecoration
import com.gh.gamecenter.databinding.FragmentListBaseSkeletonBinding
import com.gh.gamecenter.entity.CommonCollectionEntity
import com.gh.gamecenter.home.custom.model.CustomPageItem
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMMON_CONTENT_COLLECTION_LAYOUT_HORIZONTAL_SLIDE_BANNER
@ -120,6 +124,8 @@ class CustomCommonCollectionDetailFragment : LazyListFragment<LinkEntity, Custom
}
mListRv?.removeItemDecorationAt(0)
mListRv?.addItemDecoration(itemDecoration)
logPageShow(it)
}
mListViewModel.loadExceptionLiveData.observe(viewLifecycleOwner) {
if (it != null && it.code() == 404) {
@ -154,6 +160,32 @@ class CustomCommonCollectionDetailFragment : LazyListFragment<LinkEntity, Custom
})
}
private fun logPageShow(entity: CommonCollectionEntity) {
val tabIndex = arguments?.getInt(EntranceConsts.KEY_TAB_INDEX, -1) ?: -1
val tabName = arguments?.getString(EntranceConsts.KEY_TAB_NAME, "") ?: ""
val multiTabNavId = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, "") ?: ""
val multiTabNavName = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, "") ?: ""
val bottomTabName = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_NAME, "") ?: ""
mBaseHandler.postDelayed({
SensorsBridge.trackEvent("LinkContentCollectionDetailPageShow", json {
"link_content_collection_name" to entity.name
"link_content_collection_id" to entity.id
"page_name" to GlobalActivityManager.getCurrentPageEntity().pageName
"page_id" to GlobalActivityManager.getCurrentPageEntity().pageId
"page_business_id" to GlobalActivityManager.getCurrentPageEntity().pageBusinessId
"last_page_name" to GlobalActivityManager.getLastPageEntity().pageName
"last_page_id" to GlobalActivityManager.getLastPageEntity().pageId
"last_page_business_id" to GlobalActivityManager.getLastPageEntity().pageBusinessId
"bottom_tab" to bottomTabName
"several_tab_page_name" to multiTabNavName
"several_tab_page_id" to multiTabNavId
"position" to tabIndex
"tab_content" to tabName
"source_entrance" to mEntrance
})
}, 3000L)
}
override fun getItemDecoration(): RecyclerView.ItemDecoration =
when (mCollectionStyle) {
"1-2" ->

View File

@ -49,21 +49,24 @@ class GameCollectionDetailActivity : ToolBarActivity() {
fun getIntent(
context: Context,
gameCollectionId: String,
isFromSquare: Boolean = false
isFromSquare: Boolean = false,
entrance: String = ""
): Intent {
return getIntent(context, gameCollectionId, "", isFromSquare, false)
return getIntent(context, gameCollectionId, "", isFromSquare, false, entrance = entrance)
}
@JvmStatic
fun getSpecifiedCommentIntent(
context: Context,
gameCollectionId: String,
topCommentId: String
topCommentId: String,
entrance: String
): Intent {
return getIntent(
context, gameCollectionId, topCommentId,
isFromSquare = false,
isScrollToCommentArea = true
isScrollToCommentArea = true,
entrance = entrance
)
}
@ -74,13 +77,15 @@ class GameCollectionDetailActivity : ToolBarActivity() {
topCommentId: String = "",
isFromSquare: Boolean = false,
isScrollToCommentArea: Boolean = false,
exposureSourceList: ArrayList<ExposureSource>? = null
exposureSourceList: ArrayList<ExposureSource>? = null,
entrance: String = ""
): Intent {
val bundle = Bundle()
bundle.putString(EntranceConsts.KEY_GAME_COLLECTION_ID, gameCollectionId)
bundle.putString(EntranceConsts.KEY_TOP_COMMENT_ID, topCommentId)
bundle.putBoolean(EntranceConsts.KEY_IS_FROM_SQUARE, isFromSquare)
bundle.putBoolean(EntranceConsts.KEY_SCROLL_TO_COMMENT_AREA, isScrollToCommentArea)
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance)
if (exposureSourceList != null) {
bundle.putParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST, exposureSourceList)
}

View File

@ -851,6 +851,7 @@ class GameCollectionDetailFragment :
trackEvent.put("game_collect_title", mGameCollectionTitle)
trackEvent.put("game_collect_id", mGameCollectionId)
trackEvent.put("stay_length", mElapsedHelper?.elapsedTime)
trackEvent.put("source_entrance", mEntrance)
} catch (e: JSONException) {
e.printStackTrace()
}

View File

@ -6,6 +6,7 @@ import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.exposure.ExposureListener
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.baselist.ListFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.exposure.ExposureSource
@ -58,6 +59,7 @@ class GameCollectionHotListFragment : ListFragment<GameCollectionListItemData, G
if (requireActivity() is GameCollectionListDetailActivity) {
mBasicExposureSourceList.add(ExposureSource("游戏单合集", mGameCollectionListEntity?.id ?: ""))
mBasicExposureSourceList.add(ExposureSource("合集详情", ""))
logPageShow()
} else {
mBasicExposureSourceList.add(ExposureSource("游戏单热榜", ""))
mBasicExposureSourceList.add(ExposureSource("游戏单合集", mGameCollectionListEntity?.id ?: ""))
@ -68,6 +70,32 @@ class GameCollectionHotListFragment : ListFragment<GameCollectionListItemData, G
}
}
private fun logPageShow() {
val tabIndex = arguments?.getInt(EntranceConsts.KEY_TAB_INDEX, -1) ?: -1
val tabName = arguments?.getString(EntranceConsts.KEY_TAB_NAME, "") ?: ""
val multiTabNavId = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, "") ?: ""
val multiTabNavName = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, "") ?: ""
val bottomTabName = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_NAME, "") ?: ""
mBaseHandler.postDelayed({
SensorsBridge.trackEvent("GameListCollectionDetailPageShow", json {
"game_list_collection_name" to mGameCollectionListEntity?.name
"game_list_collection_id" to mGameCollectionListEntity?.id
"page_name" to GlobalActivityManager.getCurrentPageEntity().pageName
"page_id" to GlobalActivityManager.getCurrentPageEntity().pageId
"page_business_id" to GlobalActivityManager.getCurrentPageEntity().pageBusinessId
"last_page_name" to GlobalActivityManager.getLastPageEntity().pageName
"last_page_id" to GlobalActivityManager.getLastPageEntity().pageId
"last_page_business_id" to GlobalActivityManager.getLastPageEntity().pageBusinessId
"bottom_tab" to bottomTabName
"several_tab_page_name" to multiTabNavName
"several_tab_page_id" to multiTabNavId
"position" to tabIndex
"tab_content" to tabName
"source_entrance" to mEntrance
})
}, 3000L)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
if (mListRefresh != null) {
mListRefresh!!.setColorSchemeResources(com.gh.gamecenter.common.R.color.primary_theme)

View File

@ -76,7 +76,8 @@ class MyGameCollectionViewHolder(
binding.root.context.startActivity(
GameCollectionDetailActivity.getIntent(
binding.root.context,
entity.id
entity.id,
entrance = path
)
)
} else {

View File

@ -596,7 +596,8 @@ class GameCollectionSquareAdapter(
context,
gamesCollectionEntity.id,
isFromSquare = true,
exposureSourceList = ArrayList(exposureSource)
exposureSourceList = ArrayList(exposureSource),
entrance = "游戏单广场"
)
)
}

View File

@ -209,7 +209,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (data == null || resultCode != Activity.RESULT_OK) return
if (data == null || resultCode != Activity.RESULT_OK || !::mViewModel.isInitialized) return
if (requestCode == REQUEST_SELECT_TAG) {
val tagInfoEntity = data.getParcelableExtra<TagInfoEntity>(GameCollectionTagSelectFragment.SELECTED_TAG)
val tagCategory = data.getStringExtra(GameCollectionTagSelectFragment.SELECTED_TAG_CATEGORY)

View File

@ -866,10 +866,11 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
showConcernIconAtBottomBarIfAvailable()
val downloadEntitySnapshot = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
val downloadEntitySnapshot = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
if (isSpecialDownloadDialogAvailable(downloadEntitySnapshot)
&& downloadEntitySnapshot != null) {
&& downloadEntitySnapshot != null
) {
updateSpecialDownloadDialogIcon(true)
}
@ -1855,19 +1856,10 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
)
} else {
if ("download" == mGameEntity?.reserveStatus) {
ReservationHelper.showDeleteReservationDialog(requireContext()) {
ReservationHelper.deleteReservation(mGameEntity!!) {
DetailDownloadUtils.updateViewHolder(detailViewHolder)
showReserveBtn(isShowReserveBtn())
}
}
} else {
ReservationHelper.showCancelReservationDialog(requireContext(), mGameEntity) {
ReservationHelper.cancelReservation(mGameEntity!!) {
DetailDownloadUtils.updateViewHolder(detailViewHolder)
showReserveBtn(isShowReserveBtn())
}
ReservationHelper.showCancelReservationDialog(requireContext(), mGameEntity) {
ReservationHelper.cancelReservation(mGameEntity!!) {
DetailDownloadUtils.updateViewHolder(detailViewHolder)
showReserveBtn(isShowReserveBtn())
}
}
}

View File

@ -983,14 +983,17 @@ class DescAdapter(
setExpandMaxLines(maxDesLines)
setIsExpanded(Int.MAX_VALUE == maxDesLines)
if (customColumn.isHtmlDes == true) {
val decoratedDesBrief = (customColumn.desBrief ?: "").dropFontColorInDarkMode(contentTv.context)
val decoratedDes = (customColumn.des ?: "").dropFontColorInDarkMode(contentTv.context)
shrankSpanned = HtmlCompat.fromHtml(
customColumn.desBrief ?: "",
decoratedDesBrief,
HtmlCompat.FROM_HTML_MODE_COMPACT,
PicassoImageGetter(contentTv),
ExtraTagHandler()
)
expandedSpanned = HtmlCompat.fromHtml(
customColumn.des ?: "",
decoratedDes,
HtmlCompat.FROM_HTML_MODE_COMPACT,
PicassoImageGetter(contentTv),
ExtraTagHandler()

View File

@ -6,11 +6,14 @@ import android.os.Bundle
import androidx.fragment.app.Fragment
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.BaseActivity_TabLayout
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.utils.updateStatusBarColor
import com.therouter.router.Route
/**
* 开服订阅
*/
@Route(
path = RouteConsts.activity.serversCalendarManagementActivity,
description = "开服订阅"
)
class ServersCalendarManagementActivity : BaseActivity_TabLayout() {
override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -25,10 +25,10 @@ import com.gh.gamecenter.common.utils.toPx
import com.gh.gamecenter.core.iinterface.IScrollable
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.SpanBuilder
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.RatingComment
import com.gh.gamecenter.eventbus.EBStar
import com.gh.gamecenter.eventbus.EBTypeChange
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.gamedetail.GameDetailFragment
import com.halo.assistant.HaloApp
import org.greenrobot.eventbus.EventBus
@ -60,7 +60,7 @@ class RatingFragment : LazyListFragment<RatingComment, RatingViewModel>(), IScro
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RATING_EDIT_REQUEST && resultCode == Activity.RESULT_OK) {
mListViewModel.initData()
mListViewModel?.initData()
} else if (
(requestCode == RATING_REPLAY_REQUEST || requestCode == RATING_PATCH_REQUEST)
&& resultCode == Activity.RESULT_OK

View File

@ -3,7 +3,11 @@ package com.gh.gamecenter.home.custom
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.RecyclerView
@ -54,6 +58,7 @@ import com.gh.gamecenter.feature.entity.PageLocation
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.ExposureType
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.feature.utils.SentryHelper
import com.gh.gamecenter.game.commoncollection.detail.CustomCommonCollectionDetailActivity
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
import com.gh.gamecenter.home.PageConfigure
@ -182,6 +187,22 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
viewModel.init(pageConfigure, searchToolbarTabWrapperViewModel, pageLocation)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = try {
FragmentCustomBinding.inflate(layoutInflater)
} catch (e: Exception) {
SentryHelper.onEvent(
"VIEW_BINDING_BIND_ERROR",
"digest", e.localizedMessage,
"gid", HaloApp.getInstance().gid
)
// 玄学,重试一次,该闪退闪退
FragmentCustomBinding.inflate(layoutInflater)
}
mCachedView = binding.root
return mCachedView
}
override fun getRealLayoutId() = R.layout.fragment_custom
override fun onFragmentFirstVisible() {
@ -218,7 +239,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
viewModel.loadFirst(false)
}
}
binding.reuseNoConnectionStub.inflate()
binding.reuseNoConnectionStub.inflateOrShow()
} else {
noConnectionBinding?.root?.visibility = View.VISIBLE
}
@ -228,7 +249,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
noDataBinding = ReuseNoneDataBinding.bind(inflated)
noDataBinding?.root?.visibility = View.VISIBLE
}
binding.reuseNoDataStub.inflate()
binding.reuseNoDataStub.inflateOrShow()
} else {
noDataBinding?.root?.visibility = View.VISIBLE
}
@ -278,9 +299,12 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
if (searchBarBinding == null) {
binding.reuseSearchBarStub.setOnInflateListener { _, inflated ->
searchBarBinding = LayoutSearchBarBinding.bind(inflated)
binding.gameRefresh.updateLayoutParams<RelativeLayout.LayoutParams> {
addRule(RelativeLayout.BELOW, R.id.reuseSearchBar)
}
initSearchBar(it)
}
binding.reuseSearchBarStub.inflate()
binding.reuseSearchBarStub.inflateOrShow()
} else {
initSearchBar(it)
}
@ -472,7 +496,8 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
pageLocation.tabPosition,
pageLocation.tabContent,
pageLocation.pageId,
pageLocation.pageName
pageLocation.pageName,
mEntrance
)
viewModel.loadData()
@ -491,8 +516,6 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
override fun initRealView() {
super.initRealView()
binding = FragmentCustomBinding.bind(mCachedView)
scrollCalculatorHelper = ScrollCalculatorHelper(binding.gameList, R.id.autoVideoView, 0, false)
buildPriorityChain()

View File

@ -93,7 +93,12 @@ class CustomPageViewModel(
private var searchToolbarTabWrapperViewModel: SearchToolbarTabWrapperViewModel? = null
private val subjectChangedMap: ArrayMap<String, List<GameEntity>> = ArrayMap()
private val subjectChangedMap: ArrayMap<SubjectChanged, List<GameEntity>> = ArrayMap()
/**
* 微信CPM专题当前的页码记录
*/
private val cpmSubjectChangedPageMap: ArrayMap<String, Int> = ArrayMap()
var slideDiscoveryGamesPage = -1
@ -358,9 +363,68 @@ class CustomPageViewModel(
}
}
override fun onChangeABatch(subjectEntity: SubjectEntity) {
override fun onChangeABatch(subjectEntity: SubjectEntity) =
if (subjectEntity.isWechatColumnCPM) {
onChangeWGameCPMABatch(subjectEntity)
} else {
onChangeNormalGameABatch(subjectEntity)
}
/**
* 微信小游戏CPM的“换一批”功能实现
*
* @see <a href="https://jira.shanqu.cc/browse/GHZSCY-7167">【光环助手】CPM微信小游戏“换一批”功能优化</a>
*/
private fun onChangeWGameCPMABatch(subjectEntity: SubjectEntity) {
val subjectId = subjectEntity.id ?: return
val gameList = subjectChangedMap[subjectId]
val page = cpmSubjectChangedPageMap[subjectId] ?: let {
// 第一次点击“换一批”时,先缓存第一页的数据
subjectChangedMap[SubjectChanged(subjectId, 1)] = subjectEntity.data
2
}
val subjectChanged = SubjectChanged(subjectId, page)
val gameList = subjectChangedMap[subjectChanged]
if (gameList != null) {// 直接读取缓存数据
notifyWGameCPMABatchChanged(gameList, subjectId, page)
} else {
repository.loadChangeSubjectWGameCPM(page)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<List<GameEntity>>() {
override fun onResponse(response: List<GameEntity>?) {
if (response != null) {
subjectChangedMap[subjectChanged] = response
notifyWGameCPMABatchChanged(response, subjectId, page)
}
}
override fun onFailure(e: HttpException?) {
Utils.toast(getApplication(), "网络异常")
}
})
}
}
private fun notifyWGameCPMABatchChanged(gameList: List<GameEntity>, subjectId: String, page: Int) {
val nextPage: Int
val cpmGameList = if(gameList.isEmpty()) {
nextPage = 1// 已经到最后一页了,下一页是第一页
subjectChangedMap[SubjectChanged(subjectId, 1)]!!
} else {
nextPage = page + 1
gameList
}
cpmSubjectChangedPageMap[subjectId] = nextPage// 加载下一页数据
changeSubjectCustomPageItem(subjectId, ArrayList(cpmGameList))
}
/**
* 光环游戏的“换一批”功能实现
*/
private fun onChangeNormalGameABatch(subjectEntity: SubjectEntity) {
val subjectId = subjectEntity.id ?: return
val subjectChanged = SubjectChanged(subjectId, 2)
val gameList = subjectChangedMap[subjectChanged]
if (gameList != null) {
changeSubjectCustomPageItem(subjectId, getRandomGameList(subjectEntity.data, ArrayList(gameList)))
} else {
@ -370,7 +434,7 @@ class CustomPageViewModel(
.subscribe(object : Response<List<GameEntity>>() {
override fun onResponse(response: List<GameEntity>?) {
if (response != null) {
subjectChangedMap[subjectId] = response
subjectChangedMap[subjectChanged] = response
onChangeABatch(subjectEntity)
}
}
@ -760,5 +824,26 @@ class CustomPageViewModel(
repository.onClear()
}
class SubjectChanged(
val subjectId: String,
val page: Int
) {
companion object {
private const val HASH = 30
}
override fun hashCode(): Int {
return subjectId.hashCode() + page.hashCode() + HASH
}
override fun equals(other: Any?): Boolean {
if (other !is SubjectChanged) {
return false
}
return other.subjectId == subjectId
&& other.page == page
}
}
}

View File

@ -6,6 +6,8 @@ import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toBinding
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.toDrawable
import com.gh.gamecenter.databinding.RecyclerContentLabelLaneItemBinding
import com.gh.gamecenter.home.custom.model.CustomPageData
@ -28,6 +30,10 @@ class ContentLabelLaneAdapter(
override fun onBindViewHolder(holder: ContentLabelChildViewHolder, position: Int) {
val item = getItem(position)
with(holder.binding) {
vBackground.background = R.drawable.bg_shape_content_label_lane_item.toDrawable(context)
tvTitle.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
tvSubTitle.setTextColor(com.gh.gamecenter.common.R.color.primary_theme.toColor(context))
ivIcon.goneIf(item.image.isBlank()){
ivIcon.displayGameIcon(item.image, null, null)
}

View File

@ -805,11 +805,13 @@ class CustomPageRepository private constructor(
}
fun loadChangeSubjectGame(subjectEntity: SubjectEntity): Observable<List<GameEntity>> =
if (subjectEntity.isWechatColumnCPM) {// 微信小游戏CPM专题的“换一批”接口
wGameSubjectCPMRemoteDataSource.getRecommendCPMList(2, 10).toObservable()
} else {
remoteDataSource.loadChangeSubjectGame(subjectEntity)
}
remoteDataSource.loadChangeSubjectGame(subjectEntity)
.map(RegionSettingHelper.filterGame)
.map(ApkActiveUtils.filterMapperList)
fun loadChangeSubjectWGameCPM(page: Int): Observable<MutableList<GameEntity>> =
wGameSubjectCPMRemoteDataSource.getEditorRecommendCPMList(page, 10)// 微信小游戏CPM专题的“换一批”接口
.toObservable()
.map(RegionSettingHelper.filterGame)
.map(ApkActiveUtils.filterMapperList)

View File

@ -65,7 +65,7 @@ class SubjectTracker(private val pageLocation: PageLocation) {
pageLocation.pageName,
subject?.id ?: "",
subject?.name ?: "",
"最近在玩",
"自定义页面",
item.componentStyle,
"",
)

View File

@ -40,7 +40,7 @@ class CustomGameGallerySlideViewHolder(
override fun bindView(item: CustomPageItem) {
super.bindView(item)
if (item is CustomSubjectItem) {
binding.cardView.setCardBackgroundColor(com.gh.gamecenter.common.R.color.ui_container_1.toColor(binding.root.context))
if (item.data == cachedSubject) return
cachedSubject = item.data
@ -77,7 +77,6 @@ class CustomGameGallerySlideViewHolder(
val gameList = item.data.data ?: emptyList()
(recyclerView.adapter as? GameGallerySlideAdapter)?.submitList(gameList)
}
binding.cardView.setCardBackgroundColor(com.gh.gamecenter.common.R.color.text_FAFAFA.toColor(binding.root.context))
}

View File

@ -192,9 +192,6 @@ class CustomGameItemViewHolder(
adLabelTv: TextView? = null,
canShowSubTitle: Boolean
) {
if (entity.id == gameSubtitleTv.getTag(com.gh.gamecenter.common.R.string.tag_game_name_id)) return
gameSubtitleTv.setTag(com.gh.gamecenter.common.R.string.tag_game_name_id, entity.id)
var showSubtitle = false
var showAdvancedDownload = false
if (canShowSubTitle && entity.serverLabel == null && entity.subtitle.isNotEmpty() && !entity.advanceDownload) {
@ -214,6 +211,9 @@ class CustomGameItemViewHolder(
setColor("#${entity.subtitleStyle?.background}".hexStringToIntColor())
}
}
} else {
setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
background = R.drawable.bg_advance_download_game_subtitle.toDrawable(context)
}
}
}
@ -226,6 +226,10 @@ class CustomGameItemViewHolder(
background = R.drawable.bg_advance_download_game_subtitle.toDrawable(context)
}
}
if (entity.id == gameSubtitleTv.getTag(com.gh.gamecenter.common.R.string.tag_game_name_id)) return
gameSubtitleTv.setTag(com.gh.gamecenter.common.R.string.tag_game_name_id, entity.id)
if (showSubtitle || showAdvancedDownload) {
val minWidth =
if (showSubtitle) SUBTITLE_MIN_WIDTH.dip2px() else if (showAdvancedDownload) ADVANCED_DOWNLOAD_WIDTH.dip2px() else 0

View File

@ -53,6 +53,7 @@ class CustomHomeSlideListItemViewHolder(val binding: HomeSlideListItemCustomBind
ImageUtils.displayWithCallback(
binding.slideBackground,
homeSlide.image,
false,
object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
binding.bottomGradient.visibility = View.VISIBLE

View File

@ -67,6 +67,7 @@ class CustomHomeSubSlideListItemViewHolder(val binding: HomeSubSlideListItemCust
ImageUtils.displayWithCallback(
binding.slideBackground,
homeSlide.image,
false,
object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
if (homeSlide.placeholderColor.isNotEmpty() && homeSlide.linkGame != null) {

View File

@ -62,7 +62,11 @@ class HomeGameTestV2GameListViewHolder(
)
//开服日期
val gameTimeText = getGameTimeText(gameEntity)
val gameTimeText = if (gameEntity.openTest?.startPending == true) {
gameEntity.openTest?.startText ?: ""
} else {
getGameTimeText(gameEntity)
}
gameDes.text = gameTimeText
gameDes.isVisible = gameTimeText.isNotEmpty()

View File

@ -41,6 +41,8 @@ class AutomaticVideoView @JvmOverloads constructor(context: Context, attrs: Attr
var thumbImage: SimpleDraweeView = findViewById(R.id.thumbImage)
var containerView: RadiusCardView = findViewById(R.id.container)
var detailBtn: TextView? = null
var isMute = true
private var mIsFirstPlay = true
private var mMuteDisposable: Disposable? = null
private var mMaskDisposable: Disposable? = null
private val mUUID = UUID.randomUUID().toString()
@ -89,10 +91,11 @@ class AutomaticVideoView @JvmOverloads constructor(context: Context, attrs: Attr
mVideoAllCallBack.onClickStartThumb(mOriginUrl, mTitle, this)
}
prepareVideo()
val topVideoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
if (topVideoVoiceStatus) {
violenceUpdateMuteStatus()
if (mIsFirstPlay) {
isMute = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
mIsFirstPlay = false
}
violenceUpdateMuteStatus()
resetDetailMask()
}
@ -106,15 +109,21 @@ class AutomaticVideoView @JvmOverloads constructor(context: Context, attrs: Attr
mMuteDisposable?.dispose()
mMuteDisposable = null
}
mute()
if (isMute) {
mute()
} else {
unMute()
}
}
}
fun mute() {
isMute = true
CustomManager.getCustomManager(getKey()).isNeedMute = true
}
fun unMute() {
isMute = false
CustomManager.getCustomManager(getKey()).isNeedMute = false
}

View File

@ -1,93 +0,0 @@
package com.gh.gamecenter.install
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
import com.lightgame.download.ForegroundNotificationManager
import com.lightgame.utils.Utils
import java.util.*
class InstallService : Service() {
private var mForegroundTimer: Timer? = null
private var mForegroundNotificationManager: ForegroundNotificationManager? = null
override fun onCreate() {
super.onCreate()
mForegroundNotificationManager = ForegroundNotificationManager(this, this.application)
Utils.log(InstallService::class.java.simpleName, "onCreate")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Utils.log(InstallService::class.java.simpleName, "onStartCommand")
val notificationId = 9999
if (intent != null && intent.extras != null) {
val serviceAction = intent.getStringExtra(KEY_SERVICE_ACTION)
if (START_FOREGROUND == serviceAction) {
startForegroundIfNeeded(notificationId)
} else if (STOP_FOREGROUND == serviceAction) {
startForegroundIfNeeded(notificationId)
stopForegroundIfNeeded(notificationId)
}
} else {
startForegroundIfNeeded(notificationId)
stopForegroundIfNeeded(notificationId)
}
// 不需要 intent 为空的重建
return START_NOT_STICKY
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
private fun startForegroundIfNeeded(notificationId: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel =
NotificationChannel(SERVICE_CHANNEL_ID, SERVICE_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
val manager = applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)
val notification: Notification = NotificationCompat.Builder(this, SERVICE_CHANNEL_ID)
.setSmallIcon(com.lightgame.R.drawable.ic_download_notification)
.setContentTitle("光环助手安装服务")
.build()
mForegroundNotificationManager?.notify(notificationId, notification)
mForegroundTimer?.cancel()
mForegroundTimer = Timer()
val task: TimerTask = object : TimerTask() {
override fun run() {
stopForegroundIfNeeded(notificationId)
}
}
mForegroundTimer?.schedule(task, FOREGROUND_COUNT_DOWN_TIME)
}
}
private fun stopForegroundIfNeeded(notificationId: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mForegroundNotificationManager?.cancel(notificationId)
mForegroundTimer?.cancel()
mForegroundTimer = null
}
}
companion object {
private const val SERVICE_CHANNEL_ID = "安装服务"
private const val FOREGROUND_COUNT_DOWN_TIME = 20 * 1000L
const val START_FOREGROUND = "start_foreground"
const val STOP_FOREGROUND = "stop_foreground"
const val KEY_SERVICE_ACTION = "service_action"
}
}

View File

@ -59,7 +59,7 @@ class MiniGameSearchDefaultRankAdapter(
_id = rank.id,
mName = rank.name,
miniGameAppId = rank.link.link ?: "",
miniGameType = Constants.WECHAT_MINI_GAME,
miniGameCategory = Constants.WECHAT_MINI_GAME,
usage = rank.usage ?: 0
)
holder.binding.playCount.visibility = View.VISIBLE

View File

@ -21,11 +21,15 @@ class MiniGameSearchResultRepository(
return api.getSearchMiniGameList(key, page, 20)
}
override fun getSearchMiniGameCPM(key: String?): Observable<List<GameEntity>> {
return Observable.just(emptyList())
}
override fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>> {
return Observable.just(emptyList())
}
override fun getWGameCPMGameList(): Single<MutableList<GameEntity>> {
return mWGameSubjectCPMDataSource.getRecommendCPMList(1)
return mWGameSubjectCPMDataSource.getUserRecommendCPMList()
}
}

View File

@ -11,7 +11,7 @@ class WGameSubjectCPMListRepository(
) : ISubjectListRepository {
override fun getColumn(column_id: String?, page: Int, sort: String?, order: String?): Single<MutableList<GameEntity>> {
return dataSource.getRecommendCPMList(page)
return dataSource.getEditorRecommendCPMList(page)
}
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {

View File

@ -14,7 +14,51 @@ class WGameSubjectCPMRemoteDataSource(
private val api: WGameCPMApiService = RetrofitManager.getInstance().wGameCPMApi
) {
fun getRecommendCPMList(page: Int, pageSize: Int = 10): Single<MutableList<GameEntity>> {
fun getEditorRecommendCPMList(page: Int, pageSize: Int = 10): Single<MutableList<GameEntity>> {
val meta = MetaUtil.getMeta()
val request = mapOf(
"head" to mapOf(
"busiAppid" to Config.WGAME_CPM_BUSIAPPID,
"oaid" to (meta.oaid ?: ""),
"manufacturer" to (meta.manufacturer ?: ""),
"mode" to (meta.model ?: ""),
"androidId" to (MetaUtil.getAndroidId()),
"imei" to (MetaUtil.getIMEI())
),
"body" to mapOf(
"page" to page - 1,
"pageSize" to pageSize,
)
)
return api.getEditorRecommendList(request.toRequestBody())
.map {
if (it.ret == 0) {
it.appInfoList.map { info ->
GameEntity(
mName = info.appName,
mIcon = info.logo,
mBrief = info.briefIntro,
miniGameUid = info.appID,
miniGameAppId = info.userName,
miniGameCategory = Constants.WECHAT_MINI_GAME,
profit = Constants.WECHAT_MINI_GAME_PROFIT_CPM,
miniGameAppStatus = 2,
miniGameAppPath = info.wechatAppPath,
miniGameExtData = info.extData,
miniGameRecommendId = info.recommendID,
mTagStyle = arrayListOf(
TagStyleEntity(name = info.categoryName),
TagStyleEntity(name = info.subcategoryName)
)
)
}.toMutableList()
} else {
mutableListOf()
}
}
}
fun getUserRecommendCPMList(page: Int = 1, pageSize: Int = 10): Single<MutableList<GameEntity>> {
val meta = MetaUtil.getMeta()
val request = mapOf(
"head" to mapOf(
@ -40,7 +84,8 @@ class WGameSubjectCPMRemoteDataSource(
mBrief = info.briefIntro,
miniGameUid = info.appID,
miniGameAppId = info.userName,
miniGameType = Constants.WECHAT_MINI_GAME_CPM,
miniGameCategory = Constants.WECHAT_MINI_GAME,
profit = Constants.WECHAT_MINI_GAME_PROFIT_CPM,
miniGameAppStatus = 2,
miniGameAppPath = info.wechatAppPath,
miniGameExtData = info.extData,

View File

@ -19,6 +19,7 @@ import com.gh.gamecenter.common.base.activity.BaseActivity_TabLayout.PAGE_INDEX
import com.gh.gamecenter.common.base.adapter.FragmentAdapter
import com.gh.gamecenter.common.base.fragment.BaseFragment_TabLayout
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.BugFixedPopupWindow
import com.gh.gamecenter.common.view.TabIndicatorView
@ -28,10 +29,12 @@ import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.databinding.PopupMyGameGuideBinding
import com.gh.gamecenter.gamecollection.publish.GameCollectionEditActivity
import com.google.android.material.tabs.TabLayout
import com.therouter.router.Route
/**
* 我的游戏
*/
@Route(
path = RouteConsts.activity.myGameActivity,
description = "我的游戏"
)
class MyGameActivity : BaseActivity() {
private val viewModel by viewModels<MyGameActivityViewModel>()

View File

@ -35,17 +35,21 @@ class PackageFilterManager {
if (appendOnly) {
// 添加因为异常而没能正常更新的包名列表
finalPackageList.addAll(PackageRepository.mPendingPackageNameSet)
synchronized(PackageRepository.mPendingPackageNameSet) {
finalPackageList.addAll(PackageRepository.mPendingPackageNameSet)
}
}
RetrofitManager.getInstance()
.newApi
.postInstalledAppList(packageList.toRequestBody())
.postInstalledAppList(finalPackageList.toRequestBody())
.subscribeOn(Schedulers.io())
.subscribe(object : BiResponse<PackageFilter>() {
override fun onSuccess(data: PackageFilter) {
mPackageKey = data.key
PackageRepository.mPendingPackageNameSet.clear()
synchronized(PackageRepository.mPendingPackageNameSet) {
PackageRepository.mPendingPackageNameSet.removeAll(finalPackageList)
}
val partialPackageList = arrayListOf<String>()
@ -78,7 +82,9 @@ class PackageFilterManager {
super.onFailure(exception)
if (appendOnly) {
PackageRepository.mPendingPackageNameSet.addAll(packageList)
synchronized(PackageRepository.mPendingPackageNameSet) {
PackageRepository.mPendingPackageNameSet.addAll(finalPackageList)
}
} else {
if (exception is retrofit2.HttpException && exception.code() == 403) {
// 403 代表 key 过期,需要重新获取

View File

@ -85,7 +85,7 @@ object PackageRepository {
_recentVaPlayedChanged.postValue(Unit)
}
val packageFilterManager = PackageFilterManager()
var mPendingPackageNameSet = hashSetOf<String>() // 因遇到异常而等待下次操作更新的包名列表
var mPendingPackageNameSet = Collections.synchronizedSet<String>(hashSetOf<String>()) // 因遇到异常而等待下次操作更新的包名列表
var mValidPackageNameSet = hashSetOf<String>() // 已被收录的游戏包名列表

View File

@ -3,13 +3,16 @@ package com.gh.gamecenter.personal
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.utils.updateStatusBarColor
import com.therouter.router.Route
/**
* 收货信息
*/
@Route(
path = RouteConsts.activity.deliveryInfoActivity,
description = "收货信息"
)
class DeliveryInfoActivity : ToolBarActivity() {
override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -217,7 +217,7 @@ class HaloPersonalBannerAdapter(context: Context) : BaseRecyclerAdapter<Recycler
}
"开服管理" -> {// 开服管理
DirectUtils.directToServersCalendarManagement(mContext, "我的光环-活动位")
DirectUtils.directToServersCalendarManagement("我的光环-活动位")
}
else -> {

View File

@ -701,7 +701,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
}
private fun inflateRealView() {
mBinding.stub.inflate()
mBinding.stub.inflateOrShow()
mStubBinding.statusBar.goneIf(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
mStubBinding.darkModeIv.goneIf(!(Config.getNightModeSetting()?.icon ?: false))

View File

@ -209,7 +209,7 @@ class HaloPersonalFunctionAdapter(context: Context) : BaseRecyclerAdapter<Recycl
}
"开服管理" -> {// 开服管理
DirectUtils.directToServersCalendarManagement(mContext, "我的光环-更多功能")
DirectUtils.directToServersCalendarManagement("我的光环-更多功能")
}
else -> {

View File

@ -243,7 +243,7 @@ class HaloPersonalRecommendAdapter(val context: Context) : BaseRecyclerAdapter<R
}
"开服管理" -> {// 开服管理
DirectUtils.directToServersCalendarManagement(mContext, "我的光环-推荐位")
DirectUtils.directToServersCalendarManagement("我的光环-推荐位")
}
else -> {

View File

@ -3,6 +3,7 @@ package com.gh.gamecenter.provider
import android.content.*
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteException
import android.database.sqlite.SQLiteFullException
import android.database.sqlite.SQLiteOpenHelper
import android.net.Uri
@ -12,6 +13,7 @@ import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.login.entity.UserInfoEntity
import com.gh.gamecenter.login.user.UserRepository
import com.halo.assistant.HaloApp
@ -77,7 +79,12 @@ class GhContentProvider : ContentProvider() {
}
override fun onCreate(): Boolean {
initProviderSqliteHelper(context);
try {
val context = context ?: return false
initProviderSqliteHelper(context)
} catch (e: SQLiteException) {
ToastUtils.toast("数据库内存已满,无法同步")
}
return true
}

View File

@ -76,7 +76,8 @@ class ChooseForumContainerFragment : LazyListFragment<ForumEntity, ChooseForumCo
SearchActivity.toTrackSearchType(mSearchType),
forumEntity.id,
HtmlUtils.stripHtml(forumEntity.name),
forumEntity.typeChinese
forumEntity.typeChinese,
position
)
}
) { enity, position ->

View File

@ -12,15 +12,13 @@ import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.widget.TextViewCompat
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.common.base.fragment.BaseDraggableDialogFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.NormalShareEntity
import com.gh.gamecenter.common.eventbus.EBShare
import com.gh.gamecenter.common.utils.ShareUtils
import com.gh.gamecenter.common.utils.debounceActionWithInterval
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.setDrawableTop
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.databinding.DialogGameDetailMoreBinding
import com.gh.gamecenter.entity.MenuItemEntity
import org.greenrobot.eventbus.EventBus
@ -32,6 +30,7 @@ class MoreFunctionPanelDialog : BaseDraggableDialogFragment() {
private var mTitle: String = ""
private var mParentTag: String = ""
private var mStatus: String = ""
private var titleStyle: Int = MORE_DIALOG_TITLE_STYLE_CENTER_BOLD
private var mShareEntity: NormalShareEntity? = null
private var mShareUtils: ShareUtils? = null
@ -43,6 +42,7 @@ class MoreFunctionPanelDialog : BaseDraggableDialogFragment() {
mStatus = getString(KEY_STATUS) ?: ""
mShareEntity = getParcelable(KEY_SHARE)
mParentTag = getString(EntranceConsts.KEY_PARENT_TAG) ?: ""
titleStyle = getInt(KEY_TITLE_STYLE)
}
mShareUtils = getShareUtils()
}
@ -59,11 +59,30 @@ class MoreFunctionPanelDialog : BaseDraggableDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.gameNameTv.text = mTitle
binding.gameNameTv.gravity = Gravity.CENTER
binding.gameIconView.visibility = View.GONE
binding.feedbackTv.visibility = View.GONE
binding.copyrightTv.visibility = View.GONE
when (titleStyle) {
MORE_DIALOG_TITLE_STYLE_CENTER_BOLD -> {
TextViewCompat.setTextAppearance(binding.gameNameTv, com.gh.gamecenter.common.R.style.TextBody2B)
binding.gameNameTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext()))
binding.gameNameTv.gravity = Gravity.CENTER
}
MORE_DIALOG_TITLE_STYLE_LEFT_BOLD -> {
TextViewCompat.setTextAppearance(binding.gameNameTv, com.gh.gamecenter.common.R.style.TextBody2B)
binding.gameNameTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext()))
binding.gameNameTv.gravity = Gravity.START
}
MORE_DIALOG_TITLE_STYLE_CENTER_NORMAL -> {
TextViewCompat.setTextAppearance(binding.gameNameTv, com.gh.gamecenter.common.R.style.TextBody2)
binding.gameNameTv.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
binding.gameNameTv.gravity = Gravity.CENTER
}
}
binding.shareWechatTv.setOnClickListener {
debounceActionWithInterval(it.id, 2000) {
if (checkStatusIsPass()) {
@ -142,10 +161,12 @@ class MoreFunctionPanelDialog : BaseDraggableDialogFragment() {
toast("内容审核中,不支持分享")
false
}
"fail" -> {
toast("内容审核不通过,不支持分享")
false
}
else -> true
}
}
@ -227,8 +248,13 @@ class MoreFunctionPanelDialog : BaseDraggableDialogFragment() {
const val KEY_TITLE = "title"
const val KEY_SHARE = "share"
const val KEY_STATUS = "status"
const val KEY_TITLE_STYLE = "title_style"
const val REQUEST_CODE = 1101
const val MORE_DIALOG_TITLE_STYLE_CENTER_BOLD = 0 // 居中-加粗
const val MORE_DIALOG_TITLE_STYLE_LEFT_BOLD = 1 // 左对齐-加粗
const val MORE_DIALOG_TITLE_STYLE_CENTER_NORMAL = 2 // 居中
@JvmStatic
fun showMoreDialog(
activity: AppCompatActivity,
@ -236,7 +262,8 @@ class MoreFunctionPanelDialog : BaseDraggableDialogFragment() {
title: String,
share: NormalShareEntity,
status: String,
parentTag: String
parentTag: String,
titleStyle: Int = MORE_DIALOG_TITLE_STYLE_CENTER_BOLD
) {
MoreFunctionPanelDialog().apply {
arguments = Bundle().apply {
@ -245,6 +272,7 @@ class MoreFunctionPanelDialog : BaseDraggableDialogFragment() {
putParcelable(KEY_SHARE, share)
putString(KEY_STATUS, status)
putString(EntranceConsts.KEY_PARENT_TAG, parentTag)
putInt(KEY_TITLE_STYLE, titleStyle)
}
}.show(
activity.supportFragmentManager,

View File

@ -1,16 +1,15 @@
package com.gh.gamecenter.qa.editor
import android.content.Context
import android.webkit.JavascriptInterface
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.core.AppExecutor
import com.gh.common.util.*
import com.gh.common.util.DirectUtils
import com.gh.common.view.RichEditor
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.entity.CommunityEntity
import com.gh.gamecenter.common.utils.clickToastByStatus
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
import com.gh.gamecenter.common.entity.CommunityEntity
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.entity.MyVideoEntity
import com.gh.gamecenter.gamecollection.detail.GameCollectionDetailActivity
import com.gh.gamecenter.qa.answer.detail.SimpleAnswerDetailActivity
@ -61,7 +60,7 @@ class OnLinkClickListener(
)
}
"game_collection" -> {
context.startActivity(GameCollectionDetailActivity.getIntent(context, insertEntity.id ?: ""))
context.startActivity(GameCollectionDetailActivity.getIntent(context, insertEntity.id ?: "", entrance = entrance))
}
"video" -> {
DirectUtils.directToVideoDetail(context, insertEntity.id ?: "", entrance, "$path-链接")

View File

@ -19,7 +19,6 @@ import com.gh.gamecenter.core.utils.SPUtils;
import com.gh.gamecenter.entity.NewApiSettingsEntity;
import com.gh.gamecenter.eventbus.EBPackage;
import com.gh.gamecenter.feature.entity.GameInstall;
import com.gh.gamecenter.install.InstallService;
import com.gh.gamecenter.manager.PackagesManager;
import com.halo.assistant.HaloApp;
import com.lightgame.download.DownloadEntity;
@ -27,8 +26,6 @@ import com.lightgame.utils.Utils;
import org.greenrobot.eventbus.EventBus;
import java.util.Locale;
/**
* 监听安装包变更
*/
@ -49,14 +46,6 @@ public class PackageChangeBroadcastReceiver extends BroadcastReceiver {
PackageHelper.INSTANCE.dumpInstalledListCache();
ExtensionsKt.doOnMainProcessOnly(() -> {
Utils.log(TAG, "onReceive->" + intent.getAction() + "==" + intent.getDataString());
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU
&& Build.MANUFACTURER.toLowerCase(Locale.CHINA).contains("xiaomi")) {
Intent foregroundServiceIntent = new Intent(context, InstallService.class);
foregroundServiceIntent.putExtra(InstallService.KEY_SERVICE_ACTION, InstallService.STOP_FOREGROUND);
context.startForegroundService(foregroundServiceIntent);
}
// 接收安装广播
if (intent.getAction().equals(mActions.getAdd())) {
String packageName = intent.getDataString();

View File

@ -48,6 +48,7 @@ import com.gh.gamecenter.entity.GameColumnCollection;
import com.gh.gamecenter.entity.GameData;
import com.gh.gamecenter.entity.GameDigestEntity;
import com.gh.gamecenter.entity.GameGuidePopupEntity;
import com.gh.gamecenter.entity.GameServerTestTopGame;
import com.gh.gamecenter.entity.GameServerTestV2Entity;
import com.gh.gamecenter.entity.GameVideoInfo;
import com.gh.gamecenter.entity.GamesCollectionDetailEntity;
@ -84,7 +85,6 @@ import com.gh.gamecenter.entity.SignEntity;
import com.gh.gamecenter.entity.SpecialCatalogEntity;
import com.gh.gamecenter.entity.StartPointEntity;
import com.gh.gamecenter.entity.SubjectEntity;
import com.gh.gamecenter.entity.SubjectRecommendEntity;
import com.gh.gamecenter.entity.SubjectRefreshEntity;
import com.gh.gamecenter.entity.SubjectSettingEntity;
import com.gh.gamecenter.entity.TagEntity;
@ -146,7 +146,6 @@ import com.gh.gamecenter.qa.entity.QuestionsIndexEntity;
import com.gh.gamecenter.qa.entity.TopCommunityCategory;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.protobuf.Any;
import java.util.ArrayList;
import java.util.HashMap;
@ -318,6 +317,12 @@ public interface ApiService {
@GET
Observable<List<GameEntity>> getSearchGame(@Url String url);
/**
* 搜索CPM微信小游戏
*/
@GET("mini_game/search/configs")
Observable<List<GameEntity>> getSearchWechatMiniCPMGame(@Query("keyword") String key);
/**
* 游戏搜索的专题数据
*/
@ -3425,4 +3430,9 @@ public interface ApiService {
@GET("game_lists/search")
Single<List<CustomPageData.LinkColumnCollection.CustomSubjectEntity>> searchGameList(@Query("keyword") String keyword, @Query("page") int page);
/**
* 新游开测-置顶游戏
*/
@GET("app/column_test_v2/{link_id}/top_games")
Observable<List<GameServerTestTopGame>> getServerTestV2TopGames(@Path("link_id") String linkId);
}

View File

@ -7,12 +7,15 @@ import android.view.View
import androidx.fragment.app.Fragment
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.common.base.activity.BaseActivity_TabLayout
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.updateStatusBarColor
import com.therouter.router.Route
/**
* 游戏存档
*/
@Route(
path = RouteConsts.activity.gameArchiveListActivity,
description = "游戏存档"
)
class GameArchiveListActivity : BaseActivity_TabLayout() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

View File

@ -8,6 +8,8 @@ import io.reactivex.Single
interface ISearchGameResultRepository {
fun getSearchGame(key: String?, page: Int): Observable<List<GameEntity>>
fun getSearchMiniGameCPM(key: String?): Observable<List<GameEntity>>
fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>>
fun getWGameCPMGameList(): Single<MutableList<GameEntity>>

View File

@ -1,10 +1,9 @@
package com.gh.gamecenter.search
import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Shader
import android.graphics.Typeface
import android.graphics.*
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.RoundRectShape
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
@ -14,6 +13,7 @@ import android.widget.CheckedTextView
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.viewpager.widget.PagerAdapter
import com.gh.common.constant.Config
import com.gh.common.exposure.ExposureManager
@ -22,6 +22,7 @@ import com.gh.common.util.DirectUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.SearchType
import com.gh.gamecenter.common.base.fragment.BaseFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.exposure.ExposureSource
@ -35,6 +36,7 @@ import com.gh.gamecenter.databinding.TabItemSearchDefaultRankBinding
import com.gh.gamecenter.db.ISearchHistoryDao
import com.gh.gamecenter.db.SearchHistoryDao
import com.gh.gamecenter.eventbus.EBSearch
import com.gh.gamecenter.feature.entity.DiscoveryTagEntity
import com.gh.gamecenter.feature.entity.HotTagEntity
import com.gh.gamecenter.feature.entity.SettingsEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
@ -48,6 +50,7 @@ import org.json.JSONObject
open class SearchDefaultFragment : BaseFragment<Any>() {
private var mHotTagList: List<HotTagEntity>? = null
private var mDiscoveryTagList: List<DiscoveryTagEntity>? = null
protected var mRankList: List<SettingsEntity.Search.RankList>? = null
protected lateinit var mBinding: FragmentSearchDefaultBinding
@ -64,10 +67,11 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
// FlexboxLayout:maxLine 不符合需求
protected val mFlexMaxHeight = DisplayUtils.dip2px(57F)
protected val mHotAndDiscoveryFlexMaxHeight = DisplayUtils.dip2px(88F)
private val mDao by lazy { provideDao() }
private val mHotTagClickListener: (Int) -> Unit = {
val tag = mHotTagList!![it]
private val mHotTagClickListener: (HotTagEntity) -> Unit = { tag ->
NewFlatLogUtils.logSearchHotTagClick(
tag.name ?: "",
tag.type ?: "",
@ -90,6 +94,29 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
DirectUtils.directToLinkPage(requireContext(), tag, "(搜索-${tag.name})", "", exposureEvent) // 不需要path
}
private val mDiscoveryTagClickListener: (DiscoveryTagEntity, Int) -> Unit = { tag, position ->
val keyword = tag.keyword
if (keyword.isNotEmpty()) {
PageSwitchDataHelper.pushCurrentPageData(
hashMapOf(
Pair(PageSwitchDataHelper.PAGE_BUSINESS_TYPE, "游戏搜索-搜索发现"),
Pair(PageSwitchDataHelper.PAGE_BUSINESS_ID, tag.id ?: ""),
Pair(PageSwitchDataHelper.PAGE_BUSINESS_NAME, tag.text ?: " ")
)
)
SensorsBridge.trackEvent("SearchLabelClick", "label_name", tag.text ?: "", "label_id", tag.id ?: "")
SensorsBridge.trackSearchDiscoveryClick(
labelName = tag.text ?: "",
labelId = tag.id ?: "",
searchContent = keyword,
position = position
)
mViewModel?.add(keyword)
EventBus.getDefault().post(EBSearch(SearchType.DISCOVERY.value, keyword))
Util_System_Keyboard.hideSoftKeyboardByIBinder(context, mBinding.historyFlex.windowToken)
}
}
override fun getLayoutId(): Int {
return R.layout.fragment_search_default
}
@ -141,15 +168,23 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
mViewModel?.isExistRankList = mRankList?.isNotEmpty() == true
mHotTagList = Config.getSettings()?.search?.hotTag
mViewModel?.isExistHotTag = mHotTagList?.isNotEmpty() == true
mDiscoveryTagList = Config.getSettings()?.search?.discoveryTag
mViewModel?.isExistHotAndDiscoveryTag =
mHotTagList?.isNotEmpty() == true || mDiscoveryTagList?.isNotEmpty() == true
updateHistorySearchView(null)
mViewModel?.historySearchLiveData?.observe(viewLifecycleOwner) {
updateHistorySearchView(it)
}
mBinding.hotTagFlexContainer.setLimitHeight(mFlexMaxHeight)
createFlexContent(mBinding.hotTagFlex, getTagListString(), true, clickListener = mHotTagClickListener)
mBinding.hotAndDiscoveryTagFlexContainer.setLimitHeight(mHotAndDiscoveryFlexMaxHeight)
createHotAndDiscoveryFlexContent(
mBinding.hotAndDiscoveryTagFlex,
getHotTagList(),
getDiscoveryTagList(),
hotTagClickListener = mHotTagClickListener,
discoveryTagClickListener = mDiscoveryTagClickListener
)
initHeadView()
initRankViewPager()
}
@ -181,9 +216,9 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
mBinding.hotHeadContainer.headTitle.text = getString(R.string.search_hot)
mBinding.hotHeadContainer.headTitle.textSize = 16F
mBinding.hotHeadContainer.headActionTv.visibility = View.GONE
mBinding.hotTagHeadContainer.headTitle.text = getString(R.string.search_hot_tag)
mBinding.hotTagHeadContainer.headTitle.textSize = 16F
mBinding.hotTagHeadContainer.headActionTv.visibility = View.GONE
mBinding.hotAndDiscoveryTagHeadContainer.headTitle.text = getString(R.string.search_discovery_tag)
mBinding.hotAndDiscoveryTagHeadContainer.headTitle.textSize = 16F
mBinding.hotAndDiscoveryTagHeadContainer.headActionTv.visibility = View.GONE
}
protected open fun initRankViewPager() {
@ -318,8 +353,8 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
mBinding.historyHeadContainer.root.visibility =
if (mViewModel?.isExistHistory == true) View.VISIBLE else View.GONE
mBinding.historyFlex.visibility = if (mViewModel?.isExistHistory == true) View.VISIBLE else View.GONE
mBinding.hotTagHeadContainer.root.layoutParams =
(mBinding.hotTagHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
mBinding.hotAndDiscoveryTagHeadContainer.root.layoutParams =
(mBinding.hotAndDiscoveryTagHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
setMargins(
0,
if (mViewModel?.isExistHistory == true) 16F.dip2px() else 0,
@ -331,14 +366,15 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
(mBinding.hotHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
setMargins(
0,
if (mViewModel?.isExistHistory == false && mViewModel?.isExistHotTag == false) 16F.dip2px() else 0,
if (mViewModel?.isExistHistory == false && mViewModel?.isExistHotAndDiscoveryTag == false) 16F.dip2px() else 0,
0,
0
)
}
mBinding.hotTagHeadContainer.root.visibility =
if (mViewModel?.isExistHotTag == true) View.VISIBLE else View.GONE
mBinding.hotTagFlex.visibility = if (mViewModel?.isExistHotTag == true) View.VISIBLE else View.GONE
mBinding.hotAndDiscoveryTagHeadContainer.root.visibility =
if (mViewModel?.isExistHotAndDiscoveryTag == true) View.VISIBLE else View.GONE
mBinding.hotAndDiscoveryTagFlex.visibility =
if (mViewModel?.isExistHotAndDiscoveryTag == true) View.VISIBLE else View.GONE
mBinding.hotHeadContainer.root.visibility =
if (mViewModel?.isExistHotSearch == true) View.VISIBLE else View.GONE
mBinding.hotList.visibility = if (mViewModel?.isExistHotSearch == true) View.VISIBLE else View.GONE
@ -361,20 +397,31 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
}
}
private fun getTagListString(): List<String> {
val list = ArrayList<String>()
private fun getHotTagList(): List<HotTagEntity> {
val list = ArrayList<HotTagEntity>()
if (mHotTagList != null) {
for (entity in mHotTagList!!) {
entity.name?.let { list.add(it) }
if (list.size == 8) break // 最多显示8个热门标签
entity.name?.let { list.add(entity) }
}
}
return list
}
private fun getDiscoveryTagList(): List<DiscoveryTagEntity> {
val list = ArrayList<DiscoveryTagEntity>()
if (mDiscoveryTagList != null) {
for (entity in mDiscoveryTagList!!) {
entity.text?.let { list.add(entity) }
}
}
return list
}
fun createFlexContent(
flexView: FlexboxLayout,
contentList: List<String>?,
isHotTag: Boolean = false,
clickListener: (Int) -> Unit
) {
@ -388,16 +435,12 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
val params = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 24F.dip2px())
flexCell.layoutParams = params
if (isHotTag && !mHotTagList.isNullOrEmpty() && mHotTagList!![index].isGuessSearch) {
createSmartHotTagStyle(flexCell, contentList[index])
} else {
flexCell.setSingleLine()
flexCell.ellipsize = TextUtils.TruncateAt.END
flexCell.gravity = Gravity.CENTER
flexCell.textSize = 12F
flexCell.text = StringUtils.shrinkStringWithDot(contentList[index], 6)
flexCell.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
}
flexCell.setSingleLine()
flexCell.ellipsize = TextUtils.TruncateAt.END
flexCell.gravity = Gravity.CENTER
flexCell.textSize = 12F
flexCell.text = StringUtils.shrinkStringWithDot(contentList[index], 6)
flexCell.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
flexCell.setPadding(8F.dip2px(), 0, 8F.dip2px(), 0)
flexCell.background = if (mIsDarkModeOn) GradientDrawable().apply {
setStroke(0.5F.dip2px(), Color.parseColor("#21FFFFFF"))
@ -409,16 +452,84 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
}
}
private fun createSmartHotTagStyle(flexCell: TextView, name: String) {
flexCell.setDrawableStart(R.drawable.ic_smart_search)
private fun createHotAndDiscoveryFlexContent(
flexView: FlexboxLayout,
hotTagList: List<HotTagEntity>,
discoveryTagList: List<DiscoveryTagEntity>,
hotTagClickListener: (HotTagEntity) -> Unit,
discoveryTagClickListener: (DiscoveryTagEntity, Int) -> Unit
) {
if (hotTagList.isEmpty() && discoveryTagList.isEmpty()) return
flexView.removeAllViews()
createHotFlexContent(flexView, hotTagList, hotTagClickListener)
createDiscoveryFlexContent(flexView, discoveryTagList, discoveryTagClickListener)
}
private fun createHotFlexContent(
flexView: FlexboxLayout,
contentList: List<HotTagEntity>?,
clickListener: (HotTagEntity) -> Unit
) {
if (contentList.isNullOrEmpty()) return
for (index in 0 until contentList.count()) {
val flexCell = TextView(context)
flexView.addView(flexCell)
flexCell.layoutParams = FlexboxLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, 24F.dip2px()
)
createSmartHotTagStyle(flexCell, contentList[index])
flexCell.setOnClickListener {
clickListener.invoke(contentList[index])
}
}
}
private fun createDiscoveryFlexContent(
flexView: FlexboxLayout,
contentList: List<DiscoveryTagEntity>?,
clickListener: (DiscoveryTagEntity, Int) -> Unit
) {
if (contentList.isNullOrEmpty()) return
for (index in 0 until contentList.count()) {
val flexCell = TextView(context)
flexView.addView(flexCell)
flexCell.layoutParams = FlexboxLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, 24F.dip2px()
)
createSmartDiscoverTagStyle(flexCell, contentList[index])
flexCell.setPadding(8F.dip2px(), 0, 8F.dip2px(), 0)
flexCell.background = if (mIsDarkModeOn) GradientDrawable().apply {
setStroke(0.5F.dip2px(), Color.parseColor("#21FFFFFF"))
cornerRadius = 999F
} else DrawableView.getStrokeDrawable(com.gh.gamecenter.common.R.color.text_dddddd, 0.5F)
flexCell.setOnClickListener {
clickListener.invoke(contentList[index], index)
}
}
}
private fun createSmartHotTagStyle(flexCell: TextView, entity: HotTagEntity) {
flexCell.compoundDrawablePadding = 4F.dip2px()
flexCell.gravity = Gravity.CENTER_VERTICAL
flexCell.typeface = Typeface.DEFAULT_BOLD
flexCell.textSize = 12F
flexCell.text = StringUtils.shrinkStringWithDot(name, 6)
flexCell.setTextColor(Color.WHITE)
flexCell.text = StringUtils.shrinkStringWithDot(entity.name, 6)
flexCell.setPadding(8F.dip2px(), 0, 8F.dip2px(), 0)
val colors =
intArrayOf(com.gh.gamecenter.common.R.color.text_FFB749.toColor(requireContext()), com.gh.gamecenter.common.R.color.text_FF6D3C.toColor(requireContext()))
intArrayOf(
com.gh.gamecenter.common.R.color.text_FFB749.toColor(requireContext()),
com.gh.gamecenter.common.R.color.text_FF6D3C.toColor(requireContext())
)
val position = floatArrayOf(0F, 1F)
val linearGradient = LinearGradient(
0F,
@ -429,10 +540,53 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
position,
Shader.TileMode.CLAMP
)
flexCell.paint.shader = linearGradient
val shapeRadius = floatArrayOf(999F, 999F, 999F, 999F, 999F, 999F, 999F, 999F)
val strokeWidth = 0.5F.dip2px().toFloat()
val shape = RoundRectShape(shapeRadius, RectF(strokeWidth, strokeWidth, strokeWidth, strokeWidth), shapeRadius)
flexCell.background = ShapeDrawable(shape).apply {
paint.shader = linearGradient
}
if (entity.isGuessSearch) {
flexCell.setTextColor(Color.WHITE)
flexCell.typeface = Typeface.DEFAULT_BOLD
flexCell.setDrawableStart(R.drawable.ic_smart_search)
flexCell.paint.shader = linearGradient
} else {
flexCell.setTextColor(
ContextCompat.getColor(
requireContext(),
com.gh.gamecenter.common.R.color.text_secondary
)
)
}
flexCell.invalidate()
}
private fun createSmartDiscoverTagStyle(flexCell: TextView, entity: DiscoveryTagEntity) {
val labelIcon = when (entity.recommendType) {
"hot" -> R.drawable.ic_search_hot
"new" -> R.drawable.ic_search_new
"surge", "rise" -> R.drawable.ic_search_rise
"update" -> R.drawable.ic_search_update
else -> -1
}
if (labelIcon != -1) {
flexCell.setDrawableEnd(labelIcon.toDrawable())
flexCell.compoundDrawablePadding = 4F.dip2px()
}
flexCell.setSingleLine()
flexCell.ellipsize = TextUtils.TruncateAt.END
flexCell.gravity = Gravity.CENTER
flexCell.textSize = 12F
flexCell.text = entity.text
flexCell.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
flexCell.setPadding(8F.dip2px(), 0, 8F.dip2px(), 0)
flexCell.background = if (mIsDarkModeOn) GradientDrawable().apply {
setStroke(0.5F.dip2px(), Color.parseColor("#21FFFFFF"))
cornerRadius = 999F
} else DrawableView.getStrokeDrawable(com.gh.gamecenter.common.R.color.text_dddddd, 0.5F)
}
private fun postExposureEvent(index: Int) {
mRankList?.safelyGetInRelease(index)?.content?.forEach {
if (it.link.type == "game") {
@ -451,7 +605,13 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
notifyItemRangeChanged(0, itemCount)
}
mViewModel?.historySearchLiveData?.value?.let { updateHistorySearchView(it) }
createFlexContent(mBinding.hotTagFlex, getTagListString(), true, clickListener = mHotTagClickListener)
createHotAndDiscoveryFlexContent(
mBinding.hotAndDiscoveryTagFlex,
getHotTagList(),
getDiscoveryTagList(),
hotTagClickListener = mHotTagClickListener,
discoveryTagClickListener = mDiscoveryTagClickListener
)
}
protected open fun provideDao(): ISearchHistoryDao =

View File

@ -11,7 +11,7 @@ class SearchDefaultViewModel(private val dao: ISearchHistoryDao) : ViewModel() {
it
}
var isExistHotSearch: Boolean = false
var isExistHotTag: Boolean = false
var isExistHotAndDiscoveryTag: Boolean = false
var isExistHistory: Boolean = false
var isExistRankList: Boolean = false

View File

@ -86,7 +86,7 @@ class SearchSubjectItemViewHolder(var binding: SearchSubjectItemBinding) : Recyc
binding.run {
subjectRv.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
subjectRv.adapter = SearchSubjectAdapter(context, entity.getFilterGame(), "($type-专题)", key) {
subjectRv.adapter = SearchSubjectAdapter(context, entity.getFilterGame(), entity.columnId, entity.name, "($type-专题)", key) {
dao?.add(key)
if (itemData.adConfig != null) {
NewFlatLogUtils.logClickGameAd(

View File

@ -108,6 +108,7 @@ class SearchGameResultAdapter(
return when {
oldItem?.subject != null && newItem?.subject != null -> {
oldItem.subject.columnId == newItem.subject.columnId
&& oldItem.subject.games == newItem.subject.games
}
oldItem?.game != null && newItem?.game != null -> {
@ -122,6 +123,7 @@ class SearchGameResultAdapter(
return when {
oldItem?.subject != null && newItem?.subject != null -> {
oldItem.subject.columnId == newItem.subject.columnId
&& oldItem.subject.games == newItem.subject.games
}
oldItem?.game != null && newItem?.game != null -> {
@ -170,39 +172,50 @@ class SearchGameResultAdapter(
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is SearchSubjectItemViewHolder -> {
holder.binding.run {
when {
position == 0 -> topDivider.visibility = View.GONE
position > 0 -> {
val gameEntity = mEntityList[position - 1].game
if (gameEntity != null) {
val isShowTag = gameEntity.contentTag != null
&& (gameEntity.contentTag!!.custom.isNotEmpty()
|| gameEntity.contentTag!!.zone.link.isNotEmpty()
|| gameEntity.contentTag!!.isLibaoExists
|| gameEntity.contentTag!!.server)
val isShowTagByMirror =
if (gameEntity.shouldUseMirrorInfo()) isShowTag && gameEntity.obtainMirrorData()?.contentTagStatus == "on" else isShowTag
if (isShowTagByMirror) {
topDivider.visibility = View.GONE
val itemData = mEntityList[position]
if (itemData.subject == null || itemData.subject.games.isEmpty()) {
holder.binding.topDivider.visibility = View.GONE
holder.binding.bottomDivider.visibility = View.GONE
holder.binding.headContainer.root.visibility = View.GONE
holder.binding.subjectRv.visibility = View.GONE
} else {
holder.binding.headContainer.root.visibility = View.VISIBLE
holder.binding.subjectRv.visibility = View.VISIBLE
holder.binding.run {
when {
position == 0 -> topDivider.visibility = View.GONE
position > 0 -> {
val gameEntity = mEntityList[position - 1].game
if (gameEntity != null) {
val isShowTag = gameEntity.contentTag != null
&& (gameEntity.contentTag!!.custom.isNotEmpty()
|| gameEntity.contentTag!!.zone.link.isNotEmpty()
|| gameEntity.contentTag!!.isLibaoExists
|| gameEntity.contentTag!!.server)
val isShowTagByMirror =
if (gameEntity.shouldUseMirrorInfo()) isShowTag && gameEntity.obtainMirrorData()?.contentTagStatus == "on" else isShowTag
if (isShowTagByMirror) {
topDivider.visibility = View.GONE
} else {
topDivider.visibility = View.VISIBLE
}
} else {
topDivider.visibility = View.VISIBLE
topDivider.visibility = View.GONE
}
} else {
topDivider.visibility = View.GONE
}
}
bottomDivider.visibility = View.VISIBLE
}
bottomDivider.visibility = View.VISIBLE
holder.bindSubjectItem(
mContext,
itemData,
SearchType.fromString(type).toChinese(),
key,
dao,
sourceEntrance = sourceEntrance
)
}
holder.bindSubjectItem(
mContext,
mEntityList[position],
SearchType.fromString(type).toChinese(),
key,
dao,
sourceEntrance = sourceEntrance
)
}
is SearchGameFirstItemViewHolder -> {
@ -751,7 +764,8 @@ class SearchGameResultAdapter(
SearchActivity.toTrackSearchType(type),
gameEntity.id,
gameEntity.name ?: "",
gameEntity.categoryChinese
gameEntity.categoryChinese,
position
)
MiniGameItemHelper.launchMiniGame(gameEntity)
MiniGameItemHelper.trackMiniGameClick(
@ -768,7 +782,8 @@ class SearchGameResultAdapter(
SearchActivity.toTrackSearchType(type),
gameEntity.id,
gameEntity.name ?: "",
gameEntity.categoryChinese
gameEntity.categoryChinese,
position
)
GameDetailActivity.startGameDetailActivity(
context, gameEntity,

View File

@ -373,12 +373,15 @@ open class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultV
}
fun setParams(key: String, type: String) {
this.mKey = key
this.mType = type
mAdapter?.key = key
mAdapter?.type = type
mAdapter?.clearAdIdSet()
mListViewModel?.updateSearchKeyWithType(key, type)
if (this.mKey == key) return
this.mKey = key
mAdapter?.key = key
mAdapter?.clearAdIdSet()
mListViewModel?.clearSearchSubjects()
mListViewModel?.load(LoadType.REFRESH)
}

View File

@ -10,13 +10,20 @@ import com.gh.gamecenter.retrofit.service.ApiService
import com.halo.assistant.HaloApp
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import java.net.URLEncoder
import java.util.concurrent.TimeUnit
class SearchGameResultRepository(
private val mApi: ApiService = RetrofitManager.getInstance().api,
private val mNewApi: ApiService = RetrofitManager.getInstance().newApi,
private val mWGameSubjectCPMDataSource: WGameSubjectCPMRemoteDataSource = WGameSubjectCPMRemoteDataSource()
) : ISearchGameResultRepository {
private var currentSearchKey: String? = null
private var currentMiniGameCPMSearchList: MutableList<GameEntity>? = null
override fun getSearchGame(
key: String?,
page: Int
@ -31,11 +38,26 @@ class SearchGameResultRepository(
)
}
override fun getSearchMiniGameCPM(key: String?): Observable<List<GameEntity>> {
val currentMiniGameCPMSearchList = currentMiniGameCPMSearchList
if (key == currentSearchKey && currentMiniGameCPMSearchList != null) {
return Observable.just(currentMiniGameCPMSearchList)
}
return mNewApi.getSearchWechatMiniCPMGame(key)
.timeout(5, TimeUnit.SECONDS)
.onErrorReturnItem(emptyList())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext {
this.currentSearchKey = key
this.currentMiniGameCPMSearchList = it
}
}
override fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>> {
return mApi.getSearchSubject(key, page)
}
override fun getWGameCPMGameList(): Single<MutableList<GameEntity>> {
return mWGameSubjectCPMDataSource.getRecommendCPMList(1)
return mWGameSubjectCPMDataSource.getUserRecommendCPMList()
}
}

View File

@ -67,49 +67,60 @@ class SearchGameResultViewModel(
@SuppressLint("CheckResult")
private fun decorateListAndPost(list: MutableList<GameEntity>) {
val itemDataList = ArrayList(
list.mapIndexed { index, game ->
SearchItemData(game = game, gamePosition = index, isFirst = index == 0)
}
)
val itemDataList = ArrayList<SearchItemData>()
val combineGameList = list.toMutableList()
refreshWrongInstallStatus()
repository.getSearchSubject(mSearchKey, mPage)
.map { dataList ->
mSearchSubjects.addAll(dataList)
var cpmSearchSubject: SearchSubjectEntity? = null
mSearchSubjects.forEach {
// 微信小游戏CPM专题需要等搜索广告位插入完成后再插入
if (it.location == WGAME_CPM_SUBJECT_POSITION) {
cpmSearchSubject = it.apply { isWGameSubjectCPM = true }
repository.getSearchMiniGameCPM(mSearchKey)
.zipWith(repository.getSearchSubject(mSearchKey, mPage)) { cpmGameList, subjectList -> // CPM游戏搜索结果列表合并
for (cpmGame in cpmGameList) {
if (cpmGame.location <= 0 || cpmGame.location > list.size) {
combineGameList.add(cpmGame)
} else {
val item = SearchItemData(subject = it)
if (it.location <= 0 || it.location > itemDataList.size) {
itemDataList.add(item)
} else {
itemDataList.add(it.location - 1, item)
}
combineGameList.add(cpmGame.location - 1, cpmGame)
}
}
cpmSearchSubject to dataList
itemDataList.addAll(
combineGameList.mapIndexed { index, game ->
SearchItemData(game = game, gamePosition = index, isFirst = index == 0)
}
)
subjectList
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ result ->
.subscribe({ mutableList ->
val cpmSearchSubjects = mutableListOf<SearchSubjectEntity>()
mSearchSubjects.addAll(mutableList)
mSearchSubjects.forEach {
if (it.type == SearchSubjectEntity.TYPE_WECHAT_GAME_CPM_COLUMN) {
cpmSearchSubjects.add(it.apply { isWGameSubjectCPM = true })
}
val item = SearchItemData(subject = it)
if (it.location <= 0 || it.location > itemDataList.size) {
itemDataList.add(item)
} else {
itemDataList.add(it.location - 1, item)
}
}
// 处理初始化列表且游戏列表size为0的情况
handleLoadStatusWhenGameListIsEmpty(list, itemDataList)
if (mIsManuallySearch) {
if (mSearchKey == AdDelegateHelper.gameSearchKeyword) {
updateAdConfigAndDecorateList(itemDataList, list, result.first)
updateAdConfigAndDecorateList(itemDataList, list)
} else {
AdDelegateHelper.requestAdConfig(false, mSearchKey ?: "") {
updateAdConfigAndDecorateList(itemDataList, list, result.first)
updateAdConfigAndDecorateList(itemDataList, list)
}
}
} else {
decorateWithWGameSubjectCPM(itemDataList, list, result.first)
postResultList(itemDataList, list)
}
if (cpmSearchSubjects.isNotEmpty()) {
decorateListWithWGameCPM(cpmSearchSubjects, itemDataList, list)
}
}, {
it.printStackTrace()
@ -118,12 +129,50 @@ class SearchGameResultViewModel(
})
}
/**
* 请求微信小游戏CPM接口获取专题游戏数据并插入对应的专题项中相关需求如下
* @see <a href="https://jira.shanqu.cc/browse/GHZSCY-6710">【光环助手】CPM微信小游戏API接入工作</a>
* @see <a href="https://jira.shanqu.cc/browse/GHZSCY-6827">【光环助手】CPM微信小游戏一期优化</a>
*/
@SuppressLint("CheckResult")
private fun updateAdConfigAndDecorateList(
private fun decorateListWithWGameCPM(
subjects: List<SearchSubjectEntity>,
itemDataList: ArrayList<SearchItemData>,
list: MutableList<GameEntity>,
cpmSubjectEntity: SearchSubjectEntity?
list: MutableList<GameEntity>
) {
val subjectList = subjects.filterNot {
it.games.isNotEmpty()
}
if (subjectList.isEmpty()) return
val subjectSingleList = subjectList.map { subject ->
repository.getWGameCPMGameList()
.onErrorReturnItem(mutableListOf())
.map { subject.columnId to it }
}
Single.zip(subjectSingleList) { it.map { item -> item as Pair<String, MutableList<GameEntity>> } }
.map { dataList ->
for (index in itemDataList.indices) {
val itemData = itemDataList[index]
val subject = itemData.subject ?: continue
if (subject.games.isNotEmpty()) continue
val pair = dataList.firstOrNull { data ->
data.first == subject.columnId
} ?: continue
val newItemData = SearchItemData(
subject = subject.copy(games = pair.second)
)
itemDataList[index] = newItemData
}
itemDataList
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ dataList -> postResultList(dataList, list) }, {})
}
@SuppressLint("CheckResult")
private fun updateAdConfigAndDecorateList(itemDataList: ArrayList<SearchItemData>, list: MutableList<GameEntity>) {
mGameSearchAdList =
AdDelegateHelper.getGameSearchAdList().filter { AdDelegateHelper.shouldShowGameSearchAd(it) }.toArrayList()
.apply { sortBy { it.position } }
@ -137,7 +186,6 @@ class SearchGameResultViewModel(
mAdPositionSet = adPositionSet
if (adPositionSet.isNotEmpty()) {
val decoratedItemDataList = ArrayList(itemDataList)
val ownerAdList = arrayListOf<AdConfig>()
val thirdPartyAdList = arrayListOf<AdConfig>()
@ -175,18 +223,18 @@ class SearchGameResultViewModel(
Single.zip(requestSingleList) {}
.compose(singleToMain())
.subscribe({
decorateListWithAd(itemDataList, decoratedItemDataList, list, cpmSubjectEntity)
decorateListWithAd(itemDataList, list)
}, {
decorateListWithAd(itemDataList, decoratedItemDataList, list, cpmSubjectEntity)
decorateListWithAd(itemDataList, list)
})
} else {
decorateListWithAd(itemDataList, decoratedItemDataList, list, cpmSubjectEntity)
decorateListWithAd(itemDataList, list)
}
} else {
decorateListWithThirdPartyAdOnly(decoratedItemDataList, thirdPartyAdList, list, cpmSubjectEntity)
decorateListWithThirdPartyAdOnly(itemDataList, thirdPartyAdList, list)
}
} else {
decorateWithWGameSubjectCPM(itemDataList, list, cpmSubjectEntity)
postResultList(itemDataList, list)
}
}
@ -197,27 +245,25 @@ class SearchGameResultViewModel(
}
private fun decorateListWithThirdPartyAdOnly(
decoratedItemDataList: ArrayList<SearchItemData>,
itemDataList: ArrayList<SearchItemData>,
thirdPartyAdList: List<AdConfig>,
list: List<GameEntity>,
cpmSubjectEntity: SearchSubjectEntity?
list: List<GameEntity>
) {
thirdPartyAdList.forEach {
decoratedItemDataList.add(it.position - 1, SearchItemData(ad = it.thirdPartyAd, adConfig = it))
itemDataList.add(it.position - 1, SearchItemData(ad = it.thirdPartyAd, adConfig = it))
SPUtils.setLong(Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + it.position, System.currentTimeMillis())
}
decorateWithWGameSubjectCPM(decoratedItemDataList, list, cpmSubjectEntity)
postResultList(itemDataList, list)
}
private fun decorateListWithAd(
itemDataList: ArrayList<SearchItemData>,
decoratedItemDataList: ArrayList<SearchItemData>,
list: List<GameEntity>,
cpmSubjectEntity: SearchSubjectEntity?
list: List<GameEntity>
) {
val adGameOneIdSet = HashSet<String>() // 展示样式为单个游戏时记录游戏ID避免重复
val decoratedItemDataSize = itemDataList.size
for ((index, position) in mAdPositionSet!!.withIndex()) {
if (position < itemDataList.size + index + 1) {
if (position < decoratedItemDataSize + index + 1) {
val adConfig = mGameSearchAdList!!.safelyGetInRelease(index)
val showThirdPartyAd = adConfig?.displayRule?.adSource == AdDelegateHelper.AD_TYPE_SDK
val showOwnerAd = adConfig?.displayRule?.adSource == AdDelegateHelper.AD_TYPE_OWNER
@ -225,7 +271,7 @@ class SearchGameResultViewModel(
if ((showThirdPartyAd && adConfig?.thirdPartyAd != null)
|| (showOwnerAd && adConfig?.ownerAd == null && adConfig?.thirdPartyAd != null && showOnFailed)
) {
decoratedItemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd, adConfig = adConfig))
itemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd, adConfig = adConfig))
SPUtils.setLong(
Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + adConfig.position,
System.currentTimeMillis()
@ -237,7 +283,7 @@ class SearchGameResultViewModel(
if (!gameList.isNullOrEmpty()) {
if (adConfig.ownerAd.adSource?.displayStyle == "game_zone") {
// 游戏专题
decoratedItemDataList.add(
itemDataList.add(
position - 1,
SearchItemData(
subject = SearchSubjectEntity(
@ -259,7 +305,7 @@ class SearchGameResultViewModel(
}
randomGameEntity?.id?.let { adGameOneIdSet.add(it) }
decoratedItemDataList.add(
itemDataList.add(
position - 1,
SearchItemData(game = randomGameEntity, adConfig = adConfig)
)
@ -270,7 +316,7 @@ class SearchGameResultViewModel(
)
} else if (showOnFailed && adConfig.thirdPartyAd != null) {
// 自有广告为空时,显示第三方广告
decoratedItemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd, adConfig = adConfig))
itemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd, adConfig = adConfig))
SPUtils.setLong(
Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + adConfig.position,
System.currentTimeMillis()
@ -281,41 +327,7 @@ class SearchGameResultViewModel(
break
}
}
decorateWithWGameSubjectCPM(decoratedItemDataList, list, cpmSubjectEntity)
}
@SuppressLint("CheckResult")
private fun decorateWithWGameSubjectCPM(
resultList: ArrayList<SearchItemData>,
list: List<GameEntity>,
cpmSubjectEntity: SearchSubjectEntity?
) {
// 微信小游戏CPM专题搜索结果存在则请求CPM接口获取微信小游戏列表数据并将列表数据插入缓存的CPM专题中
// 再根据location的值固定为4将CPM专题插入搜索结果列表中
// 相关需求https://jira.shanqu.cc/browse/GHZSCY-6710
cpmSubjectEntity?.let { subject ->
if (subject.games.isNotEmpty()) {
Single.just(subject.games.toMutableList())
} else {
repository.getWGameCPMGameList()
.onErrorReturnItem(mutableListOf())
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
val cpmSearchItemData = SearchItemData(subject = subject.apply { games = it })
if (subject.location <= 0 || subject.location > resultList.size) {
resultList.add(cpmSearchItemData)
} else {
resultList.add(subject.location - 1, cpmSearchItemData)
}
postResultList(resultList, list)
},
{
postResultList(resultList, list)
})
} ?: postResultList(resultList, list)
postResultList(itemDataList, list)
}
@SuppressLint("CheckResult")
@ -343,7 +355,7 @@ class SearchGameResultViewModel(
}
private fun postResultList(resultList: ArrayList<SearchItemData>, list: List<GameEntity>) {
mResultLiveData.postValue(resultList)
mResultLiveData.postValue(resultList.toMutableList())
if (mPage == 1) {
if (repository is MiniGameSearchResultRepository) {
SensorsBridge.trackMiniGameSearchResultReturn(
@ -362,7 +374,6 @@ class SearchGameResultViewModel(
mSearchKey ?: "",
SearchActivity.toTrackSearchType(mSearchType),
list.isNotEmpty()
)
}
@ -431,7 +442,6 @@ class SearchGameResultViewModel(
companion object {
const val AD_SUBJECT_GAME_MAX_COUNT = 8
const val WGAME_CPM_SUBJECT_POSITION = 4
}
}

View File

@ -13,6 +13,8 @@ import com.lightgame.adapter.BaseRecyclerAdapter
class SearchSubjectAdapter(
context: Context,
private val mList: List<GameEntity>,
private val mColumnId: String,
private val mColumnName: String,
private val mEntrance: String,
private val mKey: String,
private val clickCallback: ((GameEntity) -> Unit)
@ -40,7 +42,10 @@ class SearchSubjectAdapter(
MiniGameItemHelper.launchMiniGame(gameEntity)
MiniGameItemHelper.trackMiniGameClick(
gameEntity = gameEntity,
gameColumnId = mColumnId,
gameColumnName = mColumnName,
location = "小游戏搜索结果列表",
position = position,
searchContent = mKey,
)
} else {

View File

@ -59,23 +59,26 @@ class SearchGameListAdapter(
override fun navigateToGameDetailPage(
gameId: String,
position: Int,
collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity
) {
viewModel.navigateToGameDetailPage(gameId, collection)
viewModel.navigateToGameDetailPage(gameId, position, collection)
}
override fun navigateToHomePage(
userId: String,
position: Int,
collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity
) {
viewModel.navigateToHomePage(userId, collection)
viewModel.navigateToHomePage(userId, position, collection)
}
override fun navigateGameCollectionDetailPage(
position: Int,
collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity,
exposureSourceList: List<ExposureSource>
) {
viewModel.navigateGameCollectionDetailPage(collection, exposureSourceList)
viewModel.navigateGameCollectionDetailPage(position, collection, exposureSourceList)
}
})

View File

@ -116,7 +116,8 @@ class SearchGameListFragment : LazyFragment() {
context = requireContext(),
itemId,
topCommentId = "",
exposureSourceList = exposureSourceList.toArrayList()
exposureSourceList = exposureSourceList.toArrayList(),
entrance = "游戏单搜索"
)
)
})

View File

@ -9,6 +9,7 @@ import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.databinding.FragmentSearchTabBinding
import com.gh.gamecenter.feature.entity.SettingsEntity
import com.gh.gamecenter.search.SearchGameResultFragment
@ -43,7 +44,7 @@ class SearchTabFragment : BaseFragment<Any>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
location = arguments?.getString(EntranceConsts.KEY_LOCATION) ?: ""
with(activityViewModel) {
searchKeyAndType.observe(this@SearchTabFragment) { (key, type) ->
@ -121,6 +122,17 @@ class SearchTabFragment : BaseFragment<Any>() {
}
override fun onDarkModeChanged() {
super.onDarkModeChanged()
if (::binding.isInitialized) {
binding.tabLayout.setTabTextColors(
com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext()),
com.gh.gamecenter.common.R.color.text_theme.toColor(requireContext())
)
}
}
companion object {
fun newInstance(location: String) =

View File

@ -2,7 +2,6 @@ package com.gh.gamecenter.search.viewholder
import android.content.Context
import android.graphics.Color
import android.text.Html
import android.util.SparseArray
import android.view.View
import android.view.ViewGroup
@ -14,10 +13,8 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.gh.common.util.CheckLoginUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.SearchType
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.HtmlUtils
import com.gh.gamecenter.databinding.GameCollectionSquareItemBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
@ -113,16 +110,16 @@ class SearchGameListViewHolder(
ivIcon.setOnClickListener {
val game = item.games.getOrNull(index)
game?.id?.let { gameId ->
listener.navigateToGameDetailPage(gameId, item)
listener.navigateToGameDetailPage(gameId, bindingAdapterPosition, item)
}
}
}
userContainer.setOnClickListener {
listener.navigateToHomePage(item.user.id, item)
listener.navigateToHomePage(item.user.id, bindingAdapterPosition, item)
}
root.setOnClickListener {
listener.navigateGameCollectionDetailPage(item, exposureEvent.source)
listener.navigateGameCollectionDetailPage(bindingAdapterPosition, item, exposureEvent.source)
}
}
}
@ -131,12 +128,18 @@ class SearchGameListViewHolder(
fun navigateToGameDetailPage(
gameId: String,
position: Int,
collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity
)
fun navigateToHomePage(userId: String, collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity)
fun navigateToHomePage(
userId: String,
position: Int,
collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity
)
fun navigateGameCollectionDetailPage(
position: Int,
collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity,
exposureSourceList: List<ExposureSource>
)

View File

@ -9,6 +9,7 @@ import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.clearHtmlFormatCompletely
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.home.custom.model.CustomPageData
import com.gh.gamecenter.livedata.Event
@ -109,15 +110,23 @@ class SearchGameListViewModel : ViewModel() {
private val _gameDetailDestination = MutableLiveData<Event<String>>()
val gameDetailDestination: LiveData<Event<String>> = _gameDetailDestination
fun navigateToGameDetailPage(gameId: String, collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity) {
trackGameCollectSearchResultClick(collection)
fun navigateToGameDetailPage(
gameId: String,
position: Int,
collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity
) {
trackGameCollectSearchResultClick(position, collection)
_gameDetailDestination.value = Event(gameId)
}
private val _homeDestination = MutableLiveData<Event<String>>()
val homeDestination: LiveData<Event<String>> = _homeDestination
fun navigateToHomePage(userId: String, collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity) {
trackGameCollectSearchResultClick(collection)
fun navigateToHomePage(
userId: String,
position: Int,
collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity
) {
trackGameCollectSearchResultClick(position, collection)
_homeDestination.value = Event(userId)
}
@ -126,14 +135,18 @@ class SearchGameListViewModel : ViewModel() {
_gameCollectionDetailDestination
fun navigateGameCollectionDetailPage(
position: Int,
collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity,
exposureSourceList: List<ExposureSource>
) {
trackGameCollectSearchResultClick(collection)
trackGameCollectSearchResultClick(position, collection)
_gameCollectionDetailDestination.value = Event(collection.id to exposureSourceList)
}
private fun trackGameCollectSearchResultClick(collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity) {
private fun trackGameCollectSearchResultClick(
position: Int,
collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity
) {
SensorsBridge.trackGameCollectSearchResultClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
@ -141,7 +154,8 @@ class SearchGameListViewModel : ViewModel() {
SearchActivity.toTrackSearchType(type),
location,
collection.id,
collection.title
collection.title.clearHtmlFormatCompletely(),
position
)
}
}

Some files were not shown because too many files have changed in this diff Show More