Compare commits

...

148 Commits

Author SHA1 Message Date
f3c85f8c90 refactor: update commit id 2024-01-11 14:32:42 +08:00
f53ac827da feat: 32位组件更新下载 2024-01-11 14:29:09 +08:00
c5d2e770f9 refactor!: 添加测试环境的脚本 2024-01-10 17:13:42 +08:00
8d0b95960b refactor!: 添加测试环境的脚本 2024-01-10 16:53:59 +08:00
8de168c642 feat: new/upgrade接口参数修改 2024-01-10 14:30:11 +08:00
9f4c6f8bfd feat: 畅玩32位和插件的更新流程 2024-01-10 14:04:27 +08:00
2910f8492d fix: 修复获取module_version错误 2024-01-09 14:22:15 +08:00
fd4ec8224d refactor!: 临时修改打包测试版本 2024-01-09 14:07:27 +08:00
c837c77215 refactor: 优化畅玩32 debug打包步骤 2024-01-05 10:33:44 +08:00
9a45682c74 feat: 获取32位组件和插件的接口数据 2024-01-04 14:35:50 +08:00
ca1448aeb7 refactor: update commit id 2024-01-03 17:58:25 +08:00
5dadd20382 feat: 修改va配置读取 2024-01-03 17:25:58 +08:00
c6917deaca feat: 修改plugin配置读取 2024-01-03 17:12:04 +08:00
003053b8a3 fix: 修复头条,快手等其他flavor脚本打包出错的问题 2024-01-03 14:20:05 +08:00
d37e50915b refactor: upgrade shadow_version to 1.0.4 2023-12-29 17:20:42 +08:00
9668b7e9e6 refactor: update vasdk commit id. 2023-12-29 15:03:08 +08:00
dfd8b29a11 fix: min sdk version smaller than 21. 2023-12-29 15:02:50 +08:00
cfe1bea4d2 refactor: 更新shadow版本至 1.0.3 2023-12-29 11:31:23 +08:00
4eb20fd14c refactor: 更新maven拉取顺序 2023-12-29 11:31:23 +08:00
9b8fd9d8d8 refactor: 更新apk文件路径 2023-12-29 11:31:23 +08:00
94c02835b9 refactor: 下载插件到assets目录 2023-12-29 11:31:23 +08:00
84f24302f0 refactor: 更新打包脚本 2023-12-29 11:31:23 +08:00
e5fa7f8655 feat: 展示64位va插件版本信息 https://jira.shanqu.cc/browse/GHZS-3885 2023-12-29 11:31:23 +08:00
70797b2e6f fix: 过滤va项目的配置&修复错误的assets添加脚步 2023-12-29 11:31:23 +08:00
8f84cf8d51 feat: 光环助手va组件兼容旧版畅玩助手游戏业务 2023-12-29 11:31:23 +08:00
1bc2ef205b feat: 接入vasdk编译通过 2023-12-29 11:31:23 +08:00
5e83085747 refactor: va模块引用 2023-12-29 11:31:23 +08:00
173b0c32de feat: 加速器模块占用空间太大,给ci/cd集成增加时间成本,考虑到加速器变更频繁度较低,改为maven引用 2023-12-29 11:31:18 +08:00
18b14969ec feat: 同步vasdk的代码 2023-12-29 11:30:35 +08:00
581d7d6b0e feat: 接入va模块 2023-12-29 11:29:27 +08:00
423bcda7ff Merge branch 'feat/GHZS-4446' into 'release'
feat:【光环助手】隐私合规问题-12/22 https://jira.shanqu.cc/browse/GHZS-4444

See merge request halo/android/assistant-android!1482
2023-12-28 11:44:29 +08:00
2bb61e8e4b feat: 隐私合规问题-12/22 https://jira.shanqu.cc/browse/GHZS-4446 2023-12-28 11:43:56 +08:00
22c727cd2f Merge branch 'hotfix/v5.32.7-997/crashes' into 'release'
修复sentry闪退问题

See merge request halo/android/assistant-android!1475
2023-12-18 14:20:19 +08:00
5e5aee539e fix: 修复首页下拉刷新偶发的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/352463/?project=22&query=is%3Aunresolved+assigned%3Ame&sort=date&statsPeriod=14d 2023-12-18 14:11:21 +08:00
c158225472 fix: 修复开屏广告偶发的空指针闪退 https://sentry.shanqu.cc/organizations/lightgame/issues/349408/events/ca7a12772e484958a5a9d4113fcba161/?project=22&statsPeriod=14d 2023-12-18 14:10:30 +08:00
36e9bd20ac fix: V5.32.5群测问题汇总1204 https://jira.shanqu.cc/browse/GHZS-4375 2023-12-13 15:36:34 +08:00
cc4ef16e10 chore: 版本更新至 5.32.7 2023-12-13 14:20:28 +08:00
0911cd146b Merge branch 'hotfix/v5.32.5-995/CWZS-138' into 'release'
fix:【畅玩助手】畅玩-最近在玩模块、双开按钮异常 https://jira.shanqu.cc/browse/CWZS-138

See merge request halo/android/assistant-android!1468
2023-12-13 09:34:04 +08:00
8e255b1803 fix:【畅玩助手】畅玩-最近在玩模块、双开按钮异常 https://jira.shanqu.cc/browse/CWZS-138 2023-12-13 09:34:04 +08:00
ae0f4c948b chore: 版本更新至 5.32.5 2023-12-12 15:04:32 +08:00
d650739632 Merge branch 'feature-GHZS-sentry-20231211' into 'release'
fix: Sentry异常修复

See merge request halo/android/assistant-android!1470
2023-12-11 18:00:01 +08:00
6f6a734cb5 fix: Sentry异常修复 2023-12-11 18:00:01 +08:00
e510146775 Merge branch 'hotfix/v5.32.5-995/search_crash' into 'release'
fix: 修复点击搜索栏闪退的问题...

See merge request halo/android/assistant-android!1469
2023-12-11 10:09:01 +08:00
8b863955a3 fix: 修复点击搜索栏闪退的问题 https://sentry.shanqu.cc/organizations/lightgame/issues/350701/events/e5db556244ac4ecb93d37e7997103bf3/?environment=kuaishou&project=22 2023-12-11 10:03:02 +08:00
37155b96dd Merge branch 'hotfix/v5.32.5-995/crashes' into 'release'
修复sentry闪退问题

See merge request halo/android/assistant-android!1467
2023-12-08 14:07:02 +08:00
e55d4d3332 fix: 捕获替换Fragment关联的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/348952/events/d6c0400d0edb4ee8b302faab4707960d/?project=22&statsPeriod=14d 2023-12-08 13:50:00 +08:00
10572e7b0b fix: 修复线上闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/349079/events/06d299cb0e6549a49f80cd248a91e614/?project=22 2023-12-05 14:53:00 +08:00
0c807922d6 chore: 版本更新至 5.32.5 2023-11-29 16:51:00 +08:00
d7f5b573c6 Merge branch 'hotfix/v5.32.4-994/provider_conflict' into 'release'
fix: 移除穿山甲广告 tools 依赖

See merge request halo/android/assistant-android!1463
2023-11-29 16:50:04 +08:00
f9d624b077 fix: 移除穿山甲广告 tools 依赖 2023-11-29 16:48:42 +08:00
a22fa59975 Merge branch 'hotfix/v5.32.4-994/get_app_list_crash' into 'release'
fix: 获取应用列表时偶发的空指针异常 https://sentry.shanqu.cc/organizations/lightgame/issues/343985/?project=22

See merge request halo/android/assistant-android!1460
2023-11-27 10:15:41 +08:00
e68ad6489a fix: 获取应用列表时偶发的空指针异常 https://sentry.shanqu.cc/organizations/lightgame/issues/343985/?project=22 2023-11-27 10:06:09 +08:00
ccd3a98799 Merge branch 'hotfix/v5.32.4-994/deadsystem-crash' into 'release'
fix: catch 部分 DeadSystemException 异常

See merge request halo/android/assistant-android!1458
2023-11-24 11:45:28 +08:00
96026ef9fa fix: catch 部分 DeadSystemException 异常 2023-11-24 11:31:56 +08:00
777e05733c chore: 版本更新至 5.32.4
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2023-11-23 15:41:58 +08:00
cbf6f34a9c Merge branch 'hotfix/v5.32.3-993/replace_fragment_crash' into 'release'
fix: 修复底部第四个Tab重复创建Fragment的问题,捕获替换Fragment出现的异常

See merge request halo/android/assistant-android!1455
2023-11-22 13:40:11 +08:00
23c0f12ed3 fix: 修复底部第四个Tab重复创建Fragment的问题,捕获替换Fragment出现的异常 2023-11-22 11:55:19 +08:00
da91dcab59 chore: 版本更新至 5.32.3
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2023-11-21 17:07:32 +08:00
ee846bc620 Merge branch 'feat/GHZS-4303' into 'release'
feat: 广告回传参数补充 https://jira.shanqu.cc/browse/GHZS-4303

See merge request halo/android/assistant-android!1453
2023-11-21 17:06:22 +08:00
aa3db9330e feat: 广告回传参数补充 https://jira.shanqu.cc/browse/GHZS-4303
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2023-11-21 16:52:08 +08:00
2393dc2291 chore: 版本更新至 5.32.2
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2023-11-21 15:03:12 +08:00
cb94bc9f29 Merge branch 'hotfix/v5.32.1-991/crashes' into 'release'
fix: 修复文章详情预加载闪退,修复评论页列表刷新闪退

See merge request halo/android/assistant-android!1452
2023-11-21 15:01:45 +08:00
a60442db41 fix: 修复文章详情预加载闪退,修复评论页列表刷新闪退
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2023-11-21 14:30:35 +08:00
9691344e67 chore: 版本更新至 5.32.1
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2023-11-20 14:32:54 +08:00
41ba8c3e5a Merge branch 'fix/article_detail_culprit' into 'dev'
fix: 修复不能同时打开两个社区文章详情页面的问题

See merge request halo/android/assistant-android!1445
2023-11-17 15:11:31 +08:00
b203d3a756 fix: 修复不能同时打开两个社区文章详情页面的问题 2023-11-16 14:36:45 +08:00
28bca22d93 ci: 变更编译文件存放的 OSS 地址 2023-11-15 11:13:51 +08:00
905571a637 fix:【光环助手】单机插件跳转更新验收问题(1) https://jira.shanqu.cc/browse/GHZS-3870 2023-11-15 11:13:48 +08:00
dc9ac67e6e Merge branch 'feat/CWZS-79' into 'dev'
畅玩安装本地apk

See merge request halo/android/assistant-android!1433
2023-11-10 14:00:49 +08:00
8c1d4a3778 feat: SD卡游戏按时间排序 https://jira.shanqu.cc/browse/CWZS-79 2023-11-10 13:58:38 +08:00
7189261c01 Merge branch 'feat/build_jira_comment' into 'dev'
ci: jira 需求下补充 APK 附件评论

See merge request halo/android/assistant-android!1431
2023-11-10 11:20:53 +08:00
86c1781426 ci: jira 需求下补充 APK 附件评论 2023-11-10 11:20:31 +08:00
4812e9258b fix: 过滤gh-files目录下的apk包无法正常解析。只扫描一级目录 2023-11-10 11:10:07 +08:00
b906fe7b47 Merge branch 'feat/build_jira_comment' into 'dev'
ci: jira 需求下补充 APK 附件评论

See merge request halo/android/assistant-android!1428
2023-11-10 10:43:30 +08:00
846fd7222e ci: jira 需求下补充 APK 附件评论 2023-11-10 10:42:55 +08:00
1afabdfd94 Merge branch 'chen/202311/GHZS-3940' into 'dev'
fix:埋点问题:内容内容推荐结果点击事件上报错误 https://jira.shanqu.cc/browse/GHZS-3940

See merge request halo/android/assistant-android!1427
2023-11-10 10:37:44 +08:00
8ed2a13884 fix:埋点问题:内容内容推荐结果点击事件上报错误 https://jira.shanqu.cc/browse/GHZS-3940 2023-11-10 10:34:07 +08:00
cd13c98ac2 Merge branch 'feature-GHZS-3850' into 'dev'
fix: 【光环助手】深夜模式帖子-相关tab展示错误 https://jira.shanqu.cc/browse/GHZS-3850

See merge request halo/android/assistant-android!1422
2023-11-07 09:50:30 +08:00
2c49b468e6 fix: 【光环助手】深夜模式帖子-相关tab展示错误 https://jira.shanqu.cc/browse/GHZS-3850 2023-11-07 09:45:44 +08:00
d175e895c3 Merge branch 'feat/GHZS-3613' into 'dev'
feat: 设备ID重构 https://jira.shanqu.cc/browse/GHZS-3707

See merge request halo/android/assistant-android!1402
2023-11-06 11:45:52 +08:00
1c0af1be7d feat: 设备ID重构 https://jira.shanqu.cc/browse/GHZS-3707 2023-11-06 11:45:52 +08:00
62f5a479c9 Merge branch 'fix/INTERACT_ACROSS_USERS_crash' into 'dev'
fix: 尝试修复 INTERACT_ACROSS_USERS permission 闪退问题

See merge request halo/android/assistant-android!1420
2023-11-06 10:43:44 +08:00
a87011d5b0 Merge branch 'chen/202311/fix-search-crash-when-exchange-dark' into 'dev'
fix:社区搜索改为懒加载后,切换浅色模式crash

See merge request halo/android/assistant-android!1419
2023-11-06 10:19:29 +08:00
c6c2213a88 fix: 尝试修复 INTERACT_ACROSS_USERS permission 闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/318432/events/ff3774f050c145b2a20ec69545fa3cac/?project=22&query=level%3Afatal&sort=user&statsPeriod=14d 2023-11-06 10:13:53 +08:00
9ede98deea fix:社区搜索改为懒加载后,切换浅色模式crash 2023-11-06 10:13:37 +08:00
e46ec7c416 Merge branch 'feature-GHZS-3350-patch' into 'dev'
feat: 游戏开服/开测消息通知—客户端 https://jira.shanqu.cc/browse/GHZS-3350

See merge request halo/android/assistant-android!1418
2023-11-06 10:10:22 +08:00
d49c6bc3ca feat: 游戏开服/开测消息通知—客户端 https://jira.shanqu.cc/browse/GHZS-3350 2023-11-06 10:10:22 +08:00
2bba43cf26 Merge branch 'feat/GHZS-3837' into 'dev'
feat: 穿山甲广告替换定制版SDK

See merge request halo/android/assistant-android!1415
2023-11-03 17:25:58 +08:00
19f54bb8d2 Merge branch 'feat/upload_test_apk' into 'dev'
feat: 邮件包上传至内部测试平台

See merge request halo/android/assistant-android!1416
2023-11-03 16:20:01 +08:00
a167e7ff58 feat: 上传 APK 至内测平台 2023-11-03 16:14:30 +08:00
ddd9032dbf feat: 穿山甲广告替换定制版SDK https://jira.shanqu.cc/browse/GHZS-3836 2023-11-03 10:09:26 +08:00
1062522388 Merge branch 'feat/CWZS-79' into 'dev'
fix: ci-build error

See merge request halo/android/assistant-android!1413
2023-11-02 16:38:03 +08:00
b631c3437c fix: ci-build error 2023-11-02 16:36:37 +08:00
5de5b005bf Merge branch 'feat/CWZS-79' into 'dev'
feat: 测试版本,我的页面添加从SD卡直接安装游戏的畅玩 https://jira.shanqu.cc/browse/CWZS-135

See merge request halo/android/assistant-android!1412
2023-11-02 14:38:55 +08:00
7d99db505b fix: 依赖声明错误 2023-11-02 14:26:39 +08:00
3b3e2e572e feat: 测试版本,我的页面添加从SD卡直接安装游戏的畅玩 https://jira.shanqu.cc/browse/CWZS-135 2023-11-02 14:22:42 +08:00
56eb40740a Merge branch 'feature-GHZS-3350-new' into 'dev'
feat: 游戏开服/开测消息通知—客户端 https://jira.shanqu.cc/browse/GHZS-3350

See merge request halo/android/assistant-android!1406
2023-10-26 14:06:23 +08:00
d697bc7b8a feat: 游戏开服/开测消息通知—客户端 https://jira.shanqu.cc/browse/GHZS-3350 2023-10-26 14:06:22 +08:00
95beddc194 Merge branch 'fix/dark_mode_culprit' into 'dev'
fix: 修复由于社区首页预加载 WebView 资源导致的深色模式状态问题

See merge request halo/android/assistant-android!1405
2023-10-26 09:33:56 +08:00
5e3e4a88f5 fix: 修复由于社区首页预加载 WebView 资源导致的深色模式状态问题 2023-10-26 09:17:31 +08:00
75dabfef6b Merge branch 'fix/ad_space_gid' into 'dev'
fix: 修复app启动第一次获取广告配置请求没有带上gid的问题

See merge request halo/android/assistant-android!1403
2023-10-25 16:54:41 +08:00
e51e976385 fix: 修复app启动第一次获取广告配置请求没有带上gid的问题 2023-10-25 16:42:33 +08:00
28b9e14487 Merge branch 'feat/GHZS-3502' into 'dev'
feat: APP备案的相关调整 https://jira.shanqu.cc/browse/GHZS-3502

See merge request halo/android/assistant-android!1401
2023-10-25 10:18:36 +08:00
5ee1e823c5 Merge branch 'fix/GHZS-3691' into 'dev'
修复首页下拉弹窗&首页弹窗相关问题 https://jira.shanqu.cc/browse/GHZS-3691

See merge request halo/android/assistant-android!1400
2023-10-25 10:18:32 +08:00
11eee2eb0a 修复首页下拉弹窗&首页弹窗相关问题 https://jira.shanqu.cc/browse/GHZS-3691 2023-10-25 10:18:32 +08:00
42fa273d06 feat: APP备案的相关调整 https://jira.shanqu.cc/browse/GHZS-3502 2023-10-25 09:44:55 +08:00
69dcd407b1 Merge branch 'feat/GHZS-3342' into 'dev'
feat: 游戏下载按钮合并 https://jira.shanqu.cc/browse/GHZS-3342

See merge request halo/android/assistant-android!1368
2023-10-25 09:34:43 +08:00
66722a313f Merge branch 'feat/GHZS-3446' into 'dev'
feat: 广告位管理相关优化—客户端 https://jira.shanqu.cc/browse/GHZS-3446

See merge request halo/android/assistant-android!1399
2023-10-24 17:28:58 +08:00
81b0404999 feat: 广告位管理相关优化—客户端 https://jira.shanqu.cc/browse/GHZS-3446 2023-10-24 17:28:58 +08:00
79dadfeae6 Merge branch 'fix/game_library_crash' into 'dev'
fix: 修复游戏库点击消息中心出现的闪退问题

See merge request halo/android/assistant-android!1398
2023-10-24 15:55:14 +08:00
601733f257 fix: 修复游戏库点击消息中心出现的闪退问题 2023-10-24 15:31:42 +08:00
48a6bd0d2e feat: 游戏下载按钮合并 https://jira.shanqu.cc/browse/GHZS-3342 2023-10-24 14:21:18 +08:00
dfb89980fe Merge branch 'chen/202309/feature-CWZS-110' into 'dev'
云存档优化

See merge request halo/android/assistant-android!1397
2023-10-23 14:58:19 +08:00
e7d4c598a3 feat:云存档管理相关优化—客户端 https://jira.shanqu.cc/browse/CWZS-110 2023-10-23 14:58:19 +08:00
d6d0bea491 Merge branch 'fix/GHZS-3744' into 'dev'
fix: 编辑器图片格式兼容问题 https://jira.shanqu.cc/browse/GHZS-3744

See merge request halo/android/assistant-android!1394
2023-10-20 15:04:39 +08:00
1f05d6e0ba Merge remote-tracking branch 'origin/release' into dev
# Conflicts:
#	dependencies.gradle
2023-10-20 14:24:24 +08:00
c995846db7 fix: 关编辑器图片格式兼容问题 https://jira.shanqu.cc/browse/GHZS-3744 2023-10-20 11:11:07 +08:00
964b2afaae chore: 版本更新至 5.31.3 2023-10-19 16:29:57 +08:00
7cd4a45915 Merge branch 'feat/GHZS-3682' into 'release'
feat: 关于畅玩游戏在安卓8及以下系统的实名问题 https://jira.shanqu.cc/browse/GHZS-3704

See merge request halo/android/assistant-android!1393
2023-10-19 16:28:43 +08:00
707361e660 feat: 关于畅玩游戏在安卓8及以下系统的实名问题 https://jira.shanqu.cc/browse/GHZS-3704 2023-10-19 16:23:34 +08:00
b427418ec6 Merge branch 'chen/202309/GHZS-3477' into 'dev' 2023-10-19 15:19:16 +08:00
580a00e1a9 feat:【光环助手】搜索业务埋点需求 https://jira.shanqu.cc/browse/GHZS-3477 2023-10-19 15:19:15 +08:00
1e13ae4815 Merge branch 'feat/GHZS-3675' into 'release'
feat: V5.31.0发布前调整

See merge request halo/android/assistant-android!1388
2023-10-18 17:10:05 +08:00
e18aeb92dd feat: V5.31.0发布前调整 https://jira.shanqu.cc/browse/GHZS-3675 2023-10-18 17:10:05 +08:00
24aaeeee7f Merge branch 'fix-GHZS-dialog-error' into 'release'
fix: 修复DownloadDialog点击继续下载没有反应的问题

See merge request halo/android/assistant-android!1387
2023-10-18 13:58:06 +08:00
a70a397199 fix: 修复DownloadDialog点击继续下载没有反应的问题 2023-10-18 13:58:06 +08:00
7f4d06fbe1 Merge branch 'feat/GHZS-3638' into 'release'
feat: 穿山甲广告SDK更换新版本 https://jira.shanqu.cc/browse/GHZS-3686

See merge request halo/android/assistant-android!1386
2023-10-18 10:02:09 +08:00
690ca33702 Merge branch 'feat/GHZS-3467' into 'dev'
feat: 用户认证优化—客户端 https://jira.shanqu.cc/browse/GHZS-3467

See merge request halo/android/assistant-android!1385
2023-10-17 17:31:06 +08:00
cf6a80dd0d feat: 用户认证优化—客户端 https://jira.shanqu.cc/browse/GHZS-3467 2023-10-17 17:31:06 +08:00
c409b755cf Merge branch 'feat/GHZS-3403' into 'dev'
feat: 首页底部tab第4位修改为可配置—客户端 https://jira.shanqu.cc/browse/GHZS-3403

See merge request halo/android/assistant-android!1384
2023-10-17 11:45:14 +08:00
0399a0cc91 feat: 首页底部tab第4位修改为可配置—客户端 https://jira.shanqu.cc/browse/GHZS-3403 2023-10-17 11:45:14 +08:00
c28d6f3080 feat: 穿山甲广告SDK更换新版本 https://jira.shanqu.cc/browse/GHZS-3686 2023-10-16 16:35:59 +08:00
56501f9f33 Merge branch 'feat/GHZS-3397' into 'dev'
feat: 游戏单功能优化(第二期)—客户端 https://jira.shanqu.cc/browse/GHZS-3397

See merge request halo/android/assistant-android!1383
2023-10-13 14:20:25 +08:00
ebcf2aaa9e feat: 游戏单功能优化(第二期)—客户端 https://jira.shanqu.cc/browse/GHZS-3397 2023-10-13 14:20:25 +08:00
0f9f3dc073 Merge branch 'feature-GHZS-article-detail-remove-dev-cache' into 'dev'
feat: halo_test_app.js、halo_test_app.css的预缓存移除

See merge request halo/android/assistant-android!1382
2023-10-12 15:09:53 +08:00
8c92da2ceb feat: halo_test_app.js、halo_test_app.css的预缓存移除 2023-10-12 15:09:53 +08:00
671c59a9de Merge branch 'feature-GHZS-article-detail-modification' into 'dev'
feat: 论坛文章详情WebView预加载

See merge request halo/android/assistant-android!1381
2023-10-12 13:45:11 +08:00
adcb8a4693 feat: 论坛文章详情WebView预加载 2023-10-12 13:45:11 +08:00
95d87858f1 Merge branch 'fix/home_page_memory_leak' into 'dev'
fix: 修复首页悬浮窗和AudioManager造成的内存泄漏问题

See merge request halo/android/assistant-android!1380
2023-10-11 11:23:13 +08:00
0a463b0ddd Merge branch 'chen/202310/GHZS-3652' into 'dev'
fix:修复光环首页部分数据被多线程操作的问题 https://jira.shanqu.cc/browse/GHZS-3652

See merge request halo/android/assistant-android!1379
2023-10-11 11:13:27 +08:00
2da4230d8c fix:修复光环首页部分数据被多线程操作的问题 https://jira.shanqu.cc/browse/GHZS-3652 2023-10-11 11:07:15 +08:00
b00fda2289 fix: 修复首页悬浮窗和AudioManager造成的内存泄漏问题 2023-10-11 11:06:29 +08:00
86790e7b69 Merge branch 'fix/GHZS-3596' into 'dev'
fix: 【光环助手】APP内图片显示问题(1010测试) https://jira.shanqu.cc/browse/GHZS-3596

See merge request halo/android/assistant-android!1378
2023-10-10 17:01:43 +08:00
80ea7303f8 fix: 【光环助手】APP内图片显示问题(1010测试) https://jira.shanqu.cc/browse/GHZS-3596 2023-10-10 16:58:48 +08:00
700831ba26 Merge branch 'fix/GHZS-3596' into 'dev'
fix: 【光环助手】APP内图片显示问题(1010测试) https://jira.shanqu.cc/browse/GHZS-3596

See merge request halo/android/assistant-android!1377
2023-10-10 15:27:00 +08:00
e35950ad89 fix: 【光环助手】APP内图片显示问题(1010测试) https://jira.shanqu.cc/browse/GHZS-3596 2023-10-10 15:15:56 +08:00
7be72e76f2 Merge branch 'feature-GHZS-sentry-335870' into 'release'
fix: Sentry关于神策埋点上报导致的空指针异常的BUG

See merge request halo/android/assistant-android!1376
2023-10-10 11:53:39 +08:00
6d5b0eb1e8 fix: Sentry关于神策埋点上报导致的空指针异常的BUG 2023-10-10 11:53:39 +08:00
505 changed files with 16581 additions and 5426 deletions

View File

@ -61,7 +61,7 @@ android_build:
script:
- export GRADLE_USER_HOME=/home/gitlab-runner/ci-build-cache/$CI_PROJECT_PATH/.gradle
- chmod +x ./gradlew
- ./scripts/jenkins_build.sh -c
- ./scripts/jenkins_build.sh $CI_COMMIT_REF_NAME $BEFORE_COMMIT_SHA $CI_COMMIT_SHA
#设置打包后的产物用于job之间共享
artifacts:
paths:
@ -124,7 +124,7 @@ send_sonar_report:
oss-upload&send-email:
tags:
- rancher-k8s
- sysadm-devops
stage: oss-upload&send-email
image: hub.shanqu.cc/devops/android-apk-oss-upload:latest
variables:
@ -132,9 +132,9 @@ oss-upload&send-email:
VAULT_ADDR: https://vault.shanqu.cc # 固定值
VAULT_SECRET_PATH: prod/devops/android-apk-oss-upload # 固定值
VAULT_ROLE: android-apk-oss-upload # 固定值
ENDPOINT: "oss-cn-shenzhen-internal.aliyuncs.com" # 固定值
BUCKET: "shanqu" # 固定值
FILE_PATH: "app/build/tmp/" # APK 存放路径
ENDPOINT: "tos-cn-guangzhou.ivolces.com" # 固定值
BUCKET: "sysadm-public" # 固定值
FILE_PATH: "app/build/tmp/" # APK 存放路径
Email_To_List: $EMAIL_TO_LIST # 邮件接受人列表
Email_Title: "光环助手 $CI_COMMIT_BRANCH" # 邮件标题
PIPELINE_ID: $CI_PIPELINE_ID # 流水线id
@ -149,7 +149,7 @@ oss-upload&send-email:
### 开启上传 ###
- /usr/local/bin/python /upload.py
### 发送邮件
- /usr/local/bin/python /ci-android-mail.py
- /usr/local/bin/python /ci-android-mail-jira-comment.py
only:
- dev
- dev-5.32.0

3
.gitmodules vendored
View File

@ -11,3 +11,6 @@
[submodule "ndownload"]
path = ndownload
url = ../../../android/ndownload.git
[submodule "vasdk"]
path = vasdk
url = ../../../sdg/android/vasdk.git

View File

@ -73,7 +73,7 @@ android {
versionName rootProject.ext.versionName
applicationId rootProject.ext.applicationId
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt'
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt', rootProject.ext.va_proguard_rules
String CORE_EVENT_GAME_CATEGORY = ""
@ -160,6 +160,9 @@ android {
flavorDimensions("env")
sourceSets {
main {
assets.srcDir("${rootProject.buildDir}/plugin")
}
publish {
java.srcDirs = ['src/main/java', "src/default/java"]
}
@ -181,14 +184,16 @@ android {
// internal 内部测试包使用的 flavor接口包含包括测试和正式环境
internal {
dimension "env"
versionNameSuffix "-debug"
// blame_yangfei: test script lines
//versionNameSuffix "-debug"
buildConfigField "String", "DEV_API_HOST", "\"${DEV_API_HOST}\""
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_DEV_API_HOST}\""
buildConfigField "String", "DEV_VAPI_HOST", "\"${DEV_VAPI_HOST}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${DEV_QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${DEV_QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "CSJ_APPID", "\"${DEV_CSJ_APPID}\""
buildConfigField "String", "DEV_CSJ_APPID", "\"${DEV_CSJ_APPID}\""
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
}
// publish 发布时候使用的 flavor接口仅包含正式环境
@ -200,6 +205,7 @@ android {
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
}
@ -211,6 +217,7 @@ android {
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
manifestPlaceholders.put("APPLOG_SCHEME", "rangersapplog.byAx6uYt".toLowerCase())
@ -224,6 +231,7 @@ android {
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
}
@ -235,6 +243,7 @@ android {
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
}
}
@ -320,9 +329,9 @@ dependencies {
kapt "com.alibaba:arouter-compiler:$arouterVersion"
implementation project(':ndownload')
implementation project(':vspace-bridge:vspace')
implementation project(':vspace-bridge')
implementation (project(':module_common')) {
implementation(project(':module_common')) {
exclude group: 'androidx.swiperefreshlayout'
}
implementation(project(':module_login')) {
@ -359,6 +368,14 @@ dependencies {
implementation(project(':feature:qq_game')) {
exclude group: 'androidx.swiperefreshlayout'
}
internalImplementation(project(':module_internal_test'))
implementation(project(':va-main')) {
exclude group: 'androidx.swiperefreshlayout'
}
debugImplementation "com.bytedance.tools.codelocator:codelocator-core:2.0.3"
compileOnly project(":va-core")
compileOnly project(":va-plugin-host-lib")
implementation project(":va-plugin-host")
}
File propFile = file('sign.properties')
@ -600,4 +617,14 @@ project.afterEvaluate {
}
}
}
}
def copyArtifacts = tasks.create("copyArtifacts", Copy) {
from new File(rootProject.buildDir, "artifacts.zip")
into new File(rootProject.buildDir, "plugin")
}.dependsOn(":va-plugin-floating:generateDebugArtifacts")
tasks.whenTaskAdded { Task task ->
if (task.name == "preInternalDebugBuild" || task.name == "prePublishDebugBuild") {
task.dependsOn(copyArtifacts)
}
}

View File

@ -92,3 +92,7 @@
native <methods>;
}
-keepclassmembernames class com.contrarywind.view.WheelView {
private int itemsVisible;
}

View File

@ -0,0 +1,32 @@
package com.gh.vspace
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.Keep
import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.LayoutPersonalOtherItemBinding
import com.gh.vspace.installexternalgames.InstallExternalGameActivity
@Keep
class ExternalGameUsage : IExternalGamesUsage {
override fun addInstallExternalGameButton(viewParent: ViewGroup) {
val context = viewParent.context
viewParent.findViewById<View>(R.id.install_game_from_external) ?: run {
val binding = LayoutPersonalOtherItemBinding.inflate(LayoutInflater.from(context)).apply {
root.id = R.id.install_game_from_external
titleTv.text = context.getString(R.string.title_install_external_game)
iconIv.setImageResource(R.drawable.ic_personal_my_game)
root.setOnClickListener {
VHelper.connectService {
context.startActivity(
InstallExternalGameActivity.getIntent(context)
.apply { flags = flags or Intent.FLAG_ACTIVITY_NEW_TASK })
}
}
}
viewParent.addView(binding.root, 0)
}
}
}

View File

@ -0,0 +1,5 @@
package com.gh.vspace.installexternalgames;
public class Constants {
public static final String TAG = "从SD卡安装";
}

View File

@ -0,0 +1,47 @@
package com.gh.vspace.installexternalgames
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toBinding
class ExternalGameAdapter(private val games: List<ExternalGameUiState>, private val onItemClickListener: OnItemClickListener) :
RecyclerView.Adapter<ExternalGameViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExternalGameViewHolder {
return ExternalGameViewHolder(parent.toBinding())
}
override fun getItemCount(): Int {
return games.size
}
override fun onBindViewHolder(holder: ExternalGameViewHolder, position: Int) {
val item = games[position]
holder.apkInfo.text = item.externalGameEntity.let { item ->
"""
应用程序名:${item.appName}
版本号:${item.apkVersion}
包名: ${item.apkPackageName}
路径:${item.apkPath}
""".trimIndent()
}
holder.install.goneIf(item.isInstalled) {
holder.install.setOnClickListener {
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_INSTALL)
}
}
holder.uninstall.goneIf(!item.isInstalled) {
holder.uninstall.setOnClickListener {
onItemClickListener.onItemClick(
item,
OnItemClickListener.ClickType.CLICK_UNINSTALL
)
}
}
holder.start.goneIf(!item.isInstalled) {
holder.start.setOnClickListener {
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_START)
}
}
}
}

View File

@ -0,0 +1,11 @@
package com.gh.vspace.installexternalgames
data class ExternalGameEntity(
val cpuAbi: Set<String>,
val apkPath: String,
val apkFileName: String,
val appName: String,
val apkVersion: String,
val apkPackageName: String,
val lastModified: Long,
)

View File

@ -0,0 +1,6 @@
package com.gh.vspace.installexternalgames
data class ExternalGameUiState(
val externalGameEntity: ExternalGameEntity,
val isInstalled: Boolean
)

View File

@ -0,0 +1,11 @@
package com.gh.vspace.installexternalgames
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.databinding.LayoutExternalGameItemBinding
class ExternalGameViewHolder(binding: LayoutExternalGameItemBinding) : RecyclerView.ViewHolder(binding.root) {
val apkInfo = binding.apkFileInfo
val install = binding.btnInstall
val uninstall = binding.btnUninstall
val start = binding.btnStart
}

View File

@ -0,0 +1,14 @@
package com.gh.vspace.installexternalgames
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.gh.gamecenter.common.base.activity.ToolBarActivity
class InstallExternalGameActivity : ToolBarActivity() {
companion object {
fun getIntent(context: Context): Intent {
return getTargetIntent(context, InstallExternalGameActivity::class.java, InstallExternalGameFragment::class.java, Bundle())
}
}
}

View File

@ -0,0 +1,153 @@
package com.gh.vspace.installexternalgames
import android.app.Dialog
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import com.gh.common.util.DialogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.common.view.divider.HorizontalDividerItemDecoration
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.databinding.FragmentInstallExternalGamesBinding
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lg.vspace.VirtualAppManager
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
private val mViewModel: InstallExternalGameViewModel by lazy { viewModelProvider() }
private lateinit var mBinding: FragmentInstallExternalGamesBinding
private val games = mutableListOf<ExternalGameUiState>()
private var adapter = ExternalGameAdapter(games, this)
private var uninstallDisposable: Disposable? = null
override fun getLayoutId() = 0
override fun getInflatedLayout() =
FragmentInstallExternalGamesBinding.inflate(layoutInflater).apply { mBinding = this }.root
private lateinit var dialog: Dialog
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setNavigationTitle(getString(com.gh.gamecenter.R.string.title_install_external_game))
initView()
mViewModel.gamesList.observe(this) {
if (dialog.isShowing) {
dialog.dismiss()
}
games.clear()
games.addAll(
it.map {
ExternalGameUiState(it, VHelper.isInstalled(it.apkPackageName))
}
)
adapter.notifyDataSetChanged()
}
mViewModel.scanPaths()
}
private fun initView() {
dialog = DialogUtils.showWaitDialog(requireContext(), "")
mBinding.externalGamesList.let {
it.adapter = adapter
it.layoutManager = LinearLayoutManager(requireContext())
val itemDecoration = HorizontalDividerItemDecoration.Builder(requireContext())
.size(2F.dip2px())
.color(R.color.divider.toColor(requireContext()))
.build()
if (it.itemDecorationCount != 0) {
it.removeItemDecorationAt(0)
}
it.addItemDecoration(itemDecoration)
}
}
override fun onDestroy() {
super.onDestroy()
if (dialog.isShowing) {
dialog.dismiss()
}
if (uninstallDisposable?.isDisposed != true) {
uninstallDisposable?.dispose()
}
}
override fun onItemClick(externalGameUiState: ExternalGameUiState, clickType: OnItemClickListener.ClickType) {
when (clickType) {
OnItemClickListener.ClickType.CLICK_INSTALL -> {
install(externalGameUiState)
}
OnItemClickListener.ClickType.CLICK_UNINSTALL -> {
uninstall(externalGameUiState)
}
OnItemClickListener.ClickType.CLICK_START -> {
start(externalGameUiState)
}
}
}
private fun install(externalGameUiState: ExternalGameUiState) {
val bit =
externalGameUiState.externalGameEntity.cpuAbi.let { if (it.size == 1 && it.contains("armeabi-v7a")) "32" else "64" }
if (VHelper.showDialogIfVSpaceIsNeeded(
requireContext(),
"",
externalGameUiState.externalGameEntity.appName,
"",
bit = bit
)
) return
dialog.show()
externalGameUiState.externalGameEntity.let {
val intent = VirtualAppManager.getInstallIntent(context, it.apkPath, it.apkPackageName)
requireActivity().startActivity(intent)
}
}
private fun uninstall(externalGameUiState: ExternalGameUiState) {
dialog.show()
uninstallDisposable = Single.create<Void> {
VHelper.uninstall(externalGameUiState.externalGameEntity.apkPackageName)
}.subscribeOn(Schedulers.from(AppExecutor.lightWeightIoExecutor)).observeOn(AndroidSchedulers.mainThread())
.subscribe { t1, t2 ->
if (dialog.isShowing) {
dialog.dismiss()
}
}
}
private fun start(externalGameUiState: ExternalGameUiState) {
val intent = VirtualAppManager.get().getStartGameIntent(
externalGameUiState.externalGameEntity.apkPackageName,
"",
externalGameUiState.externalGameEntity.appName,
"",
MetaUtil.getBase64EncodedAndroidId(),
HaloApp.getInstance().gid,
com.gh.gamecenter.BuildConfig.VERSION_NAME,
HaloApp.getInstance().channel,
"",
""
)
requireActivity().startActivity(intent)
}
}

View File

@ -0,0 +1,64 @@
package com.gh.vspace.installexternalgames
import android.app.Application
import android.content.pm.PackageManager
import android.os.Environment
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.core.runOnIoThread
import com.gh.vspace.VHelper
import com.lg.vspace.helper.compat.NativeLibraryHelperCompat
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
class InstallExternalGameViewModel(application: Application) : AndroidViewModel(application) {
private val _gamesList = MutableLiveData<List<ExternalGameEntity>>(listOf())
val gamesList: LiveData<List<ExternalGameEntity>> = _gamesList
private val pkgManger = getApplication<Application>().packageManager
private var disposable: Disposable = VHelper.callSite.observeOn(AndroidSchedulers.mainThread()).subscribe {
scanPaths()
}
fun scanPaths() {
runOnIoThread {
_gamesList.postValue(Environment.getExternalStorageDirectory().walk().maxDepth(1)
.filter { it.isHidden.not() }
.filter { it.isFile }
.onEach {
Utils.log(Constants.TAG, "获得文件: ${it.name}")
}
.filter { it.extension == "apk" }
.map {
val packageInfo = pkgManger.getPackageArchiveInfo(
it.absolutePath,
PackageManager.GET_META_DATA or PackageManager.GET_ACTIVITIES
)
packageInfo?.let { packageInfo ->
val applicationInfo = packageInfo.applicationInfo
applicationInfo.publicSourceDir = it.absolutePath
applicationInfo.sourceDir = it.absolutePath
ExternalGameEntity(
cpuAbi = NativeLibraryHelperCompat.getPackageAbiList(it.absolutePath),
apkPath = it.absolutePath,
apkFileName = it.name,
apkPackageName = packageInfo.packageName,
apkVersion = packageInfo.versionName,
appName = pkgManger.getApplicationLabel(applicationInfo).toString(),
lastModified = it.lastModified()
)
}
}.filterNotNull()
.toList().sortedByDescending { it.lastModified }
)
}
}
override fun onCleared() {
super.onCleared()
disposable.dispose()
}
}

View File

@ -0,0 +1,11 @@
package com.gh.vspace.installexternalgames
interface OnItemClickListener {
enum class ClickType {
CLICK_INSTALL, CLICK_UNINSTALL, CLICK_START
}
fun onItemClick(externalGameUiState: ExternalGameUiState, clickType: ClickType)
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/external_games_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/apk_file_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
tools:text="文件名:\n路径" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_install"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_install"
android:visibility="gone"
tools:visibility="visible" />
<Button
android:id="@+id/btn_uninstall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_uninstall"
android:visibility="gone"
tools:visibility="visible" />
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_start"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="install_game_from_external" type="id" />
</resources>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title_install_external_game">从SD卡安装</string>
<string name="text_install">安装</string>
<string name="text_uninstall">卸载</string>
<string name="text_start">启动</string>
</resources>

View File

@ -78,11 +78,36 @@
androidx.constraintlayout.compose,
androidx.compose.ui.test.manifest,
com.bytedance.sdk.openadsdk,
com.bykv.vk.openvk,
com.bytedance.tools,
androidx.compose.ui.tooling.preview,
com.tencent.qqmini,
com.tencent.qqmini.minigame.external,
com.tencent.qqmini.minigame.opensdk,
com.tencent.qqmini.union.ad" />
com.tencent.qqmini.union.ad,
com.lg.vspace,
io.lg.va.common,
com.va.floating,
com.lg.cloud,
com.lg.archive,
com.lg.vclient,
com.va.realname,
com.lg.vspace.flavor,
com.lg.update,
com.lg.login,
com.lg.accelerator,
com.lody.virtual,
com.lg.core,
com.lg.ads,
com.lg.common,
com.lg.vspace.network,
com.lody.virtual.lib.res,
com.va.host,
com.lg.vspace.plugin.host,
com.lg.plugin.constant,
com.bytedance.tools.codelocator,
org.chickenhook.restrictionbypass,
com.lody.virtual.sandhook,com.lg.vspace.common" />
<!-- 去掉 SDK 一些流氓权限 -->
<uses-permission
@ -97,6 +122,9 @@
android:name="android.permission.GET_TASKS"
tools:node="remove" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
tools:node="remove"/>
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
@ -474,6 +502,14 @@
android:name="com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity"
android:screenOrientation="portrait" />
<activity
android:name=".gamedetail.fuli.kaifu.ServersCalendarManagementActivity"
android:screenOrientation="portrait" />
<activity
android:name=".gamedetail.fuli.kaifu.ServersSubscribedGameListActivity"
android:screenOrientation="portrait" />
<activity
android:name=".qa.answer.draft.AnswerDraftActivity"
android:screenOrientation="portrait" />
@ -754,7 +790,11 @@
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qgame.QGameSubjectActivity"
android:name="com.gh.gamecenter.gamecollection.hotlist.GameCollectionListDetailActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.UserAuthActivity"
android:screenOrientation="portrait" />
@ -768,7 +808,8 @@
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
android:grantUriPermissions="true"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
@ -812,6 +853,8 @@
<!-- tools:node="remove" />-->
<!-- </provider>-->
<service android:name = "com.gh.gamecenter.install.InstallService" />
<receiver
android:name="com.gh.gamecenter.receiver.DownloadReceiver"
android:exported="false">

File diff suppressed because one or more lines are too long

View File

@ -65,7 +65,7 @@ object AdDelegateHelper {
private const val AD_SDK_CSJ = "穿山甲"
private const val AD_SDK_BEIZI = "倍孜"
private const val AD_TYPE_SDK = "third_party_ads" // 第三方 SDK 广告
const val AD_TYPE_SDK = "third_party_ads" // 第三方 SDK 广告
private const val KEY_CACHE_CONFIG = "cache_config" // 放在 SP 里的广告缓存(避免接口加载问题)
@ -73,6 +73,8 @@ object AdDelegateHelper {
HaloApp.getInstance().getSharedPreferences("AdConfig", Context.MODE_PRIVATE)
}
var gameSearchKeyword = ""
fun initAdSdk(context: Context) {
// 初始化 Beizi
if (mBeiziAdImpl == null) {
@ -85,7 +87,8 @@ object AdDelegateHelper {
if (mCsjAdImpl == null) {
mCsjAdImpl =
ARouter.getInstance().build(RouteConsts.provider.csjAd).navigation() as? ICsjAdProvider
mCsjAdImpl?.initSDK(context, BuildConfig.CSJ_APPID, HaloApp.getInstance().oaid)
val csjAppId = if (EnvHelper.isDevEnv) BuildConfig.DEV_CSJ_APPID else BuildConfig.CSJ_APPID
mCsjAdImpl?.initSDK(context, csjAppId, HaloApp.getInstance().oaid)
// 监听亮色/暗色模式切换
DarkModeUtils.registerModeChangeListener {
val topActivity = CurrentActivityHolder.getCurrentActivity() ?: return@registerModeChangeListener
@ -98,19 +101,21 @@ object AdDelegateHelper {
* 请求接口获取广告相关配置
*/
@SuppressLint("CheckResult")
fun requestAdConfig(isFromRetry: Boolean) {
fun requestAdConfig(isFromRetry: Boolean, keyword: String = "", callback: (() -> Unit)? = null) {
// mAdConfigList 不为空不需要重试
if (isFromRetry && mAdConfigList != null) {
return
}
val paramsMap = if (keyword.isNotEmpty()) mapOf("keyword" to keyword) else mapOf()
RetrofitManager.getInstance()
.newApi
.adConfig
.getAdConfig(paramsMap)
.subscribeOn(Schedulers.io())
.subscribe(object : BiResponse<List<AdConfig>>() {
override fun onSuccess(data: List<AdConfig>) {
gameSearchKeyword = keyword
handleAdConfig(data)
callback?.invoke()
// 缓存数据到 SP 供接口请求失败用
SPUtils.setString(mAdConfigSp, KEY_CACHE_CONFIG, data.toJson())
@ -124,6 +129,8 @@ object AdDelegateHelper {
if (cachedConfig != null) {
handleAdConfig(cachedConfig)
}
callback?.invoke()
}
})
}
@ -146,10 +153,18 @@ object AdDelegateHelper {
* 处理广告配置
*/
fun handleAdConfig(configList: List<AdConfig>) {
mGameSearchAdList.clear()
mSplashAd = null
mDownloadManagerAd = null
mVGameLaunchAd = null
for (config in configList) {
// 处理返回的数据
when (config.location) {
"halo_launch" -> mSplashAd = config
"halo_launch" -> {
config.ownerAd?.startAd?.let { it.id = config.ownerAd.id }
mSplashAd = config
}
"download_manager" -> mDownloadManagerAd = config
"game_search" -> config.let { mGameSearchAdList.add(it) }
"helper_launch" -> mVGameLaunchAd = config
@ -196,7 +211,12 @@ object AdDelegateHelper {
} else {
if (mSplashAd?.displayRule?.onFailedAction == "show") {
sdkStartAdContainer.visibility = View.GONE
requestStandardSplashAd(mSplashAd!!.ownerAd, startAdContainer, handler, hideCallback)
requestStandardSplashAd(
mSplashAd!!.ownerAd?.startAd,
startAdContainer,
handler,
hideCallback
)
} else {
hideCallback.invoke()
}
@ -226,7 +246,7 @@ object AdDelegateHelper {
)
}
} else {
requestStandardSplashAd(mSplashAd!!.ownerAd, startAdContainer, handler, hideCallback)
requestStandardSplashAd(mSplashAd!!.ownerAd?.startAd, startAdContainer, handler, hideCallback)
}
}
}
@ -332,7 +352,9 @@ object AdDelegateHelper {
val jumpBtn: View = startAdContainer.findViewById(R.id.jumpBtn)
val jumpDetailBtn: TextView = startAdContainer.findViewById(R.id.jumpDetailBtn)
val adImage: SimpleDraweeView = startAdContainer.findViewById(R.id.adImage)
val icpContainer: View? = startAdContainer.findViewById(R.id.startAdIcpContainer)
startAdContainer.visibility = View.VISIBLE
icpContainer?.visibility = View.VISIBLE
jumpDetailBtn.text = ad.desc
jumpDetailBtn.setDrawableEnd(
AppCompatResources.getDrawable(
@ -376,9 +398,9 @@ object AdDelegateHelper {
}
/**
* 获取信息流广告
* 获取第三方信息流广告
*/
fun requestFlowAd(
fun requestThirdPartyFlowAd(
fragment: Fragment,
slotId: String,
adContainerView: ViewGroup,
@ -389,9 +411,9 @@ object AdDelegateHelper {
}
/**
* 获取 Banner 广告
* 获取第三方 Banner 广告
*/
fun requestBannerAd(
fun requestThirdPartyBannerAd(
fragment: Fragment,
containerView: ViewGroup,
ad: AdConfig.ThirdPartyAd,

View File

@ -28,6 +28,7 @@ import com.gh.gamecenter.retrofit.service.ApiService
import com.gh.gamecenter.video.upload.OnUploadListener
import com.gh.gamecenter.video.upload.UploadManager
import com.google.gson.JsonObject
import com.lightgame.download.FileUtils
import com.lightgame.utils.Utils
import com.zhihu.matisse.Matisse
import com.zhihu.matisse.internal.utils.PathUtils
@ -38,6 +39,10 @@ import okhttp3.ResponseBody
import retrofit2.HttpException
import java.io.File
import java.io.FileOutputStream
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.collections.LinkedHashMap
import kotlin.collections.set
// TODO: 移动到module_bbs模块
@ -124,8 +129,17 @@ abstract class BaseRichEditorViewModel(application: Application) : AndroidViewMo
}
val map = LinkedHashMap<String, String>()
for (key in imageUrlMap.keys) {
map[MD5Utils.getUrlMD5(key)] = FILE_HOST + key.decodeURI()
mapImages[TextUtils.htmlEncode(key).decodeURI()] = imageUrlMap[key] ?: ""
val localFileUri = FILE_HOST + key.decodeURI()
// 文件格式为 HEIC 时,使用经 OSS 转码的图片作为预览图片
if (FileUtils.getFileMimeType(getApplication(), key.decodeURI())?.lowercase(Locale.CHINA)?.contains("heic") == true) {
val transformedImgUrl = ImageUtils.getTransformedUrl(imageUrlMap[key], 5000) ?: ""
map[MD5Utils.getUrlMD5(key)] = transformedImgUrl
mapImages[transformedImgUrl.decodeURI()] = imageUrlMap[key] ?: ""
} else {
map[MD5Utils.getUrlMD5(key)] = localFileUri
mapImages[TextUtils.htmlEncode(key).decodeURI()] = imageUrlMap[key] ?: ""
}
}
chooseImagesUploadSuccess.value = map
}

View File

@ -13,8 +13,10 @@ import com.gh.gamecenter.SplashScreenActivity
import com.gh.gamecenter.authorization.AuthorizationActivity
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.utils.PackageFlavorHelper
import com.gh.gamecenter.login.view.LoginActivity
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lg.vspace.ui.launcher.LaunchActivity
// TODO移动到对应的模块
class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
@ -56,6 +58,8 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
}
if (activity is AppCompatActivity
&& activity !is LaunchActivity
&& activity !is LoginActivity
&& activity !is SplashScreenActivity
&& activity !is SkipActivity
&& activity !is AuthorizationActivity

View File

@ -69,9 +69,14 @@ class DefaultJsApi(
val entrance: String = "",
private var mFragment: Fragment? = null,
private var mBbsId: String? = "",
private var mOriginUrl: String?= "",
private var mOriginUrl: String? = "",
private val mForumName: String? = ""
) {
companion object {
private const val SOURCE_ENTRANCE = "webView"
}
private var mLoginHandler: CompletionHandler<Any>? = null
private var mDownloadWatcher: DataWatcher? = null // 下载观察者
private var mDownloadUrlSet: HashSet<String>? = null // 下载的 url 集合
@ -230,7 +235,14 @@ class DefaultJsApi(
val context = CurrentActivityHolder.getCurrentActivity()
context?.startActivity(ImageViewerActivity.getIntent(context, imageEvent.imageList, imageEvent.position, "浏览器"))
context?.startActivity(
ImageViewerActivity.getIntent(
context,
imageEvent.imageList,
imageEvent.position,
"浏览器"
)
)
}
@JavascriptInterface
@ -279,11 +291,18 @@ class DefaultJsApi(
/**
* 打开论坛搜索页
* 如果用户是从 webView跳转到论坛搜索页则sourceEntrance为空
*/
@JavascriptInterface
fun openForumSearch(msg: Any) {
runOnUiThread {
DirectUtils.directToForumOrUserSearch(context, mBbsId ?: "", entrance.ifBlank { "内部网页" })
DirectUtils.directToForumOrUserSearch(
context,
mBbsId ?: "",
entrance.ifBlank { "内部网页" },
SOURCE_ENTRANCE,
mForumName ?: ""
)
}
}
@ -385,7 +404,7 @@ class DefaultJsApi(
@JavascriptInterface
fun showQaFeedbackDialog(msg: Any) {
val mHelpAndFeedbackHelp =
val mHelpAndFeedbackHelp =
ARouter.getInstance().build(RouteConsts.provider.helpAndFeedback).navigation() as? IHelpAndFeedbackProvider
mHelpAndFeedbackHelp?.showQaFeedbackDialogFragment(context as AppCompatActivity, msg.toString())
}
@ -531,10 +550,9 @@ class DefaultJsApi(
@JavascriptInterface
fun installDownloadedGame(event: Any) {
val url = event.toString()
val vUrl = VHelper.getVUrl(url)
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(url, null, false)
?: DownloadManager.getInstance().getDownloadEntitySnapshot(vUrl, null, false)
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(url, null)
?: DownloadManager.getInstance().getDownloadEntitySnapshot(url, null)
NewFlatLogUtils.logGameInstall(
gameId = downloadEntity?.gameId ?: "",
@ -549,7 +567,7 @@ class DefaultJsApi(
)
downloadEntity?.let {
PackageInstaller.install(context, it, showUnzipToast = false)
PackageInstaller.install(context, it, showUnzipToast = false, ignoreAsVGame = false)
}
}
@ -750,6 +768,7 @@ class DefaultJsApi(
var status: String = "" // DOWNLOADING, PAUSED, DOWNLOADED, ERROR, UNKNOWN
) {
companion object {
fun fromDownloadEntity(downloadEntity: DownloadEntity): SimpleDownloadEntity {
val status: String = when (downloadEntity.status) {
add,

View File

@ -1,23 +1,21 @@
package com.gh.common.chain
import android.content.Context
import com.gh.common.xapk.XapkInstaller
import com.gh.download.server.BrowserInstallHelper
import com.gh.gamecenter.core.utils.EmptyCallback
import com.gh.gamecenter.feature.entity.GameEntity
class BrowserInstallHandler : ChainHandler() {
class BrowserInstallHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
BrowserInstallHelper.showBrowserInstallHintDialog(
context,
gameEntity,
gameEntity.isVGame() || gameEntity.isSplitXApk()
asVGame || gameEntity.isSplitXApk()
) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
}

View File

@ -4,14 +4,14 @@ import android.content.Context
import com.gh.common.dialog.CertificationDialog
import com.gh.gamecenter.feature.entity.GameEntity
class CertificationHandler : ChainHandler() {
class CertificationHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
CertificationDialog.showCertificationDialog(context, gameEntity) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
}

View File

@ -1,24 +0,0 @@
package com.gh.common.chain
import android.content.Context
import com.gh.gamecenter.feature.entity.GameEntity
abstract class ChainHandler {
private var next: ChainHandler? = null
var processEndCallback: ((Any?) -> Unit)? = null
fun setNext(next: ChainHandler?) {
this.next = next
}
fun getNext(): ChainHandler? {
return next
}
fun hasNext(): Boolean {
return next != null
}
abstract fun handleRequest(context: Context, gameEntity: GameEntity)
}

View File

@ -5,15 +5,15 @@ import com.gh.common.util.DialogUtils
import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.feature.entity.GameEntity
class CheckDownloadHandler : ChainHandler() {
class CheckDownloadHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return
DialogUtils.checkDownload(context, apk.size, gameEntity.id, gameEntity.name, gameEntity.categoryChinese) { isSubscribe: Boolean ->
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(isSubscribe)
processEndCallback?.invoke(asVGame, isSubscribe)
}
}

View File

@ -4,19 +4,20 @@ import android.content.Context
import com.gh.gamecenter.common.utils.PermissionHelper
import com.gh.gamecenter.feature.entity.GameEntity
class CheckStoragePermissionHandler : ChainHandler() {
class CheckStoragePermissionHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
PermissionHelper.checkStoragePermissionBeforeAction(
context,
gameEntity.id,
gameEntity.name ?: "",
gameEntity.categoryChinese
gameEntity.categoryChinese,
gameEntity.getApk().firstOrNull()?.format,
) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
}

View File

@ -1,22 +1,22 @@
package com.gh.common.chain
class ChainBuilder {
class DownloadChainBuilder {
private val handlers: MutableList<ChainHandler> = ArrayList()
private val handlers: MutableList<DownloadChainHandler> = ArrayList()
private var processEndCallback: ((Any?) -> Unit)? = null
private var processEndCallback: ((asVGame: Boolean, Any?) -> Unit)? = null
fun setProcessEndCallback(callback: (Any?) -> Unit): ChainBuilder {
fun setProcessEndCallback(callback: (asVGame: Boolean, Any?) -> Unit): DownloadChainBuilder {
processEndCallback = callback
return this
}
fun addHandler(handler: ChainHandler): ChainBuilder {
fun addHandler(handler: DownloadChainHandler): DownloadChainBuilder {
handlers.add(handler)
return this
}
fun buildHandlerChain(): ChainHandler? {
fun buildHandlerChain(): DownloadChainHandler? {
for (i in handlers.indices) {
handlers[i].processEndCallback = processEndCallback
if (i + 1 < handlers.size) {

View File

@ -0,0 +1,40 @@
package com.gh.common.chain
import android.content.Context
import com.gh.gamecenter.feature.entity.GameEntity
abstract class DownloadChainHandler {
private var next: DownloadChainHandler? = null
// asVGame: 当前下载是否以畅玩游戏来进行
var processEndCallback: ((asVGame: Boolean, Any?) -> Unit)? = null
/**
* 设置下一个处理者
*/
fun setNext(next: DownloadChainHandler?) {
this.next = next
}
/**
* 获取下一个处理者
*/
fun getNext(): DownloadChainHandler? {
return next
}
/**
* 是否存在下一个处理者
*/
fun hasNext(): Boolean {
return next != null
}
/**
* 处理请求
* @param gameEntity 游戏实体
* @param asVGame 是否作为畅玩游戏进行
*/
abstract fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean)
}

View File

@ -3,21 +3,18 @@ package com.gh.common.chain
import android.content.Context
import com.gh.common.util.DownloadDialogHelper
import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.core.utils.EmptyCallback
import com.gh.gamecenter.feature.entity.GameEntity
class DownloadDialogHelperHandler : ChainHandler() {
class DownloadDialogHelperHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, object : EmptyCallback {
override fun onCallback() {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
} else {
processEndCallback?.invoke(null)
}
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(asVGame, null)
}
})
}
}
}

View File

@ -5,14 +5,14 @@ import androidx.appcompat.app.AppCompatActivity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
class GamePermissionHandler : ChainHandler() {
class GamePermissionHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
GamePermissionDialogFragment.show((context as AppCompatActivity), gameEntity, gameEntity.info) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
}

View File

@ -5,18 +5,18 @@ import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
import com.gh.gamecenter.feature.entity.GameEntity
class LandPageAddressHandler : ChainHandler() {
class LandPageAddressHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
if (gameEntity.isLandPageAddressDialog()) {
DialogUtils.showLandPageAddressDialog(context, gameEntity) {// 跳转第三方落地页
DirectUtils.directToExternalBrowser(context, gameEntity.landPageAddressDialog!!.link!!)
}
} else {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
}

View File

@ -4,22 +4,22 @@ import android.content.Context
import com.gh.common.util.DialogUtils
import com.gh.gamecenter.feature.entity.GameEntity
class OverseaDownloadHandler : ChainHandler() {
class OverseaDownloadHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
if (gameEntity.isOverseaAddressDialog()) {
DialogUtils.showOverseaDownloadDialog(context, gameEntity) {// 跳转海外下载地址弹窗
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
} else {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
}

View File

@ -5,14 +5,14 @@ import androidx.appcompat.app.AppCompatActivity
import com.gh.common.dialog.PackageCheckDialogFragment
import com.gh.gamecenter.feature.entity.GameEntity
class PackageCheckHandler : ChainHandler() {
class PackageCheckHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
PackageCheckDialogFragment.show((context as AppCompatActivity), gameEntity) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
}

View File

@ -4,18 +4,20 @@ import android.content.Context
import com.gh.gamecenter.common.utils.DialogHelper
import com.gh.gamecenter.feature.entity.GameEntity
class UnsupportedFeatureHandler : ChainHandler() {
class UnsupportedFeatureHandler : DownloadChainHandler() {
override fun handleRequest(
context: Context, gameEntity: GameEntity
context: Context,
gameEntity: GameEntity,
asVGame: Boolean
) {
if (shouldShowUnsupportedFeatureDialog()) {
DialogHelper.showUnsupportedFeatureDialog(context)
} else {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
}

View File

@ -5,31 +5,27 @@ import com.gh.common.simulator.NewSimulatorGameManager
import com.gh.common.simulator.SimulatorGameManager
import com.gh.gamecenter.feature.entity.GameEntity
class UpdateNewSimulatorHandler: ChainHandler() {
class UpdateNewSimulatorHandler: DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
if (NewSimulatorGameManager.shouldShowUpdateNewSimulatorAlert(context)) {
NewSimulatorGameManager.showUpdateNewsSimulator(context, gameEntity) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
}
else{
} else {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
}
}
}
else{
} else {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
}
}
}
}

View File

@ -4,15 +4,23 @@ import android.content.Context
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.vspace.VHelper
class ValidateVSpaceHandler : ChainHandler() {
class ValidateVSpaceHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
VHelper.validateVSpaceBeforeAction(context, gameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
val closure = {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
if (asVGame) {
VHelper.validateVSpaceBeforeAction(context, gameEntity) {
closure.invoke()
}
} else {
closure.invoke()
}
}
}

View File

@ -7,14 +7,14 @@ import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.toResString
import com.gh.gamecenter.feature.entity.GameEntity
class VersionNumberHandler : ChainHandler() {
class VersionNumberHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
val confirmCallback = {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(null)
processEndCallback?.invoke(asVGame, null)
}
}
if (!gameEntity.isShowVersionNumber()) {

View File

@ -8,7 +8,6 @@ import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.gh.common.util.AdHelper;
import com.gh.common.util.PackageHelper;
import com.gh.common.util.PackageUtils;
import com.gh.gamecenter.BuildConfig;
@ -22,14 +21,17 @@ import com.gh.gamecenter.common.utils.EnvHelper;
import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.SPUtils;
import com.gh.gamecenter.core.utils.UrlFilterUtils;
import com.gh.gamecenter.entity.AppEntity;
import com.gh.gamecenter.entity.GameGuidePopupEntity;
import com.gh.gamecenter.entity.NewApiSettingsEntity;
import com.gh.gamecenter.entity.NewSettingsEntity;
import com.gh.gamecenter.entity.VNewSetting;
import com.gh.gamecenter.entity.VSetting;
import com.gh.gamecenter.feature.entity.NewsEntity;
import com.gh.gamecenter.feature.entity.SettingsEntity;
import com.gh.gamecenter.feature.entity.SimulatorEntity;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.gh.gamecenter.retrofit.service.VApiService;
import com.gh.vspace.VHelper;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.Utils;
@ -42,8 +44,12 @@ import java.io.IOException;
import java.util.List;
import java.util.Locale;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.BehaviorSubject;
import okhttp3.ResponseBody;
public class Config {
@ -72,6 +78,10 @@ public class Config {
private static NewApiSettingsEntity.NightMode mNightModeSetting;
private static SimulatorEntity mNewSimulatorEntity;
private static VSetting mVSetting;
private static VNewSetting mVNewSetting;
private static AppEntity mNew32UpdateEntity;
public static BehaviorSubject<VNewSetting> vNewSettingSubject = BehaviorSubject.create();
private static GameGuidePopupEntity mGameGuidePopupEntity;
private static SharedPreferences mDefaultSharedPreferences;
@ -305,6 +315,27 @@ public class Config {
return mVSetting;
}
@Nullable
public static VNewSetting getVNewSettingEntity() {
if (mVNewSetting == null) {
try {
String json = SPUtils.getString(Constants.SP_V_NEW_SETTINGS);
if (!TextUtils.isEmpty(json)) {
mVNewSetting = GsonUtils.fromJson(json, VNewSetting.class);
vNewSettingSubject.onNext(mVNewSetting);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return mVNewSetting;
}
@Nullable
public static AppEntity getNew32UpdateEntity() {
return mNew32UpdateEntity;
}
/**
* 请求网络数据,尝试刷新畅玩相关配置
*/
@ -325,6 +356,36 @@ public class Config {
});
}
@SuppressLint("CheckResult")
public static void getNewSetting() {
VApiService vApi = RetrofitManager.getInstance().getVApi();
vApi.getNewSettings(BuildConfig.VERSION_NAME, Build.VERSION.SDK_INT).flatMap(new Function<VNewSetting, SingleSource<AppEntity>>() {
@Override
public SingleSource<AppEntity> apply(VNewSetting data) throws Exception {
mVNewSetting = data;
vNewSettingSubject.onNext(mVNewSetting);
SPUtils.setString(Constants.SP_V_NEW_SETTINGS, GsonUtils.toJson(data));
if (data.getVa() != null && data.getVa().getArch32() != null) {
String versionNameByPackageName = PackageUtils.getVersionNameByPackageName(data.getVa().getArch32().getPackageName());
return vApi.getNewPackageUpdate(
BuildConfig.VERSION_NAME,
versionNameByPackageName != null ? versionNameByPackageName : "",
HaloApp.getInstance().getChannel()
);
}
return Single.error(new IllegalStateException("VNewSetting entity is not expected"));
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BiResponse<AppEntity>() {
@Override
public void onSuccess(AppEntity data) {
mNew32UpdateEntity = data;
}
});
}
@Nullable
public static GameGuidePopupEntity getGameGuidePopupEntity() {
return mGameGuidePopupEntity;
@ -403,6 +464,7 @@ public class Config {
});
refreshVSettingEntity();
getNewSetting();
RetrofitManager.getInstance()
.getApi().getGameGuidePopup(Build.MANUFACTURER, Build.VERSION.RELEASE, Build.MODEL, channel, BuildConfig.VERSION_NAME)

View File

@ -3,27 +3,21 @@ package com.gh.common.databind;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.common.chain.BrowserInstallHandler;
import com.gh.common.chain.CertificationHandler;
import com.gh.common.chain.ChainBuilder;
import com.gh.common.chain.ChainHandler;
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.DownloadDialogHelperHandler;
@ -46,7 +40,6 @@ import com.gh.common.util.DialogUtils;
import com.gh.common.util.GameUtils;
import com.gh.common.util.GameViewUtils;
import com.gh.common.util.LogUtils;
import com.gh.common.util.NewsUtils;
import com.gh.common.util.PackageInstaller;
import com.gh.common.util.PackageLauncher;
import com.gh.common.util.PackageUtils;
@ -57,26 +50,16 @@ import com.gh.download.server.BrowserInstallHelper;
import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WebActivity;
import com.gh.gamecenter.common.baselist.LoadStatus;
import com.gh.gamecenter.common.callback.OnViewClickListener;
import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.common.eventbus.EBReuse;
import com.gh.gamecenter.common.utils.DarkModeUtils;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.common.utils.ImageUtils;
import com.gh.gamecenter.common.utils.NewFlatLogUtils;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.common.view.DrawableView;
import com.gh.gamecenter.core.utils.DisplayUtils;
import com.gh.gamecenter.core.utils.MtaHelper;
import com.gh.gamecenter.core.utils.NumberUtils;
import com.gh.gamecenter.core.utils.ToastUtils;
import com.gh.gamecenter.databinding.KaifuDetailItemRowBinding;
import com.gh.gamecenter.feature.entity.ApkEntity;
import com.gh.gamecenter.feature.entity.CommunityVideoEntity;
import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.feature.entity.PluginLocation;
import com.gh.gamecenter.feature.entity.ServerCalendarEntity;
import com.gh.gamecenter.feature.entity.TagStyleEntity;
import com.gh.gamecenter.feature.entity.TestEntity;
import com.gh.gamecenter.feature.exposure.ExposureEvent;
@ -85,14 +68,11 @@ import com.gh.gamecenter.feature.view.DownloadButton;
import com.gh.gamecenter.feature.view.GameIconView;
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment;
import com.gh.gamecenter.manager.PackagesManager;
import com.gh.vspace.VDownloadManagerActivity;
import com.gh.vspace.VHelper;
import com.lightgame.download.DownloadEntity;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.Utils;
import org.greenrobot.eventbus.EventBus;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@ -100,134 +80,8 @@ import java.util.List;
/**
* Created by khy on 12/02/18.
*/
public class BindingAdapters {
public static void loadIcon(SimpleDraweeView view, String imageUrl) {
ImageUtils.displayIcon(view, imageUrl);
}
public static void loadImage(SimpleDraweeView view, String imageUrl) {
ImageUtils.display(view, imageUrl);
}
public static void setTextSize(TextView view, int number) {
view.setTextSize(number);
}
public static void setTypeface(TextView view, String type) {
if (type == null) return;
switch (type) {
case "bold":
view.setTypeface(null, Typeface.BOLD);
break;
case "italic":
view.setTypeface(null, Typeface.ITALIC);
break;
case "bold_italic":
view.setTypeface(null, Typeface.BOLD_ITALIC);
break;
default:
view.setTypeface(null, Typeface.NORMAL);
break;
}
}
public static void addDetailKaiFuView(LinearLayout view, List<ServerCalendarEntity> list
, OnViewClickListener listener, Boolean isReadyPatch) {
if (list == null) return;
view.removeAllViews();
for (int i = 0; i < list.size() + 1; i++) { // 1 is Title
View inflate = LayoutInflater.from(view.getContext()).inflate(R.layout.kaifu_detail_item_row, null);
KaifuDetailItemRowBinding binding = KaifuDetailItemRowBinding.bind(inflate);
binding.getRoot().setBackgroundColor(isReadyPatch != null && isReadyPatch ? ExtensionsKt.toColor(R.color.theme) : ExtensionsKt.toColor(R.color.white));
binding.getRoot().setPadding(DisplayUtils.dip2px(1), DisplayUtils.dip2px(1), DisplayUtils.dip2px(1), i == list.size() ? DisplayUtils.dip2px(1) : 0);
ServerCalendarEntity serverEntity = list.get(i - 1);
binding.timeTv.setText(i == 0 ? "时间" : serverEntity.getFormatTime("HH:mm"));
binding.remarkTv.setText(i == 0 ? "备注" : serverEntity.getRemark());
binding.nameTv.setText(i == 0 ? "名字" : (TextUtils.isEmpty(serverEntity.getNote()) ? "-" : serverEntity.getNote()));
if (i != 0) {
binding.getRoot().setOnClickListener(v -> {
listener.onClick(v, isReadyPatch != null && isReadyPatch ? serverEntity : null);
});
// 滑动冲突处理
binding.getRoot().setOnTouchListener((v, event) -> {
if (list.size() > 5) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
EventBus.getDefault().post(new EBReuse("CalenderDown"));
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
EventBus.getDefault().post(new EBReuse("CalenderCancel"));
}
}
return false;
});
}
view.addView(inflate);
}
}
// 如果超过10000则转换为1.0W
public static void transSimpleCount(TextView view, int count) {
view.setText(NumberUtils.transSimpleCount(count));
}
public static void textColorFromString(TextView tv, String hexString) {
if (TextUtils.isEmpty(hexString)) return;
try {
tv.setTextColor(Color.parseColor(hexString));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void showHide(View view, Boolean show) {
if (show != null && show) {
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.GONE);
}
}
public static void goneIf(View view, Boolean gone) {
if (gone != null && gone) {
view.setVisibility(View.GONE);
} else {
view.setVisibility(View.VISIBLE);
}
}
/**
* lazy 的 paddingTop
*/
public static void lazyPaddingLeft(View view, int paddingLeftInDp) {
view.setPadding(DisplayUtils.dip2px(paddingLeftInDp), view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom());
}
/**
* lazy 的 paddingTop
*/
public static void lazyPaddingTop(View view, int paddingTopInDp) {
view.setPadding(view.getPaddingLeft(), DisplayUtils.dip2px(paddingTopInDp), view.getPaddingRight(), view.getPaddingBottom());
}
/**
* lazy 的 paddingBottom
*/
public static void lazyPaddingBottom(View view, int paddingBottomInDp) {
view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), DisplayUtils.dip2px(paddingBottomInDp));
}
public static void visibleInvisible(View view, Boolean show) {
if (show != null && show) {
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.INVISIBLE);
}
}
public static void setMessageUnread(TextView view, int unreadCount) {
if (unreadCount < 100) {
view.setText(String.valueOf(unreadCount));
@ -236,119 +90,12 @@ public class BindingAdapters {
}
}
public static void setServerTypePadding(TextView view, String serverType) {
int paddRight = 0;
if (TextUtils.isEmpty(serverType)) {
} else {
if ("删档内测".equals(serverType) || "不删档内测".equals(serverType)) {
if ("删档内测".equals(serverType)) {
paddRight = DisplayUtils.dip2px(view.getContext(), 50);
} else {
paddRight = DisplayUtils.dip2px(view.getContext(), 60);
}
} else {
paddRight = DisplayUtils.dip2px(view.getContext(), 30);
}
}
view.setPadding(0, 0, paddRight, 0);
}
public static void setServerType(TextView view, String serverType) {
view.setText(serverType);
if ("删档内测".equals(serverType) || "不删档内测".equals(serverType)) {
view.setBackgroundResource(R.drawable.textview_server_tag);
} else {
view.setBackgroundResource(R.drawable.textview_orange_up);
}
}
public static void setGame(View view, GameEntity gameEntity) {
if (gameEntity != null && view instanceof GameIconView) {
((GameIconView) view).displayGameIcon(gameEntity);
}
}
public static void setGameIcon(View view, GameEntity gameEntity) {
if (gameEntity != null && view instanceof GameIconView) {
((GameIconView) view).displayGameIcon(gameEntity.getIcon(), gameEntity.getIconSubscript(), gameEntity.getIconFloat());
}
}
public static void setArticleType(TextView view, String articleType) {
NewsUtils.setNewsType(view, articleType, 0, 0);
}
public static void setDetailDownloadText(TextView view, GameEntity gameEntity) {
if (gameEntity == null || gameEntity.getApk().isEmpty()) {
view.setBackgroundResource(R.drawable.game_item_btn_pause_style);
view.setTextColor(0xFF999999);
view.setClickable(false);
}
}
public static void setLiBaoBtn(TextView view, String status) {
if (TextUtils.isEmpty(status)) return;
switch (status) {
case "coming":
view.setText(R.string.libao_coming);
view.setBackgroundResource(R.drawable.textview_blue_style);
break;
case "ling":
view.setText(R.string.libao_ling);
view.setBackgroundResource(R.drawable.textview_green_style);
break;
case "tao":
view.setText(R.string.libao_tao);
view.setBackgroundResource(R.drawable.textview_orange_style);
break;
case "used_up":
view.setText(R.string.libao_used_up);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "finish":
view.setText(R.string.libao_finish);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "linged":
view.setText(R.string.libao_linged);
view.setBackgroundResource(R.drawable.libao_linged_style);
view.setTextColor(ContextCompat.getColorStateList(view.getContext(), R.color.libao_linged_selector));
break;
case "taoed":
view.setText(R.string.libao_taoed);
view.setBackgroundResource(R.drawable.libao_taoed_style);
view.setTextColor(ContextCompat.getColorStateList(view.getContext(), R.color.libao_taoed_selector));
break;
case "copy":
view.setText(R.string.libao_copy);
view.setBackgroundResource(R.drawable.textview_blue_style);
break;
case "repeatLing":
view.setText(R.string.libao_repeat_ling);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "repeatLinged":
view.setText(R.string.libao_repeat_ling);
view.setBackgroundResource(R.drawable.textview_green_style);
break;
case "repeatTao":
view.setText(R.string.libao_repeat_tao);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "repeatTaoed":
view.setText(R.string.libao_repeat_tao);
view.setBackgroundResource(R.drawable.textview_orange_style);
break;
case "unshelve":
view.setBackgroundResource(R.drawable.textview_cancel_style);
view.setText(R.string.libao_unshelve);
break;
default:
view.setBackgroundResource(R.drawable.textview_cancel_style);
view.setText("异常");
}
}
// 大图下的进度条
public static void setDownloadButton(DownloadButton progressBar,
GameEntity gameEntity,
@ -376,13 +123,9 @@ public class BindingAdapters {
switch (progressBar.getButtonStyle()) {
case DOWNLOADING_PLUGIN:
case DOWNLOADING_NORMAL:
if (gameEntity.isVGame()) {
v.getContext().startActivity(VDownloadManagerActivity.getIntent(v.getContext(), true));
} else {
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(v.getContext(),
gameEntity.getApk().get(0).getUrl(), entrance);
v.getContext().startActivity(intent);
}
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(v.getContext(),
gameEntity.getApk().get(0).getUrl(), entrance);
v.getContext().startActivity(intent);
break;
case NONE:
Utils.toast(v.getContext(), "该游戏已关闭下载");
@ -405,7 +148,7 @@ public class BindingAdapters {
}
}
ChainBuilder builder = new ChainBuilder();
DownloadChainBuilder builder = new DownloadChainBuilder();
builder.addHandler(new UnsupportedFeatureHandler());
builder.addHandler(new GamePermissionHandler());
builder.addHandler(new CheckStoragePermissionHandler());
@ -419,22 +162,33 @@ public class BindingAdapters {
builder.addHandler(new OverseaDownloadHandler());
builder.addHandler(new CheckDownloadHandler());
builder.setProcessEndCallback(o -> {
download(v.getContext(), progressBar, gameEntity, traceEvent, (boolean) o, entrance, location);
builder.setProcessEndCallback((asVGame, isSubscribe) -> {
download(v.getContext(),
progressBar,
gameEntity,
traceEvent,
asVGame,
(boolean) isSubscribe,
entrance,
location);
return null;
});
final ChainHandler chainHandler = builder.buildHandlerChain();
final DownloadChainHandler chainHandler = builder.buildHandlerChain();
if (chainHandler != null) {
chainHandler.handleRequest(v.getContext(), gameEntity);
chainHandler.handleRequest(
v.getContext(),
gameEntity,
GameUtils.shouldPerformAsVGame(gameEntity)
);
}
} else {
ChainBuilder builder = new ChainBuilder();
DownloadChainBuilder builder = new DownloadChainBuilder();
builder.addHandler(new UnsupportedFeatureHandler());
builder.addHandler(new GamePermissionHandler());
builder.addHandler(new CertificationHandler());
builder.addHandler(new VersionNumberHandler());
builder.setProcessEndCallback(o -> {
builder.setProcessEndCallback((asVGame, isSubscribe) -> {
DownloadDialog.showDownloadDialog(
v.getContext(),
gameEntity,
@ -443,9 +197,13 @@ public class BindingAdapters {
location + ":" + gameEntity.getName());
return null;
});
final ChainHandler chainHandler = builder.buildHandlerChain();
final DownloadChainHandler chainHandler = builder.buildHandlerChain();
if (chainHandler != null) {
chainHandler.handleRequest(v.getContext(), gameEntity);
chainHandler.handleRequest(
v.getContext(),
gameEntity,
GameUtils.shouldPerformAsVGame(gameEntity)
);
}
}
}
@ -458,7 +216,14 @@ public class BindingAdapters {
if (downloadEntity != null) {
File file = new File(downloadEntity.getPath());
if (!file.exists()) {
download(v.getContext(), progressBar, gameEntity, traceEvent, false, entrance, location);
download(v.getContext(),
progressBar,
gameEntity,
traceEvent,
false,
false,
entrance,
location);
return;
}
@ -467,12 +232,7 @@ public class BindingAdapters {
return;
}
if (gameEntity.isVGame()) {
VHelper.installOrLaunch((AppCompatActivity) v.getContext(), gameEntity, null);
return;
}
PackageLauncher.launchApp(v.getContext(), gameEntity, gameEntity.getApk().get(0).getPackageName());
PackageLauncher.launch(v.getContext(), gameEntity, null);
} else {
DownloadDialog.showDownloadDialog(
v.getContext(),
@ -500,13 +260,12 @@ public class BindingAdapters {
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity);
if (gameEntity.isVGame()) {
VHelper.installOrLaunch(v.getContext(), gameEntity, null);
return;
}
if (downloadEntity != null) {
PackageInstaller.install(v.getContext(), downloadEntity);
if (ExtensionsKt.isLocalDownloadInDualDownloadMode(downloadEntity)) {
PackageInstaller.install(v.getContext(), downloadEntity);
} else {
VHelper.installOrLaunch(v.getContext(), gameEntity, null);
}
}
}
break;
@ -592,7 +351,7 @@ public class BindingAdapters {
}
} else {
String status = GameUtils.getDownloadBtnText(progressBar.getContext(), gameEntity, PluginLocation.only_game);
String status = GameUtils.getDownloadBtnText(progressBar.getContext(), gameEntity, true, false, PluginLocation.only_game);
switch (status) {
case "插件化":
progressBar.setButtonStyle(DownloadButton.ButtonStyle.PLUGIN);
@ -664,24 +423,6 @@ public class BindingAdapters {
}
}
/*private static void download(DownloadProgressBar progressBar, GameEntity gameEntity, ExposureEvent traceEvent, @Nullable String entrance, @Nullable String location, View v) {
if (gameEntity.getApk().size() == 1) {
ApkEntity apk = gameEntity.getApk().get(0);
DownloadDialogHelper.findAvailableDialogAndShow(
v.getContext(),
gameEntity,
apk,
() -> {
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
});
} else {
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
entrance, location + gameEntity.getName(), traceEvent);
}
}*/
private static void updateReservation(DownloadButton progressBar, GameEntity gameEntity) {
// 显示预约
if (gameEntity.isReservable()) {
@ -701,45 +442,35 @@ public class BindingAdapters {
DownloadButton progressBar,
GameEntity gameEntity,
ExposureEvent traceEvent,
boolean asVGame,
boolean isSubscribe,
String entrance,
String location) {
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint));
}
String str = progressBar.getText().toString();
String method;
if (str.contains("更新")) {
method = "更新";
} else if (str.contains("插件化")) {
method = "插件化";
} else {
method = progressBar.getContext().getString(R.string.download);
}
String buttonText = progressBar.getText();
ApkEntity apkEntity = gameEntity.getApk().get(0);
String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity.getSize());
if (TextUtils.isEmpty(msg)) {
DownloadManager.createDownload(progressBar.getContext(),
apkEntity,
gameEntity,
method,
asVGame,
gameEntity.isDualBtnModeEnabled(),
entrance,
location + gameEntity.getName(),
isSubscribe,
traceEvent);
progressBar.setProgress(0);
progressBar.setButtonStyle("插件化".equals(method) ?
progressBar.setButtonStyle(buttonText.contains("插件化") ?
DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN : DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
} else {
Utils.toast(progressBar.getContext(), msg);
}
}
public static void setGameLabelList(LinearLayout layout, List<TagStyleEntity> tagStyle) {
GameViewUtils.setLabelList(layout.getContext(), layout, tagStyle);
}
// 包含测试开服标签
public static void setGameTags(LinearLayout layout, GameEntity gameEntity) {
try {
@ -809,12 +540,6 @@ public class BindingAdapters {
}
}
public static void isRefreshing(SwipeRefreshLayout layout, LoadStatus status) {
if (status != LoadStatus.INIT_LOADING && status != LoadStatus.LIST_LOADING) {
layout.setRefreshing(false);
}
}
public static void setGameName(TextView view, GameEntity game, boolean isShowPlatform, @Nullable Boolean isShowSuffix) {
if (isShowSuffix == null) isShowSuffix = true; // 默认显示
String gameName;
@ -836,30 +561,6 @@ public class BindingAdapters {
}
public static void setCommunityImage(SimpleDraweeView imageView, List<String> images, List<CommunityVideoEntity> videos) {
if (videos.size() > 0) {
CommunityVideoEntity videoEntity = videos.get(0);
ImageUtils.display(imageView, videoEntity.getPoster());
imageView.setVisibility(View.VISIBLE);
} else if (images.size() > 0) {
imageView.setVisibility(View.VISIBLE);
ImageUtils.display(imageView, images.get(0));
} else {
imageView.setVisibility(View.GONE);
}
}
public static void setCommunityVideoDuration(TextView mVideoDuration, List<CommunityVideoEntity> videos) {
if (videos != null && videos.size() > 0) {
CommunityVideoEntity videoEntity = videos.get(0);
mVideoDuration.setBackground(DrawableView.getOvalDrawable(R.color.black_alpha_50, 999F));
mVideoDuration.setText(videoEntity.getDuration());
mVideoDuration.setVisibility(View.VISIBLE);
} else {
mVideoDuration.setVisibility(View.GONE);
}
}
public static void setGameTags(TextView view, List<TagStyleEntity> tags, int maxTags) {
if (tags == null) {
view.setText("");
@ -887,16 +588,4 @@ public class BindingAdapters {
}
view.setText(span);
}
public static void setVideoData(TextView view, int count) {
if (count > 0) {
ExtensionsKt.setDrawableStart(view, ContextCompat.getDrawable(view.getContext(), R.drawable.ic_video_data_up), null, null);
view.setTextColor(ContextCompat.getColor(view.getContext(), R.color.text_EA3333));
view.setText(count + "");
} else {
ExtensionsKt.removeDrawable(view);
view.setTextColor(ContextCompat.getColor(view.getContext(), R.color.text_subtitleDesc));
view.setText("-");
}
}
}

View File

@ -96,9 +96,9 @@ object ExposureUtils {
}
@JvmStatic
fun getDownloadType(apkEntity: ApkEntity, gameId: String, isVGame: Boolean): DownloadType {
fun getDownloadType(apkEntity: ApkEntity, gameId: String, asVGame: Boolean): DownloadType {
return when {
isVGame -> getVGameDownloadType(apkEntity, gameId)
asVGame -> getVGameDownloadType(apkEntity, gameId)
PackageUtils.isInstalled(
HaloApp.getInstance().application,
apkEntity.packageName
@ -109,7 +109,7 @@ object ExposureUtils {
private fun getVGameDownloadType(apkEntity: ApkEntity, gameId: String): DownloadType {
return when {
PackagesManager.isCanUpdate(gameId, apkEntity.packageName) -> DownloadType.FUN_UPDATE
PackagesManager.isCanUpdate(gameId, apkEntity.packageName, asVGame = true) -> DownloadType.FUN_UPDATE
else -> DownloadType.FUN_DOWNLOAD
}
}

View File

@ -41,6 +41,7 @@ class AccelerateNotificationHandler(priority: Int) : PriorityChainHandler(priori
if (gameEntityList == null) {
processNext()
} else {
updateStatus(STATUS_VALID)
onProcess()
}
} else {

View File

@ -20,7 +20,7 @@ class FloatingWindowHandler(priority: Int) : PriorityChainHandler(priority) {
mWindowList = windowList
if (mFragment != null) {
preProcess()
doPreProcess()
}
}
@ -32,15 +32,16 @@ class FloatingWindowHandler(priority: Int) : PriorityChainHandler(priority) {
mRecyclerView = recyclerView
if (mWindowList != null) {
preProcess()
doPreProcess()
}
}
private fun preProcess() {
private fun doPreProcess() {
Utils.log(TAG, "FloatingWindowHandler preProcess windowSize is -> ${mWindowList?.size}")
if (getStatus() == STATUS_PENDING) {
if (!mWindowList.isNullOrEmpty()) {
updateStatus(STATUS_VALID)
onProcess()
} else {
processNext()

View File

@ -14,6 +14,7 @@ class HomePushHandler(priority: Int): PriorityChainHandler(priority) {
if (getStatus() == STATUS_PENDING) {
if (shouldShow && homeFragment != null) {
updateStatus(STATUS_VALID)
onProcess()
} else {
processNext()

View File

@ -20,6 +20,7 @@ class PrivacyPolicyDialogHandler(priority: Int) : PriorityChainHandler(priority)
if (privacyPolicyEntity == null) {
processNext()
} else {
updateStatus(STATUS_VALID)
onProcess()
}
} else {

View File

@ -21,6 +21,7 @@ class ReserveDialogHandler(priority: Int) : PriorityChainHandler(priority) {
if (reserveData.isNullOrEmpty()) {
processNext()
} else {
updateStatus(STATUS_VALID)
onProcess()
}
} else {

View File

@ -8,6 +8,7 @@ import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IAppProvider
import com.gh.gamecenter.core.provider.IFlavorProvider
import com.halo.assistant.HaloApp
import com.va.host.HostUtils
@Route(path = RouteConsts.provider.app, name = "Application暴露服务")
class AppProviderImpl : IAppProvider {
@ -82,4 +83,6 @@ class AppProviderImpl : IAppProvider {
override fun getIsBrandNewInstall(): Boolean {
return HaloApp.getInstance().isBrandNewInstall
}
override fun getPluginVersion(): String = HostUtils.getPluginVersion()
}

View File

@ -120,6 +120,10 @@ class DirectProviderImpl : IDirectProvider {
return DirectUtils.directToQGameHome(context)
}
override fun directToExternalBrowser(context: Context, url: String) {
DirectUtils.directToExternalBrowser(context, url)
}
override fun init(context: Context?) {
// Do nothing
}

View File

@ -3,6 +3,7 @@ package com.gh.common.provider
import android.content.Context
import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.exposure.ExposureSource
@ -39,13 +40,16 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
gameId = boundedObject.id
gameName = boundedObject.name ?: ""
gameCategory = boundedObject.category ?: ""
downloadStatus = if (boundedObject.isVGame()) {
"畅玩"
} else if (boundedObject.downloadStatus == "demo") {
"试玩"
} else {
"下载"
}
downloadStatus =
if (boundedObject.isVGamePreferred()) {
"畅玩"
} else {
if (boundedObject.downloadStatus == "demo") {
"试玩"
} else {
"下载"
}
}
gameTypeInChinese = boundedObject.categoryChinese
downloadStatusInChinese = boundedObject.downloadStatusChinese
gameSchemaType = boundedObject.gameBitChinese
@ -68,7 +72,7 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
gameId = boundedObject.gameId
gameName = boundedObject.name ?: ""
gameCategory = boundedObject.getGameCategory()
downloadStatus = if (boundedObject.isVGame()) "畅玩" else "下载"
downloadStatus = if (boundedObject.asVGame()) "畅玩" else "下载"
packageName = boundedObject.packageName
exposureSourceList = boundedObject.exposureTrace?.toObject<ExposureEvent>()?.source
}
@ -93,9 +97,18 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
}
// 预约状态不上报
if (downloadButton.buttonStyle != DownloadButton.ButtonStyle.RESERVABLE
&& downloadButton.buttonStyle != DownloadButton.ButtonStyle.RESERVED
) {
if (downloadButton.buttonStyle == DownloadButton.ButtonStyle.NORMAL
|| downloadButton.buttonStyle == DownloadButton.ButtonStyle.PLUGIN) {
val text = downloadButton.text.ifEmpty {
downloadButton.getTag(R.string.download) ?: ""
}.toString()
val downloadType = if (text.contains("畅玩")) {
"畅玩下载"
} else {
"本地下载"
}
// 上报神策点击事件
SensorsBridge.trackEventWithExposureSource(
@ -107,6 +120,7 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
"download_status", downloadStatusInChinese,
"button_name", downloadButton.text,
"game_schema_type", gameSchemaType,
"download_type", downloadType,
"page_name", GlobalActivityManager.getCurrentPageEntity().pageName,
"page_id", GlobalActivityManager.getCurrentPageEntity().pageId,
"page_business_id", GlobalActivityManager.getCurrentPageEntity().pageBusinessId,

View File

@ -11,7 +11,7 @@ import com.lightgame.download.DownloadEntity
class PackageInstallerProviderImpl : IPackageInstallerProvider {
override fun install(context: Context, downloadEntity: DownloadEntity, showUnzipToast: Boolean) {
PackageInstaller.install(context, downloadEntity, showUnzipToast)
PackageInstaller.install(context, downloadEntity, showUnzipToast, false)
}
override fun uninstall(context: Context, path: String) {

View File

@ -8,14 +8,6 @@ import com.gh.vspace.VHelper
@Route(path = RouteConsts.provider.vhelper, name = "VHelper暴露服务")
class VHelperProviderImpl: IVHelperProvider {
override fun getPlatformV(): String {
return VHelper.PLATFORM_V
}
override fun getVUrl(originUrl: String?): String {
return VHelper.getVUrl(originUrl)
}
override fun isVGameOn(): Boolean {
return VHelper.isVGameOn()
}

View File

@ -21,10 +21,6 @@ class WebProviderImpl : IWebProvider {
return WebActivity.getBindWechatIntent(context)
}
override fun getSecurityCertificationIntent(context: Context): Intent {
return WebActivity.getSecurityCertificationIntent(context)
}
override fun getQAIntent(
context: Context?,
url: String?,

View File

@ -167,7 +167,7 @@ class SimulatorDownloadManager private constructor() {
this.gameName = gameName
this.gameType = gameCategoryChinese
PermissionHelper.checkGetInstalledAppsListBeforeAction(context, object : EmptyCallback {
val callback = object : EmptyCallback {
override fun onCallback() {
val isInstalledNewSimulator =
SimulatorGameManager.isNewSimulatorInstalled(HaloApp.getInstance().application)
@ -322,7 +322,15 @@ class SimulatorDownloadManager private constructor() {
SPUtils.setString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, TimeUtils.getToday())
}
}
})
}
if (context is AppCompatActivity
&& PackageUtils.isSupportGetInstalledAppsPermission(context)
&& PermissionHelper.isGetInstalledListPermissionDisabled(context)) {
PermissionHelper.requestGetInstalledAppsListPermission(context, false, callback)
} else {
callback.onCallback()
}
}
fun showDownloadingDialog(

View File

@ -1,15 +1,8 @@
package com.gh.common.util
import com.gh.common.constant.Config
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.utils.observableToMain
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.entity.NewApiSettingsEntity
import com.gh.gamecenter.entity.StartupAdEntity
import com.gh.gamecenter.feature.entity.SettingsEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
object AdHelper {

View File

@ -5,6 +5,7 @@ import android.os.Build;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.constant.EntranceConsts;
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.common.utils.NetworkUtils;
import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.entity.NewsDetailEntity;
@ -54,7 +55,7 @@ public class DataCollectionUtils {
map.put("location", downloadEntity.getLocation());
map.put(EntranceConsts.KEY_ENTRANCE, downloadEntity.getEntrance());
map.put("installed", downloadEntity.getInstalled());
map.put("network", NetworkUtils.getConnectedType(context));
map.put("network", MetaUtil.getMeta().getNetwork());
DataCollectionManager.onEvent(context, "download", map);
}
@ -118,7 +119,7 @@ public class DataCollectionUtils {
map.put("key", args[0]);
map.put("game_id", args[3]);
map.put("game_name", args[4]);
map.put("netword", NetworkUtils.getConnectedType(context));
map.put("netword", MetaUtil.getMeta().getNetwork());
map.put("type", "search");
map.put("device_type", android.os.Build.MODEL);
map.put("device_system", android.os.Build.VERSION.SDK_INT + "=" + android.os.Build.VERSION.RELEASE);
@ -136,7 +137,7 @@ public class DataCollectionUtils {
map.put("key", args[0]);
map.put("game_id", args[3]);
map.put("game_name", args[4]);
map.put("netword", NetworkUtils.getConnectedType(context));
map.put("netword", MetaUtil.getMeta().getNetwork());
map.put("type", "click");
map.put("device_type", android.os.Build.MODEL);
map.put("device_system", android.os.Build.VERSION.SDK_INT + "=" + android.os.Build.VERSION.RELEASE);

View File

@ -9,15 +9,16 @@ import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import com.gh.gamecenter.common.base.GlobalActivityManager;
import com.gh.ad.AdDelegateHelper;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.common.base.GlobalActivityManager;
import com.gh.gamecenter.common.base.activity.BaseActivity;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.eventbus.EBReuse;
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.common.retrofit.BiResponse;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.core.AppExecutor;
import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.MtaHelper;
import com.gh.gamecenter.core.utils.SPUtils;
@ -114,18 +115,25 @@ public class DataUtils {
Utils.log("Gid", gid);
PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()).edit().putString(Constants.DEVICE_KEY, gid).apply();
String originalGid = HaloApp.getInstance().getGid();
HaloApp.getInstance().setGid(gid);
// gid 变更时上报 gid 变更日志
if (!TextUtils.isEmpty(originalGid) && !originalGid.equals(gid)) {
NewFlatLogUtils.logGidChanged(originalGid, gid);
// 默认用 APP 级已存储的 GID 来使用,不使用外部 GID
String savedGid = SPUtils.getString(Constants.GID);
if (!TextUtils.isEmpty(savedGid)) {
gid = savedGid;
} else {
SPUtils.setString(Constants.GID, gid);
}
HaloApp.getInstance().setGid(gid);
SensorsBridge.setGid(gid);
// 更新广告配置
ExtensionsKt.doOnMainProcessOnly(HaloApp.getInstance(), () -> {
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
});
// 避免重复调用
if (!TextUtils.isEmpty(gid) && !gid.equals(originalGid)) {
if (!TextUtils.isEmpty(gid)) {
GameSubstituteRepositoryHelper.updateSubstitutableGames();
}

View File

@ -1,16 +1,20 @@
package com.gh.common.util;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import com.gh.common.constant.Config;
import com.gh.common.filter.RegionSetting;
import com.gh.common.filter.RegionSettingHelper;
import com.gh.common.repository.ReservationRepository;
import com.gh.common.simulator.SimulatorGameManager;
import com.gh.gamecenter.feature.view.DownloadButton;
import com.gh.common.xapk.XapkInstaller;
import com.gh.common.xapk.XapkUnzipStatus;
import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.feature.entity.PluginLocation;
import com.gh.gamecenter.feature.view.DownloadButton;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.viewholder.DetailViewHolder;
@ -18,7 +22,6 @@ import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.core.utils.SPUtils;
import com.gh.gamecenter.feature.entity.PluginLocation;
import com.gh.gamecenter.manager.PackagesManager;
import com.gh.vspace.VHelper;
import com.lightgame.download.DownloadEntity;
@ -30,163 +33,125 @@ import java.util.Objects;
* Created by khy on 27/06/17.
* 详情下载工具类
*/
public class DetailDownloadUtils {
public static void detailInitDownload(DetailViewHolder viewHolder, boolean isCheck) {
String downloadAddWord = viewHolder.gameEntity.getDownloadAddWord();
public static void updateViewHolder(DetailViewHolder viewHolder) {
updateViewHolder(viewHolder, false);
}
/**
* 更新底部下载区域
* @param viewHolder 下载区域的包裹
* @param ignoreDownloadEntity 忽略下载实体(往往用于下载异常时)
*/
public static void updateViewHolder(DetailViewHolder viewHolder, boolean ignoreDownloadEntity) {
GameEntity gameEntity = viewHolder.getGameEntity();
String downloadAddWord = gameEntity.getDownloadAddWord();
// 隐藏下载按钮上的畅玩文案
if (viewHolder.getOverlayTv() != null) {
viewHolder.getOverlayTv().setVisibility(View.GONE);
}
if (viewHolder.mMultiVersionDownloadTv != null) {
viewHolder.mMultiVersionDownloadTv.setVisibility(View.GONE);
// 多版本下载箭头
if (viewHolder.getMultiVersionDownloadTv() != null) {
viewHolder.getMultiVersionDownloadTv().setVisibility(View.GONE);
}
if (viewHolder.gameEntity != null && Config.isShowDownload(viewHolder.gameEntity.getId()) && !"光环助手".equals(viewHolder.gameEntity.getName())) {
viewHolder.downloadBottom.setVisibility(View.VISIBLE);
// 根据预置的配置更新 ViewHolder 的状态 (譬如青少年模式、下载内容为空等)
if (updateViewHolderWithPredefinedConfig(viewHolder, gameEntity)) {
return;
}
// 游戏只包含单 APK 的情况
if (gameEntity.getApk().size() == 1) {
boolean showVGame = false; // 真下载按钮(DownloadButton)是否需要显示为畅玩,包括单按钮显示和双按钮显示
boolean showDualDownloadButton = false; // 是否显示双下载按钮
int gameDownloadMode = gameEntity.getGameDownloadButtonMode(); // 获取游戏的下载按钮模式
DownloadEntity downloadEntity = null;
if (!ignoreDownloadEntity) {
downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity);
}
// 不支持双下载按钮的情况时(新闻详情、礼包详情页),优选一个下载方式显示
if (!viewHolder.isSupportDualButton()) {
boolean performAsVGame = GameUtils.shouldPerformAsVGame(gameEntity);
if (performAsVGame) {
gameDownloadMode = GameEntity.GAME_DOWNLOAD_BUTTON_MODE_VGAME;
} else {
gameDownloadMode = GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DOWNLOAD;
}
}
if (gameDownloadMode == GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DOWNLOAD) {
showVGame = false;
if (viewHolder.getLocalDownloadContainer() != null) {
viewHolder.getLocalDownloadContainer().setVisibility(View.GONE);
}
} else if (gameDownloadMode == GameEntity.GAME_DOWNLOAD_BUTTON_MODE_VGAME) {
showVGame = true;
if (viewHolder.getLocalDownloadContainer() != null) {
viewHolder.getLocalDownloadContainer().setVisibility(View.GONE);
}
} else if (gameDownloadMode == GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DUAL) {
showVGame = true;
showDualDownloadButton = true;
if (viewHolder.getLocalDownloadContainer() != null) {
viewHolder.getLocalDownloadContainer().setVisibility(View.VISIBLE);
}
// 畅玩未安装,且当前下载的默认类型为"普通下载",且用户未安装时,禁用双按钮,禁用畅玩
if (!VHelper.isInstalled(gameEntity.getUniquePackageName())
&& !PackagesManager.isInstalled(gameEntity.getUniquePackageName())
&& downloadEntity != null
&& ExtensionsKt.isLocalDownloadInDualDownloadMode(downloadEntity)
) {
viewHolder.getDownloadPb().setVisibility(View.GONE);
if (viewHolder.getOverlayTv() != null) {
viewHolder.getOverlayTv().setVisibility(View.GONE);
}
} else {
viewHolder.getDownloadPb().setVisibility(View.VISIBLE);
}
}
// 更新默认的下载按钮
updateWithSingleApk(
gameEntity,
viewHolder,
viewHolder.getDownloadPb(),
downloadAddWord,
showVGame,
showDualDownloadButton,
downloadEntity
);
if (showDualDownloadButton) {
// 双下载按钮时更新占位的下载按钮
updateWithSingleApk(
gameEntity,
viewHolder,
viewHolder.getLocalDownloadButton(),
downloadAddWord,
false,
true,
downloadEntity
);
}
} else {
viewHolder.downloadBottom.setVisibility(View.GONE);
return;
}
if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) {
viewHolder.mDownloadPb.setText("查看");
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.TEENAGER_MODE);
return;
}
if (viewHolder.gameEntity.isSpecialDownload()) {
viewHolder.mDownloadPb.setText("查看下载资源");
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.SPECIAL_DOWNLOAD);
return;
}
if (viewHolder.gameEntity.isReservable()) {
if (!ReservationRepository.thisGameHasBeenReserved(viewHolder.gameEntity.getId())) {
if (TextUtils.isEmpty(downloadAddWord)) {
viewHolder.mDownloadPb.setText(String.format("预约" + "《%s》", viewHolder.gameEntity.getName()));
} else {
viewHolder.mDownloadPb.setText(String.format("预约" + "《%s》%s", viewHolder.gameEntity.getName(), downloadAddWord));
}
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.RESERVABLE);
} else {
viewHolder.mDownloadPb.setText("已预约《" + viewHolder.gameEntity.getName() + "");
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.RESERVED);
}
return;
}
final RegionSetting.GameH5Download gameH5Download = RegionSettingHelper.getGameH5DownloadByGameId(viewHolder.gameEntity.getId());
if (gameH5Download != null) {
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.gameEntity.getDownloadOffText()) ? "查看详情" : viewHolder.gameEntity.getDownloadOffText());
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
return;
}
if (viewHolder.gameEntity.isVGame() && !viewHolder.gameEntity.getApk().isEmpty()) {
String status = GameUtils.getDownloadBtnText(viewHolder.context, viewHolder.gameEntity, PluginLocation.only_game);
if (viewHolder.context.getString(R.string.launch).equals(status)) {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
} else if (viewHolder.context.getString(R.string.install).equals(status)) {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
} else {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
}
String downloadText;
if (viewHolder.context.getString(R.string.launch).equals(status) || viewHolder.context.getString(R.string.install).equals(status) || viewHolder.context.getString(R.string.download).equals(status)) {
downloadText = "";
if (viewHolder.getOverlayTv() != null) {
viewHolder.getOverlayTv().setVisibility(View.VISIBLE);
}
} else if (viewHolder.context.getString(R.string.attempt).equals(status)) {
downloadText = status + getDownloadSizeText(viewHolder);
} else {
downloadText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : downloadAddWord) + getDownloadSizeText(viewHolder);
}
viewHolder.mDownloadPb.setText(downloadText);
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(viewHolder.gameEntity);
// 在下载管理找不到下载实体,到畅玩数据库里找
if (downloadEntity == null && viewHolder.gameEntity.isVGame()) {
String packageName = viewHolder.gameEntity.getUniquePackageName();
if (!TextUtils.isEmpty(packageName)) {
downloadEntity = VHelper.getVDownloadEntitySnapshot(viewHolder.gameEntity.getId(), packageName);
}
}
if (downloadEntity != null) {
viewHolder.downloadEntity = downloadEntity;
detailInvalidate(viewHolder);
}
return;
}
if (viewHolder.gameEntity.getApk().isEmpty() || viewHolder.gameEntity.getDownloadOffStatus() != null) {
LinkEntity h5LinkEntity = viewHolder.gameEntity.getH5Link();
if (h5LinkEntity != null) {
if ("play".equals(h5LinkEntity.getType())) {
String defaultString = String.format("开始玩" + "《%s》", viewHolder.gameEntity.getName());
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(h5LinkEntity.getText()) ? defaultString : h5LinkEntity.getText());
} else {
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(h5LinkEntity.getText()) ? "查看" : h5LinkEntity.getText());
}
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.H5_GAME);
} else {
if ("dialog".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.gameEntity.getDownloadOffText()) ? "查看详情" : viewHolder.gameEntity.getDownloadOffText());
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.NONE_WITH_HINT);
} else if ("updating".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.gameEntity.getDownloadOffText()) ? "更新中" : viewHolder.gameEntity.getDownloadOffText());
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.UPDATING);
} else {
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.gameEntity.getDownloadOffText()) ? "暂无下载" : viewHolder.gameEntity.getDownloadOffText());
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.NONE);
}
}
} else if (viewHolder.gameEntity.getApk().size() == 1) {
String status = GameUtils.getDownloadBtnText(viewHolder.context, viewHolder.gameEntity, PluginLocation.only_game);
if (viewHolder.context.getString(R.string.pluggable).equals(status)) {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.PLUGIN);
} else if (viewHolder.context.getString(R.string.launch).equals(status)) {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
} else if (viewHolder.context.getString(R.string.install).equals(status)) {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
} else {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
}
String downloadText;
if (viewHolder.isNewsDetail) {
downloadText = status;
} else if (viewHolder.context.getString(R.string.pluggable).equals(status)) {
downloadText = "升级" + (TextUtils.isEmpty(downloadAddWord) ? "" : "" + downloadAddWord) + getDownloadSizeText(viewHolder);
} else if (viewHolder.context.getString(R.string.launch).equals(status)) {
downloadText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord);
} else if (viewHolder.context.getString(R.string.attempt).equals(status)) {
downloadText = status + getDownloadSizeText(viewHolder);
} else if (viewHolder.context.getString(R.string.install).equals(status)) {
downloadText = viewHolder.context.getString(R.string.install);
} else {
downloadText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : downloadAddWord) + getDownloadSizeText(viewHolder);
}
viewHolder.mDownloadPb.setText(downloadText);
} else {
viewHolder.mMultiVersionDownloadTv.setText("选择下载你的版本" + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord));
viewHolder.mMultiVersionDownloadTv.setVisibility(View.VISIBLE);
viewHolder.mDownloadPb.setText("");
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(viewHolder.gameEntity);
// 游戏包含多 APK 的情况
viewHolder.getMultiVersionDownloadTv().setText("选择下载你的版本" + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord));
viewHolder.getMultiVersionDownloadTv().setVisibility(View.VISIBLE);
viewHolder.getDownloadPb().setText("");
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity);
if (downloadEntity != null) {
switch (downloadEntity.getStatus()) {
case downloading:
viewHolder.mDownloadTips.setVisibility(View.VISIBLE);
ExtensionsKt.setDownloadTipsAnimation(viewHolder.mDownloadTips, true);
viewHolder.getDownloadTips().setVisibility(View.VISIBLE);
ExtensionsKt.setDownloadTipsAnimation(viewHolder.getDownloadTips(), true);
break;
case done:
case pause:
@ -195,73 +160,348 @@ public class DetailDownloadUtils {
case subscribe:
case neterror:
case overflow:
viewHolder.mDownloadTips.setVisibility(View.VISIBLE);
ExtensionsKt.setDownloadTipsAnimation(viewHolder.mDownloadTips, false);
viewHolder.getDownloadTips().setVisibility(View.VISIBLE);
ExtensionsKt.setDownloadTipsAnimation(viewHolder.getDownloadTips(), false);
break;
default:
viewHolder.mDownloadTips.setVisibility(View.GONE);
viewHolder.getDownloadTips().setVisibility(View.GONE);
break;
}
} else {
viewHolder.mDownloadTips.setVisibility(View.GONE);
viewHolder.getDownloadTips().setVisibility(View.GONE);
}
}
}
if (isCheck && viewHolder.gameEntity.getApk().size() == 1) {
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(viewHolder.gameEntity);
/**
* 更新只有单个 APK 文件时候的下载按钮状态
*
* @param downloadButton 下载按钮,可能是真的下载按钮也可能只是占位下载按钮
* @param downloadAddWord 下载按钮的补充文案
* @param showAsVGame 是否显示为畅玩游戏
* @param showDualDownloadButton 是否正显示为双下载按钮
*/
// 在下载管理找不到下载实体,到畅玩数据库里找
if (downloadEntity == null && viewHolder.gameEntity.isVGame()) {
String packageName = viewHolder.gameEntity.getUniquePackageName();
if (!TextUtils.isEmpty(packageName)) {
downloadEntity = VHelper.getVDownloadEntitySnapshot(viewHolder.gameEntity.getId(), packageName);
private static void updateWithSingleApk(GameEntity gameEntity,
DetailViewHolder viewHolder,
DownloadButton downloadButton,
String downloadAddWord,
boolean showAsVGame,
boolean showDualDownloadButton,
DownloadEntity downloadEntity) {
Context context = viewHolder.getContext();
TextView overlayTv = viewHolder.getOverlayTv();
String status = GameUtils.getDownloadBtnText(context, gameEntity, false, showAsVGame, PluginLocation.only_game);
if (showAsVGame) {
// 显示为畅玩游戏
if (context.getString(R.string.launch).equals(status)) {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
} else {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
}
String btnText;
if (showDualDownloadButton
&& (context.getString(R.string.launch).equals(status) || context.getString(R.string.install).equals(status) || context.getString(R.string.smooth).equals(status) || context.getString(R.string.update).equals(status))) {
if (context.getString(R.string.smooth).equals(status)) {
btnText = context.getString(R.string.download_v);
} else if (context.getString(R.string.update).equals(status)) {
btnText = context.getString(R.string.update_v);
} else {
btnText = context.getString(R.string.launch_v);
}
if (overlayTv != null && downloadButton.getVisibility() != View.GONE) {
overlayTv.setVisibility(View.VISIBLE);
overlayTv.setText(btnText);
downloadButton.setText("");
}
} else {
btnText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : downloadAddWord) + getDownloadSizeText(viewHolder);
if (overlayTv != null && downloadButton.getVisibility() != View.GONE) {
if (context.getString(R.string.launch).equals(status)
|| context.getString(R.string.install).equals(status)) {
overlayTv.setVisibility(View.VISIBLE);
overlayTv.setText("启动(畅玩)");
} else {
overlayTv.setVisibility(View.GONE);
downloadButton.setText(btnText);
}
} else {
if (overlayTv != null) {
overlayTv.setVisibility(View.GONE);
}
downloadButton.setText(btnText);
}
}
if (downloadEntity != null) {
viewHolder.downloadEntity = downloadEntity;
detailInvalidate(viewHolder);
// 在下载管理找不到下载实体,到畅玩数据库里找
if (downloadEntity == null) {
String packageName = gameEntity.getUniquePackageName();
if (!TextUtils.isEmpty(packageName)) {
downloadEntity = VHelper.getVDownloadEntitySnapshot(gameEntity.getId(), packageName);
}
}
} else {
// 非畅玩,显示为普通游戏
if (context.getString(R.string.pluggable).equals(status)) {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.PLUGIN);
} else if (context.getString(R.string.launch).equals(status)) {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
} else if (context.getString(R.string.install).equals(status)) {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
} else {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
}
if (showDualDownloadButton && viewHolder.getLocalDownloadSizeTv() != null) {
viewHolder.getLocalDownloadSizeTv().setVisibility(View.GONE);
String size = viewHolder.getGameEntity().getApk().get(0).getSize();
if (size != null) {
String sizeWithoutDigit = size.replaceAll("(?<=\\d)\\.[0-9]+(?!\\d)", "");
viewHolder.getLocalDownloadSizeTv().setText(sizeWithoutDigit);
}
// 若双下载按钮时,下载的游戏是以畅玩游戏下载的,把 downloadEntity 置空,避免把按钮更新到错误的状态
if (downloadEntity != null && ExtensionsKt.isVGameDownloadInDualDownloadMode(downloadEntity)) {
downloadEntity = null;
}
}
String btnText;
String extraBtnText;
if (viewHolder.isNewsDetail()) {
btnText = status;
extraBtnText = status;
} else if (context.getString(R.string.pluggable).equals(status)) {
btnText = "升级" + (TextUtils.isEmpty(downloadAddWord) ? "" : "" + downloadAddWord) + getDownloadSizeText(viewHolder);
extraBtnText = "升级" + (TextUtils.isEmpty(downloadAddWord) ? "" : "" + downloadAddWord);
} else if (context.getString(R.string.launch).equals(status)) {
btnText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord);
extraBtnText = context.getString(R.string.launch_local);
} else if (context.getString(R.string.attempt).equals(status)) {
btnText = status + getDownloadSizeText(viewHolder);
extraBtnText = status;
if (showDualDownloadButton
&& viewHolder.getLocalDownloadContainer() != null
&& viewHolder.getLocalDownloadContainer().getVisibility() == View.VISIBLE) {
viewHolder.getLocalDownloadSizeTv().setVisibility(View.VISIBLE);
}
} else if (context.getString(R.string.install).equals(status)) {
btnText = context.getString(R.string.install);
extraBtnText = context.getString(R.string.install_local);
} else if (context.getString(R.string.update).equals(status)) {
btnText = context.getString(R.string.update);
extraBtnText = context.getString(R.string.update_local);
if (showDualDownloadButton
&& viewHolder.getLocalDownloadContainer() != null
&& viewHolder.getLocalDownloadContainer().getVisibility() == View.VISIBLE) {
viewHolder.getLocalDownloadSizeTv().setVisibility(View.VISIBLE);
}
} else {
btnText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : downloadAddWord) + getDownloadSizeText(viewHolder);
extraBtnText = context.getString(R.string.download_local);
if (showDualDownloadButton
&& viewHolder.getLocalDownloadContainer() != null
&& viewHolder.getLocalDownloadContainer().getVisibility() == View.VISIBLE) {
viewHolder.getLocalDownloadSizeTv().setVisibility(View.VISIBLE);
}
}
downloadButton.setText(btnText);
if (viewHolder.getLocalDownloadTitleTv() != null) {
viewHolder.getLocalDownloadTitleTv().setText(extraBtnText);
}
}
if (overlayTv != null && overlayTv.getVisibility() == View.VISIBLE) {
downloadButton.setTag(R.string.download, overlayTv.getText());
} else {
downloadButton.setTag(R.string.download, downloadButton.getText());
}
if (downloadEntity == null) return;
if (handleDownloadButtonAsXapk(downloadEntity, downloadButton)) {
return;
}
// 非完成状态显示下载按钮
if (downloadEntity.getStatus() != DownloadStatus.done) {
viewHolder.getDownloadPb().setVisibility(View.VISIBLE);
}
// 存在未完成的下载任务或不显示双按钮时,隐藏本地下载按钮
if (viewHolder.getLocalDownloadContainer() != null) {
if (downloadEntity.getStatus() != DownloadStatus.done) {
viewHolder.getLocalDownloadContainer().setVisibility(View.GONE);
} else if (showDualDownloadButton) {
viewHolder.getLocalDownloadContainer().setVisibility(View.VISIBLE);
} else {
viewHolder.getLocalDownloadContainer().setVisibility(View.GONE);
}
}
downloadButton.setProgress((int) (downloadEntity.getPercent() * 10));
if (overlayTv != null
&& downloadEntity.getStatus() != DownloadStatus.done) {
overlayTv.setVisibility(View.GONE);
}
if (showAsVGame) {
updateVStyleDownloadButton(viewHolder, downloadButton, downloadEntity, status);
} else {
updateDefaultStyleDownloadButton(context, viewHolder, downloadButton, gameEntity, downloadEntity);
}
}
/**
* 根据预置的配置更新 ViewHolder 的状态
*
* @return 是否已经是最终状态,返回 true 表示已应用当前配置,返回 false 表示不应用当前配置
*/
private static boolean updateViewHolderWithPredefinedConfig(DetailViewHolder viewHolder, GameEntity gameEntity) {
String downloadAddWord = gameEntity.getDownloadAddWord();
// 不满足条件的部分游戏隐藏下载按钮
if (Config.isShowDownload(gameEntity.getId())
&& !"光环助手".equals(gameEntity.getName())) {
viewHolder.getDownloadBottom().setVisibility(View.VISIBLE);
} else {
viewHolder.getDownloadBottom().setVisibility(View.GONE);
return true;
}
// 青少年模式显示为查看
if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) {
viewHolder.getDownloadPb().setText("查看");
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.TEENAGER_MODE);
return true;
}
// 预约
if (gameEntity.isReservable()) {
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
if (TextUtils.isEmpty(downloadAddWord)) {
viewHolder.getDownloadPb().setText(String.format("预约" + "《%s》", gameEntity.getName()));
} else {
viewHolder.getDownloadPb().setText(String.format("预约" + "《%s》%s", gameEntity.getName(), downloadAddWord));
}
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.RESERVABLE);
} else {
viewHolder.getDownloadPb().setText("已预约《" + gameEntity.getName() + "");
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.RESERVED);
}
return true;
}
// 国际服 H5 弹窗
final RegionSetting.GameH5Download gameH5Download = RegionSettingHelper.getGameH5DownloadByGameId(gameEntity.getId());
if (gameH5Download != null) {
viewHolder.getDownloadPb().setText(TextUtils.isEmpty(gameEntity.getDownloadOffText()) ? "查看详情" : gameEntity.getDownloadOffText());
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
return true;
}
// 特殊下载
if (gameEntity.isSpecialDownload()) {
viewHolder.getDownloadPb().setText("查看下载资源");
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.SPECIAL_DOWNLOAD);
return true;
}
// 处理不存在 APK 文件或游戏状态为关闭时的情况
if (gameEntity.getApk().isEmpty() || gameEntity.getDownloadOffStatus() != null) {
LinkEntity h5LinkEntity = gameEntity.getH5Link();
if (h5LinkEntity != null) {
if ("play".equals(h5LinkEntity.getType())) {
String defaultString = String.format("开始玩" + "《%s》", gameEntity.getName());
viewHolder.getDownloadPb().setText(TextUtils.isEmpty(h5LinkEntity.getText()) ? defaultString : h5LinkEntity.getText());
} else {
viewHolder.getDownloadPb().setText(TextUtils.isEmpty(h5LinkEntity.getText()) ? "查看" : h5LinkEntity.getText());
}
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.H5_GAME);
} else {
if ("dialog".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())) {
viewHolder.getDownloadPb().setText(TextUtils.isEmpty(gameEntity.getDownloadOffText()) ? "更新中" : gameEntity.getDownloadOffText());
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.UPDATING);
} else {
viewHolder.getDownloadPb().setText(TextUtils.isEmpty(gameEntity.getDownloadOffText()) ? "暂无下载" : gameEntity.getDownloadOffText());
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.NONE);
}
}
return true;
}
return false;
}
private static String getDownloadSizeText(DetailViewHolder viewHolder) {
return String.format("%s", viewHolder.gameEntity.getApk().get(0).getSize());
return String.format("%s", viewHolder.getGameEntity().getApk().get(0).getSize());
}
public static void detailInvalidate(DetailViewHolder viewHolder) {
DownloadEntity downloadEntity = viewHolder.downloadEntity;
String xapkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
private static void updateVStyleDownloadButton(DetailViewHolder viewHolder,
DownloadButton downloadButton,
DownloadEntity downloadEntity,
String status) {
switch (downloadEntity.getStatus()) {
case redirected:
case downloading:
downloadButton.setText("游戏加载中 " + downloadEntity.getPercent() + "%");
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
break;
case waiting:
downloadButton.setText(R.string.waiting);
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
downloadButton.setVisibility(View.GONE);
break;
case overflow:
case timeout:
case neterror:
case subscribe:
case diskisfull:
case diskioerror:
case pause:
downloadButton.setText("继续加载 " + downloadEntity.getPercent() + "%");
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
break;
case done:
if (!status.contains("更新")) {
if (VHelper.isInstalled(downloadEntity.getPackageName())) {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
} else {
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
}
if (XapkUnzipStatus.SUCCESS.name().equals(xapkStatus) && XapkInstaller.INSTANCE.isInstalling(downloadEntity.getPath())) {
viewHolder.mDownloadPb.setText("游戏安装中");
viewHolder.mDownloadPb.setProgress(100);
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
return;
}
if (XapkUnzipStatus.UNZIPPING.name().equals(xapkStatus)) {
String percent = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_PERCENT);
viewHolder.mDownloadPb.setText("游戏解压中 " + percent + "%");
viewHolder.mDownloadPb.setProgress((int) (Float.valueOf(percent) * 10));
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.XAPK_UNZIPPING);
return;
} else if (XapkUnzipStatus.FAILURE.name().equals(xapkStatus)) {
viewHolder.mDownloadPb.setText(R.string.install);
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.XAPK_FAILURE);
return;
}
viewHolder.mDownloadPb.setProgress((int) (viewHolder.downloadEntity.getPercent() * 10));
if (viewHolder.getOverlayTv() != null) {
viewHolder.getOverlayTv().setVisibility(View.GONE);
}
if (viewHolder.gameEntity.isVGame()) {
updateVStyleButton(viewHolder);
return;
downloadButton.setText("");
}
break;
case cancel:
case hijack:
case notfound:
case uncertificated:
case unqualified:
case unavailable:
case banned:
updateViewHolder(viewHolder, true);
break;
default:
break;
}
}
private static void updateDefaultStyleDownloadButton(
Context context,
DetailViewHolder viewHolder,
DownloadButton downloadButton,
GameEntity gameEntity,
DownloadEntity downloadEntity) {
switch (downloadEntity.getStatus()) {
case timeout:
case neterror:
@ -274,55 +514,37 @@ public class DetailDownloadUtils {
case overflow:
String downloadingText = "游戏加载中 " + downloadEntity.getPercent() + "%";
String resumeText = "继续加载 " + downloadEntity.getPercent() + "%";
viewHolder.mDownloadPb.setText((downloadEntity.getStatus() == DownloadStatus.downloading || downloadEntity.getStatus() == DownloadStatus.redirected) ? downloadingText : resumeText);
downloadButton.setText((downloadEntity.getStatus() == DownloadStatus.downloading || downloadEntity.getStatus() == DownloadStatus.redirected) ? downloadingText : resumeText);
if (downloadEntity.isPluggable() && PackagesManager.isInstalled(downloadEntity.getPackageName())) {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN);
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN);
} else {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
}
break;
case waiting:
viewHolder.mDownloadPb.setText(R.string.waiting);
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.WAITING);
downloadButton.setText(R.string.waiting);
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.WAITING);
break;
case done:
if (SimulatorGameManager.isSimulatorGame(viewHolder.gameEntity)) {
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(viewHolder.context, viewHolder.gameEntity.getSimulator().getApk().getPackageName());
boolean isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(viewHolder.context);
if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(context, gameEntity.getSimulator().getApk().getPackageName());
boolean isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(context);
if (isInstalled || isInstalledNewSimulator) {
viewHolder.mDownloadPb.setText(R.string.launch);
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
downloadButton.setText(R.string.launch);
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
} else {
if (SPUtils.getBoolean(Constants.SP_USE_BROWSER_TO_INSTALL) && !Objects.equals(Constants.XAPK_APKS_FORMAT, downloadEntity.getFormat())) {
viewHolder.mDownloadPb.setText(R.string.browser_install_install);
downloadButton.setText(R.string.browser_install_install);
} else {
viewHolder.mDownloadPb.setText(R.string.install);
}
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
}
} else if (viewHolder.gameEntity.isVGame()) {
if (!viewHolder.mDownloadPb.getText().toString().contains("更新")) {
if (VHelper.isInstalled(downloadEntity.getPackageName())) {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
} else {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
}
viewHolder.mDownloadPb.setText("");
if (viewHolder.getOverlayTv() != null) {
viewHolder.getOverlayTv().setVisibility(View.VISIBLE);
downloadButton.setText(R.string.install);
}
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
}
} else {
if (SPUtils.getBoolean(Constants.SP_USE_BROWSER_TO_INSTALL) && !Objects.equals(Constants.XAPK_APKS_FORMAT, downloadEntity.getFormat())) {
viewHolder.mDownloadPb.setText(R.string.browser_install_install);
downloadButton.setText(R.string.browser_install_install);
} else {
viewHolder.mDownloadPb.setText(R.string.install);
}
if (downloadEntity.isPluggable() && PackagesManager.isInstalled(downloadEntity.getPackageName())) {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_PLUGIN);
} else {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
downloadButton.setText(R.string.install);
}
}
@ -334,50 +556,35 @@ public class DetailDownloadUtils {
case unqualified:
case unavailable:
case banned:
detailInitDownload(viewHolder, false);
updateViewHolder(viewHolder, true);
break;
default:
break;
}
}
private static void updateVStyleButton(DetailViewHolder viewHolder) {
switch (viewHolder.downloadEntity.getStatus()) {
case redirected:
case downloading:
viewHolder.mDownloadPb.setText("游戏加载中 " + viewHolder.downloadEntity.getPercent() + "%");
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
break;
case waiting:
viewHolder.mDownloadPb.setText(R.string.waiting);
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
break;
case overflow:
case timeout:
case neterror:
case subscribe:
case diskisfull:
case diskioerror:
case pause:
viewHolder.mDownloadPb.setText("继续加载 " + viewHolder.downloadEntity.getPercent() + "%");
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
break;
case done:
if (!viewHolder.mDownloadPb.getText().toString().contains("更新")) {
if (VHelper.isInstalled(viewHolder.downloadEntity.getPackageName())) {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
} else {
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
}
private static boolean handleDownloadButtonAsXapk(DownloadEntity downloadEntity, DownloadButton downloadButton) {
String xapkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
viewHolder.mDownloadPb.setText("");
if (viewHolder.getOverlayTv() != null) {
viewHolder.getOverlayTv().setVisibility(View.VISIBLE);
}
}
break;
default:
break;
if (XapkUnzipStatus.SUCCESS.name().equals(xapkStatus) && XapkInstaller.INSTANCE.isInstalling(downloadEntity.getPath())) {
downloadButton.setText("游戏安装中");
downloadButton.setProgress(100);
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
return true;
}
if (XapkUnzipStatus.UNZIPPING.name().equals(xapkStatus)) {
String percent = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_PERCENT);
downloadButton.setText("游戏解压中 " + percent + "%");
downloadButton.setProgress((int) (Float.valueOf(percent) * 10));
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.XAPK_UNZIPPING);
return true;
} else if (XapkUnzipStatus.FAILURE.name().equals(xapkStatus)) {
downloadButton.setText(R.string.install);
downloadButton.setButtonStyle(DownloadButton.ButtonStyle.XAPK_FAILURE);
return true;
}
return false;
}
}

View File

@ -4,7 +4,6 @@ import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
@ -12,16 +11,9 @@ import android.net.Uri;
import android.os.CountDownTimer;
import android.provider.Settings;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -34,12 +26,9 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.common.constant.Config;
import com.gh.common.filter.RegionSetting;
@ -47,11 +36,9 @@ import com.gh.common.xapk.XapkDialogHelper;
import com.gh.gamecenter.R;
import com.gh.gamecenter.ShellActivity;
import com.gh.gamecenter.adapter.ReportReasonAdapter;
import com.gh.gamecenter.adapter.viewholder.PrivacyPolicyItemViewHolder;
import com.gh.gamecenter.common.base.TrackableDialog;
import com.gh.gamecenter.common.callback.CancelListener;
import com.gh.gamecenter.common.callback.ConfirmListener;
import com.gh.gamecenter.common.callback.SimpleCallback;
import com.gh.gamecenter.common.databinding.DialogAlertDefaultBinding;
import com.gh.gamecenter.common.entity.SimpleGameEntity;
import com.gh.gamecenter.common.entity.SuggestType;
@ -60,9 +47,7 @@ import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.common.utils.ImageUtils;
import com.gh.gamecenter.common.utils.NetworkUtils;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.common.view.CustomLinkMovementMethod;
import com.gh.gamecenter.common.view.DrawableView;
import com.gh.gamecenter.common.view.FixLinearLayoutManager;
import com.gh.gamecenter.common.view.MaxHeightLinearLayout;
import com.gh.gamecenter.common.view.MaxHeightNestedScrollView;
import com.gh.gamecenter.common.view.VerticalItemDecoration;
@ -80,10 +65,7 @@ import com.gh.gamecenter.databinding.DialogRelievePhoneBinding;
import com.gh.gamecenter.databinding.DialogReportReasonBinding;
import com.gh.gamecenter.databinding.DialogWechatReserveSuccessBinding;
import com.gh.gamecenter.databinding.ImprintContentItemBinding;
import com.gh.gamecenter.databinding.PrivacyItemBinding;
import com.gh.gamecenter.entity.BadgeEntity;
import com.gh.gamecenter.entity.PermissionsEntity;
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
import com.gh.gamecenter.entity.TrackableEntity;
import com.gh.gamecenter.feature.entity.ApkEntity;
import com.gh.gamecenter.feature.entity.Badge;
@ -91,7 +73,6 @@ import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.feature.entity.SettingsEntity;
import com.gh.gamecenter.help.HelpAndFeedbackBridge;
import com.gh.gamecenter.setting.SettingBridge;
import com.lightgame.adapter.BaseRecyclerAdapter;
import com.lightgame.download.DownloadEntity;
import com.lightgame.utils.AppManager;
import com.lightgame.utils.Util_System_Keyboard;
@ -328,180 +309,7 @@ public class DialogUtils {
return dialog;
}
public static void showPrivacyPolicyDialog(Context context,
@NonNull PrivacyPolicyEntity entity,
SimpleCallback<Boolean> callback) {
final Context activityContext = checkDialogContext(context);
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
AtomicBoolean isCanceledByClickOutsideOfDialog = new AtomicBoolean(true);
final Dialog dialog = new Dialog(activityContext, R.style.GhAlertDialog);
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_privacy_policy, null);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawableResource(android.R.color.transparent);
WindowManager.LayoutParams params = window.getAttributes();
params.horizontalMargin = 0;
params.width = context.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(40);
// int height = context.getResources().getDisplayMetrics().heightPixels - DisplayUtils.dip2px(120);
// int maxHeight = DisplayUtils.dip2px(446);
// if (height > maxHeight) {
// params.height = maxHeight;
// } else {
// params.height = height;
// }
window.setAttributes(params);
}
TextView title = contentView.findViewById(R.id.title);
TextView bottomContent = contentView.findViewById(R.id.bottom_content);
TextView topContent = contentView.findViewById(R.id.top_content);
TextView allowButton = contentView.findViewById(R.id.allow_button);
TextView disallowButton = contentView.findViewById(R.id.disallow_button);
TextView linkContent = contentView.findViewById(R.id.link_content);
RecyclerView permissions = contentView.findViewById(R.id.permissions_content);
permissions.setLayoutManager(new FixLinearLayoutManager(context));
permissions.setAdapter(new BaseRecyclerAdapter(context) {
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = mLayoutInflater.inflate(R.layout.privacy_item, parent, false);
return new PrivacyPolicyItemViewHolder(PrivacyItemBinding.bind(view));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof PrivacyPolicyItemViewHolder) {
PrivacyPolicyItemViewHolder viewHolder = (PrivacyPolicyItemViewHolder) holder;
PrivacyItemBinding binding = viewHolder.getBinding();
final PermissionsEntity permissionsEntity = entity.getPermissions().get(position);
ImageUtils.display(binding.icon, permissionsEntity.getIcon());
binding.name.setText(permissionsEntity.getName());
binding.intro.setText(permissionsEntity.getIntro());
GenericDraweeHierarchy hierarchy = binding.icon.getHierarchy();
if (hierarchy != null) {
if (position == 0) {
hierarchy.setPlaceholderImage(R.drawable.permission_storage);
} else if (position == 1) {
hierarchy.setPlaceholderImage(R.drawable.permission_phone_state);
}
}
}
}
@Override
public int getItemCount() {
return entity.getPermissions().size();
}
});
SpannableStringBuilder skipText = new SpannableStringBuilder("查看完整版的隐私政策和用户协议");
skipText.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(ContextCompat.getColor(activityContext, R.color.theme_font));
ds.setUnderlineText(false);
}
@Override
public void onClick(@NonNull View widget) {
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击隐私政策");
DirectUtils.directToExternalBrowser(context, context.getString(R.string.privacy_policy_url));
}
}, skipText.length() - 9, skipText.length() - 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
skipText.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(ContextCompat.getColor(activityContext, R.color.theme_font));
ds.setUnderlineText(false);
}
@Override
public void onClick(@NonNull View widget) {
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击用户协议");
DirectUtils.directToExternalBrowser(context, context.getString(R.string.disclaimer_url));
}
}, skipText.length() - 4, skipText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
/*skipText.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(ContextCompat.getColor(activityContext, R.color.theme_font));
ds.setUnderlineText(false);
}
@Override
public void onClick(@NonNull View widget) {
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击第三方SDK接入说明");
activityContext.startActivity(WebActivity.getThirdPartySdkStatementIntent(activityContext));
}
}, skipText.length() - 10, skipText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);*/
title.setText(entity.getTitle());
linkContent.setText(skipText);
linkContent.setMovementMethod(LinkMovementMethod.getInstance());
topContent.setText(entity.getTopContent());
bottomContent.setText(ExtensionsKt.fromHtml(entity.getBottomContent()));
bottomContent.setMovementMethod(CustomLinkMovementMethod.getInstance());
// Remove underline
Spannable sa = (Spannable) bottomContent.getText();
for (URLSpan u : sa.getSpans(0, sa.length(), URLSpan.class)) {
sa.setSpan(new UnderlineSpan() {
public void updateDrawState(TextPaint tp) {
tp.setUnderlineText(false);
}
}, sa.getSpanStart(u), sa.getSpanEnd(u), 0);
}
allowButton.setOnClickListener(view -> {
dialog.dismiss();
callback.onCallback(true);
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击同意");
});
disallowButton.setOnClickListener(v -> {
dialog.dismiss();
callback.onCallback(false);
// showPrivacyPolicyDisallowDialog(activityContext, entity, callback);
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "不同意并退出App");
});
dialog.setOnCancelListener(cd -> {
if (isCanceledByClickOutsideOfDialog.get()) {
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击空白");
}
});
dialog.setOnKeyListener((dialog1, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
isCanceledByClickOutsideOfDialog.set(false);
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击返回");
}
return false;
});
// 用户未同意隐私策略不应该触发 MTA 事件
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "出现弹窗");
try {
dialog.setCancelable(false);
dialog.show();
} catch (Exception ignored) {
}
}
public static void showPrivacyPolicyDisallowDialog(Context context,
@NonNull PrivacyPolicyEntity entity,
EmptyCallback callback) {
final Context activityContext = checkDialogContext(context);

View File

@ -37,6 +37,7 @@ import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.discovery.DiscoveryActivity
import com.gh.gamecenter.download.DownloadFragment.Companion.INDEX_UPDATE
import com.gh.gamecenter.entity.GameCollectionListEntity
import com.gh.gamecenter.entity.SubjectData
import com.gh.gamecenter.entity.SubjectRecommendEntity
import com.gh.gamecenter.entity.VideoLinkEntity
@ -58,9 +59,12 @@ import com.gh.gamecenter.game.commoncollection.detail.CommonCollectionDetailActi
import com.gh.gamecenter.game.upload.GameSubmissionActivity
import com.gh.gamecenter.gamecollection.detail.GameCollectionDetailActivity
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.GameDetailFragment
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
import com.gh.gamecenter.help.HelpAndFeedbackBridge
@ -154,7 +158,8 @@ object DirectUtils {
"bbs_video",
"explore_column",
"game_explore",
"column_test_v2"
"column_test_v2",
"game_list_collection"
)
fun directToLinkPage(
@ -189,6 +194,8 @@ object DirectUtils {
}
}
"game_server_calendar" -> directToGameServerCalendar(context, linkEntity.link)
"column", "游戏专题" -> directToSubject(
context, linkEntity.link
?: "", linkEntity.text, BaseActivity.mergeEntranceAndPath(entrance, path), exposureEvent
@ -444,6 +451,14 @@ object DirectUtils {
"qq_mini_game_column" -> directToQGameHome(context)
"game_list_collection" -> directToGameCollectionListDetail(
context,
linkEntity.link ?: "",
linkEntity.text ?: "",
linkEntity.explain,
entrance
)
"" -> {
// do nothing
}
@ -532,12 +547,13 @@ object DirectUtils {
* 跳转至游戏日历表
*/
@JvmStatic
fun directToGameServerCalendar(context: Context, gameId: String?) {
fun directToGameServerCalendar(context: Context, gameId: String?, kaifuTime: Long = 0) {
val bundle = Bundle()
bundle.putString(KEY_TO, ServersCalendarActivity::class.java.name)
bundle.putParcelable(GameEntity::class.java.simpleName, GameEntity().apply {
id = gameId ?: ""
})
bundle.putLong(KEY_KAIFU_TIME, kaifuTime)
bundle.putParcelable(GameDetailServer::class.java.simpleName, GameDetailServer())
bundle.putParcelable(MeEntity::class.java.simpleName, MeEntity())
jumpActivity(context, bundle)
@ -830,27 +846,6 @@ object DirectUtils {
jumpActivity(context, bundle)
}
/**
* 跳转到下载管理器并开始下载 [gameId] 和 [packageName] 用于唯一确定一个下载文件
*/
@JvmStatic
fun directToDownloadManagerAndStartDownload(
context: Context,
gameId: String? = "",
packageName: String? = "",
entrance: String? = null
) {
DownloadHelper.createABrandNewDownloadTaskQuietly(gameId, packageName) {
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, DownloadManagerActivity.TAG)
bundle.putString(KEY_GAMEID, gameId)
bundle.putString(KEY_PACKAGENAME, packageName)
bundle.putBoolean(KEY_AUTO_DOWNLOAD, true)
jumpActivity(context, bundle)
}
}
@JvmStatic
fun directToDownloadManagerAndStartUpdate(
context: Context,
@ -864,7 +859,7 @@ object DirectUtils {
bundle.putString(KEY_GAMEID, gameId)
bundle.putString(KEY_PACKAGENAME, packageName)
bundle.putInt(BaseFragment_TabLayout.PAGE_INDEX, INDEX_UPDATE)
jumpActivity(context, bundle)
jumpActivityCompat(context, bundle)
}
@JvmStatic
@ -925,9 +920,9 @@ object DirectUtils {
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(browserIntent)
} catch (e: ActivityNotFoundException) {
} catch (e: Exception) {
e.printStackTrace()
Utils.toast(context, "跳转地址无效")
url.copyTextAndToast(context.getString(R.string.direct_to_external_browser_failed_toast))
}
}
@ -1125,7 +1120,8 @@ object DirectUtils {
act: String = "",
paginationType: String = "",
fieldId: String = "",
sectionName: String = ""
sectionName: String = "",
isHomeVideo: Boolean = false
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val bundle = Bundle()
@ -1143,6 +1139,7 @@ object DirectUtils {
bundle.putString(KEY_PAGINATION_TYPE, paginationType)
bundle.putString(KEY_FIELD_ID, fieldId)
bundle.putString(KEY_SECTION_NAME, sectionName)
bundle.putBoolean(KEY_IS_HOME_VIDEO, isHomeVideo)
jumpActivity(context, bundle)
} else {
DialogHelper.showVideoUnsupportedDialog(context)
@ -1969,8 +1966,14 @@ object DirectUtils {
* @param bbsId, 为空时搜索全范围的内容,不为空时搜索该 bbsId 对应的内容
*/
@JvmStatic
fun directToForumOrUserSearch(context: Context, bbsId: String, entrance: String) {
context.startActivity(ForumOrUserSearchActivity.getIntent(context, bbsId, entrance))
fun directToForumOrUserSearch(
context: Context,
bbsId: String,
entrance: String,
sourceEntrance: String,
forumName: String
) {
context.startActivity(ForumOrUserSearchActivity.getIntent(context, bbsId, entrance, sourceEntrance, forumName))
}
@JvmStatic
@ -2101,4 +2104,42 @@ object DirectUtils {
.withInt(BaseActivity_TabLayout.PAGE_INDEX, defaultTabIndex)
.navigation()
}
// 跳转游戏单合集详情
@JvmStatic
fun directToGameCollectionListDetail(
context: Context,
collectionId: String,
collectionName: String,
explain: String,
entrance: String = ""
) {
context.startActivity(
GameCollectionListDetailActivity.getIntent(
context,
GameCollectionListEntity(id = collectionId, name = collectionName, explain = explain),
entrance
)
)
}
/**
* 跳转到游戏订阅页面
* @param context 上下文
*/
@JvmStatic
fun directToServersSubscribedGameList(context: Context) {
context.startActivity(ServersSubscribedGameListActivity.getIntent(context))
}
/**
* 跳转到开服订阅页面
* @param context 上下文
*/
@JvmStatic
fun directToServersCalendarManagement(context: Context, entrance: String) {
CheckLoginUtils.checkLogin(context, entrance) {
context.startActivity(ServersCalendarManagementActivity.getIntent(context))
}
}
}

View File

@ -42,6 +42,7 @@ object DownloadDialogHelper {
gameName = gameEntity.name ?: "",
gameType = gameEntity.categoryChinese
)
callback.onCallback()
},
cancelClickCallback = {
SensorsBridge.trackGameDownloadDialogClick(
@ -50,7 +51,6 @@ object DownloadDialogHelper {
gameName = gameEntity.name ?: "",
gameType = gameEntity.categoryChinese
)
callback.onCallback()
},
touchOutsideCallback = {
SensorsBridge.trackGameDownloadDialogClick(

View File

@ -1,63 +0,0 @@
package com.gh.common.util
import com.gh.common.filter.RegionSettingHelper
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
import retrofit2.HttpException
/**
* 不想写这个类的,但是与其在一个糟糕的类里插入同样的代码,我想独立写一个类相较而已还没那么糟糕
*/
object DownloadHelper {
/**
* 根据 game_id 和 packageName 悄悄地开启一个下载任务,如果可以的话
* @param block 成功添加下载任务后执行的代码块
*/
fun createABrandNewDownloadTaskQuietly(gameId: String? = "", packageName: String? = "", block: () -> Unit) {
if (RegionSettingHelper.shouldThisGameBeFiltered(gameId)) {
return
}
RetrofitManager.getInstance()
.api
.getGameDigest(gameId)
.map(ApkActiveUtils.filterMapper)
.subscribeOn(Schedulers.io())
.subscribe(object : Response<GameEntity>() {
override fun onResponse(response: GameEntity?) {
response?.let {
if (response.getApk().size > 1) {
for (apk in response.getApk()) {
if (packageName == apk.packageName) {
DownloadManager.createDownload(
HaloApp.getInstance().application,
apk, response, "", EntranceConsts.ENTRANCE_RECOMMEND, "", false, null
)
block.invoke()
}
}
} else if (response.getApk().size == 1) {
DownloadManager.createDownload(
HaloApp.getInstance().application,
response, "", EntranceConsts.ENTRANCE_RECOMMEND, "", false, null
)
block.invoke()
}
}
}
override fun onFailure(e: HttpException?) {
e?.printStackTrace()
block.invoke()
}
})
}
}

View File

@ -122,7 +122,7 @@ object DownloadItemUtils {
fun updateItemWithReserveStatus(holder: GameViewHolder, gameEntity: GameEntity) {
if ("download" == gameEntity.reserveStatus) {
// 已上线
updateItem(holder.gameDownloadBtn.context, gameEntity, holder, false)
updateItem(holder.gameDownloadBtn.context, gameEntity, holder)
} else if ("appointment" == gameEntity.reserveStatus) {
// 已预约
holder.gameDownloadBtn.text = "已预约"
@ -133,25 +133,35 @@ object DownloadItemUtils {
}
fun updateItem(
context: Context, gameEntity: GameEntity, holder: GameViewHolder,
isShowPlatform: Boolean, hideDownloadBtnIfNoAvailableContent: Boolean
context: Context,
gameEntity: GameEntity,
holder: GameViewHolder,
hideDownloadBtnIfNoAvailableContent: Boolean
) {
updateItem(
context,
gameEntity,
holder,
isShowPlatform,
PluginLocation.only_game,
hideDownloadBtnIfNoAvailableContent,
null
context = context,
gameEntity = gameEntity,
holder = holder,
pluginLocation = PluginLocation.only_game,
hideDownloadBtnIfNoAvailableContent = hideDownloadBtnIfNoAvailableContent,
briefStyle = null
)
}
fun updateItem(
context: Context, gameEntity: GameEntity, holder: GameViewHolder,
isShowPlatform: Boolean, briefStyle: String?
context: Context,
gameEntity: GameEntity,
holder: GameViewHolder,
briefStyle: String?
) {
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game, false, briefStyle)
updateItem(
context = context,
gameEntity = gameEntity,
holder = holder,
pluginLocation = PluginLocation.only_game,
hideDownloadBtnIfNoAvailableContent = false,
briefStyle = briefStyle
)
}
@JvmStatic
@ -160,7 +170,6 @@ object DownloadItemUtils {
context: Context,
gameEntity: GameEntity,
holder: GameViewHolder,
isShowPlatform: Boolean,
pluginLocation: PluginLocation? = PluginLocation.only_game,
hideDownloadBtnIfNoAvailableContent: Boolean = false,
briefStyle: String? = null,
@ -286,12 +295,54 @@ object DownloadItemUtils {
}
}
} else if (gameEntity.getApk().size == 1) {
// 优先从下载管理获取 downloadEntity
var downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
// 来自于下载管理的实体快照
val entityFromDownloadManager = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
// 是否正在下载中
val isDownloading = entityFromDownloadManager != null && entityFromDownloadManager.status != DownloadStatus.done
// 是否已安装至本地
val isInstalledLocally = PackagesManager.isInstalled(gameEntity.getUniquePackageName())
// 来自于畅玩安装列表的实体快照,若存在,代表游戏已下载并成功安装
val entityFromInstalledVGame = VHelper.getVDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
// 是否已安装至畅玩
val isInstalledToVSpace = entityFromInstalledVGame != null
// 是否处于待安装状态 (仅本地安装有这个状态)
val isPendingToInstall = if (entityFromDownloadManager?.status != DownloadStatus.done) {
false
} else {
entityFromDownloadManager.isLocalDownloadInDualDownloadMode()
&& (!isInstalledLocally || entityFromDownloadManager.isUpdate)
}
// 找不到时,若类型为畅玩,尝试从畅玩数据库的快照中获取 downloadEntity。若存在代表游戏已下载并成功安装
if (downloadEntity == null && gameEntity.isVGame()) {
downloadEntity = VHelper.getVDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
// 列表按钮显示的优先级
// 1. 都未安装,且不存在下载任务,按后台配置显示的状态优先
// 2. 存在未完成的下载任务时,下载任务优先
// 3. 存在待安装任务时,待安装任务优先
// 4. 存在一个已安装,已安装的显示优先
// 5. 都已安装,按后台配置显示的状态优先
val isVGamePreferred = if (!isInstalledLocally && !isInstalledToVSpace && entityFromDownloadManager == null) {
gameEntity.isVGamePreferred()
} else if (isDownloading || isPendingToInstall) {
entityFromDownloadManager?.isVGameDownloadInDualDownloadMode() == true
} else if (isInstalledLocally && isInstalledToVSpace) {
gameEntity.isVGamePreferred()
} else if (isInstalledLocally) {
false
} else if (isInstalledToVSpace) {
true
} else {
gameEntity.isVGamePreferred()
}
val downloadEntity: DownloadEntity? = if (isDownloading) {
entityFromDownloadManager
} else if (isPendingToInstall) {
entityFromDownloadManager
} else {
if (isVGamePreferred) {
entityFromInstalledVGame ?: entityFromDownloadManager
} else {
entityFromDownloadManager
}
}
if (downloadEntity != null) {
@ -300,11 +351,12 @@ object DownloadItemUtils {
DownloadStatus.done -> {
if (downloadEntity.isSimulatorGame() && gameEntity.simulator != null) {
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn, pluginLocation)
} else if (downloadEntity.isVGame()) {
} else if (isVGamePreferred) {
buttonStyle =
if (PackagesManager.isCanUpdate(
downloadEntity.gameId,
downloadEntity.packageName
downloadEntity.packageName,
asVGame = true
)
) {
setText(R.string.update)
@ -333,8 +385,19 @@ object DownloadItemUtils {
return
}
buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
setText(R.string.install)
if (PackagesManager.isInstalled(downloadEntity.packageName) && !downloadEntity.isUpdate) {
// 双下载按钮快速安装时存在已下载的安装包过时,需要重新下载的情况
if (PackagesManager.isCanUpdate(downloadEntity.gameId, downloadEntity.packageName)) {
buttonStyle = DownloadButton.ButtonStyle.NORMAL
setText(R.string.update)
} else {
buttonStyle = DownloadButton.ButtonStyle.LAUNCH_OR_OPEN
setText(R.string.launch)
}
} else {
buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
setText(R.string.install)
}
}
buttonStyle =
if (downloadEntity.isPluggable && PackagesManager.isInstalled(downloadEntity.packageName)) {
@ -827,6 +890,7 @@ object DownloadItemUtils {
gameEntity.id,
gameEntity.name ?: "",
gameEntity.categoryChinese,
gameEntity.getApk().firstOrNull()?.format,
clickRunnable
)
}
@ -836,17 +900,21 @@ object DownloadItemUtils {
allStateClickCallback?.onCallback()
clickCallback?.onCallback()
ChainBuilder().apply {
DownloadChainBuilder().apply {
addHandler(GamePermissionHandler())
addHandler(CheckStoragePermissionHandler())
addHandler(CertificationHandler())
addHandler(VersionNumberHandler())
}
.setProcessEndCallback {
.setProcessEndCallback { _, _ ->
DownloadDialog.showDownloadDialog(view.context, gameEntity, traceEvent, entrance, location)
}
.buildHandlerChain()
?.handleRequest(context, gameEntity)
?.handleRequest(
context,
gameEntity,
GameUtils.shouldPerformAsVGame(gameEntity)
)
}
}
}
@ -866,8 +934,11 @@ object DownloadItemUtils {
val str = if (downloadBtn is DownloadButton) downloadBtn.text else context.getString(R.string.download)
if (gameEntity.getApk().isEmpty()) return
val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return
val shouldPerformAsVGame = GameUtils.shouldPerformAsVGame(gameEntity)
if (str == context.getString(R.string.download)) {
ChainBuilder().apply {
DownloadChainBuilder().apply {
addHandler(UnsupportedFeatureHandler())
addHandler(UpdateNewSimulatorHandler())
addHandler(GamePermissionHandler())
@ -879,14 +950,14 @@ object DownloadItemUtils {
addHandler(LandPageAddressHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback {
download(context, gameEntity, downloadBtn, entrance, location, it as Boolean, traceEvent)
.setProcessEndCallback { asVGame, isSubscribe ->
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
?.handleRequest(context, gameEntity)
?.handleRequest(context, gameEntity, shouldPerformAsVGame)
DataLogUtils.uploadGameLog(context, gameEntity.id, gameEntity.name, entrance)
} else if (str == context.getString(R.string.attempt)) {
ChainBuilder().apply {
DownloadChainBuilder().apply {
addHandler(UnsupportedFeatureHandler())
addHandler(UpdateNewSimulatorHandler())
addHandler(GamePermissionHandler())
@ -899,14 +970,14 @@ object DownloadItemUtils {
addHandler(OverseaDownloadHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback {
download(context, gameEntity, downloadBtn, entrance, location, it as Boolean, traceEvent)
.setProcessEndCallback { asVGame, isSubscribe ->
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
?.handleRequest(context, gameEntity)
?.handleRequest(context, gameEntity, shouldPerformAsVGame)
DataLogUtils.uploadGameLog(context, gameEntity.id, gameEntity.name, entrance)
} else if (str == context.getString(R.string.smooth)) {
ChainBuilder().apply {
DownloadChainBuilder().apply {
addHandler(UnsupportedFeatureHandler())
addHandler(GamePermissionHandler())
addHandler(PackageCheckHandler())
@ -919,25 +990,25 @@ object DownloadItemUtils {
addHandler(ValidateVSpaceHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback {
download(context, gameEntity, downloadBtn, entrance, location, it as Boolean, traceEvent)
.setProcessEndCallback { asVGame, isSubscribe ->
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
?.handleRequest(context, gameEntity)
?.handleRequest(context, gameEntity, shouldPerformAsVGame)
} else if (str.contains("")) {
if (gameEntity.pluggableCollection != null) {
DownloadDialog.showDownloadDialog(context, gameEntity, traceEvent, entrance, location)
} else {
ChainBuilder().apply {
DownloadChainBuilder().apply {
addHandler(DownloadDialogHelperHandler())
addHandler(CertificationHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback {
plugin(context, gameEntity, downloadBtn, entrance, location, it as Boolean, traceEvent)
.setProcessEndCallback { _, isSubscribe ->
plugin(context, gameEntity, downloadBtn, entrance, location, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
?.handleRequest(context, gameEntity)
?.handleRequest(context, gameEntity, shouldPerformAsVGame)
}
} else if (str == context.getString(R.string.install)) {
val downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apk.url)
@ -978,11 +1049,7 @@ object DownloadItemUtils {
}
}
if (gameEntity.isVGame()) {
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
} else {
install(context, gameEntity, position, adapter, refreshCallback)
}
install(context, gameEntity, position, adapter, refreshCallback)
} else if (str == context.getString(R.string.launch)) {
//启动模拟器游戏
if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
@ -994,7 +1061,16 @@ object DownloadItemUtils {
if (downloadEntity != null) {
val file = File(downloadEntity.path)
if (!file.exists()) {
download(context, gameEntity, downloadBtn, entrance, location, false, traceEvent)
download(
context = context,
gameEntity = gameEntity,
downloadBtn = downloadBtn,
entrance = entrance,
location = location,
asVGame = false,
isSubscribe = false,
traceEvent = traceEvent
)
return
}
NewFlatLogUtils.logSimulatorGameCardClick("启动")
@ -1003,21 +1079,17 @@ object DownloadItemUtils {
return
}
if (gameEntity.isVGame()) {
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
return
}
PackageLauncher.launchApp(context, gameEntity, gameEntity.getApk()[0].packageName)
PackageLauncher.launch(context, gameEntity)
} else if (str == context.getString(R.string.update)) {
if (gameEntity.isVGame()) {
if (shouldPerformAsVGame) {
VHelper.updateOrReDownload(gameEntity)
return
}
ChainBuilder()
DownloadChainBuilder()
.apply {
addHandler(LandPageAddressHandler())
}.setProcessEndCallback {
}.setProcessEndCallback { asVGame, _ ->
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk) {
DialogUtils.checkDownload(
context,
@ -1026,21 +1098,16 @@ object DownloadItemUtils {
gameEntity.name,
gameEntity.categoryChinese
) { isSubscribe: Boolean ->
update(context, gameEntity, entrance, location, isSubscribe, traceEvent)
update(context, gameEntity, entrance, location, asVGame, isSubscribe, traceEvent)
}
}
}
.buildHandlerChain()
?.handleRequest(context, gameEntity)
?.handleRequest(context, gameEntity, false)
} else {
var downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
// 找不到时,若类型为畅玩,尝试从畅玩数据库的快照中获取 downloadEntity。若存在代表游戏已下载并成功安装
if (downloadEntity == null && gameEntity.isVGame()) {
downloadEntity = VHelper.getVDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
}
// 还是找不到时,尝试从 gameEntity 里找已绑定的 downloadEntity
// 尝试从 gameEntity 里找已绑定的 downloadEntity
if (downloadEntity == null) {
downloadEntity = gameEntity.getEntryMap().getOrDefault(gameEntity.getUniquePlatform(), null)
}
@ -1078,6 +1145,7 @@ object DownloadItemUtils {
downloadBtn: View?,
entrance: String,
location: String,
asVGame: Boolean,
isSubscribe: Boolean,
traceEvent: ExposureEvent?
) {
@ -1088,7 +1156,7 @@ object DownloadItemUtils {
DownloadManager.createDownload(
context,
gameEntity,
context.getString(R.string.download),
asVGame,
entrance,
location,
isSubscribe,
@ -1123,7 +1191,7 @@ object DownloadItemUtils {
) {
val msg = FileUtils.isCanDownload(context, gameEntity.getApk()[0].size ?: "")
if (TextUtils.isEmpty(msg)) {
DownloadManager.createDownload(context, gameEntity, "插件化", entrance, location, isSubscribe, traceEvent)
DownloadManager.createDownload(context, gameEntity, false, entrance, location, isSubscribe, traceEvent)
ToastUtils.toast(gameEntity.name + "已加入下载队列")
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
val toast = context.getString(R.string.unsupported_browser_install_hint)
@ -1187,9 +1255,19 @@ object DownloadItemUtils {
gameEntity: GameEntity,
entrance: String,
location: String,
asVGame: Boolean,
isSubscribe: Boolean,
traceEvent: ExposureEvent?
) {
DownloadManager.createDownload(context, gameEntity, "更新", entrance, location, isSubscribe, traceEvent)
// 执行更新操作前,先清理历史下载任务,避免冲突
if (gameEntity.getApk().size == 1 && !asVGame) {
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
if (downloadEntity != null) {
DownloadManager.getInstance().cancel(downloadEntity.url)
}
}
DownloadManager.createDownload(context, gameEntity, asVGame, entrance, location, isSubscribe, traceEvent)
}
}

View File

@ -15,7 +15,7 @@ import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.getMetaExtra
import com.gh.gamecenter.common.utils.isSimulatorGame
import com.gh.gamecenter.common.utils.isVGame
import com.gh.gamecenter.common.utils.asVGame
import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.utils.SpeedUtils
@ -57,65 +57,65 @@ object DownloadNotificationHelper {
intent.putExtra(EntranceConsts.KEY_URL, entity.url)
intent.putExtra(EntranceConsts.KEY_PATH, entity.path)
intent.action = ACTION_INSTALL
} else if (entity.isVGame()) {
} else if (entity.asVGame()) {
intent.action = ACTION_VDOWNLOAD
} else {
intent.action = ACTION_DOWNLOAD
}
val pendingIntent = PendingIntent.getBroadcast(
HaloApp.getInstance().application,
downloadNotificationId,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel =
NotificationChannel(DOWNLOAD_CHANNEL_ID, DOWNLOAD_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
notificationManager.createNotificationChannel(channel)
}
val whenTime = 1000 * 60 * (System.currentTimeMillis() / 1000 / 60)
val builder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
.setContentTitle(entity.name)
.setSmallIcon(getNotificationIcon())
.setContentIntent(pendingIntent)
.setGroup(DOWNLOAD_GROUP_KEY)
.setWhen(whenTime)
if (xapkStatus == XapkUnzipStatus.FAILURE.name) {
builder.setContentText("" + entity.name + "》解压失败,点击查看详情~")
} else {
when (entity.status) {
DownloadStatus.downloading -> builder.setContentText(
String.format(
"%s(剩%s)",
SpeedUtils.getSpeed(entity.speed),
SpeedUtils.getRemainTime(entity.size, entity.progress, entity.speed * 1024)
)
)
DownloadStatus.done -> builder.setContentText("下载完成,点击立即安装")
DownloadStatus.waiting -> builder.setContentText("等待中")
DownloadStatus.subscribe,
DownloadStatus.timeout,
DownloadStatus.diskisfull,
DownloadStatus.diskioerror,
DownloadStatus.neterror -> builder.setContentText("已暂停连接WiFi自动下载")
else -> builder.setContentText("暂停中")
}
builder.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
}
when (entity.status) {
DownloadStatus.done -> {
builder.setSortKey("A")
builder.setOngoing(true) // 垃圾华为 sortKey 不起效 priority 也不起效,要将下载完成任务的通知置顶只能设置为 ongoing喷了
}
DownloadStatus.downloading -> builder.setSortKey("B")
else -> builder.setSortKey("C")
}
tryCatchInRelease {
val pendingIntent = PendingIntent.getBroadcast(
HaloApp.getInstance().application,
downloadNotificationId,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel =
NotificationChannel(DOWNLOAD_CHANNEL_ID, DOWNLOAD_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
notificationManager.createNotificationChannel(channel)
}
val whenTime = 1000 * 60 * (System.currentTimeMillis() / 1000 / 60)
val builder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
.setContentTitle(entity.name)
.setSmallIcon(getNotificationIcon())
.setContentIntent(pendingIntent)
.setGroup(DOWNLOAD_GROUP_KEY)
.setWhen(whenTime)
if (xapkStatus == XapkUnzipStatus.FAILURE.name) {
builder.setContentText("" + entity.name + "》解压失败,点击查看详情~")
} else {
when (entity.status) {
DownloadStatus.downloading -> builder.setContentText(
String.format(
"%s(剩%s)",
SpeedUtils.getSpeed(entity.speed),
SpeedUtils.getRemainTime(entity.size, entity.progress, entity.speed * 1024)
)
)
DownloadStatus.done -> builder.setContentText("下载完成,点击立即安装")
DownloadStatus.waiting -> builder.setContentText("等待中")
DownloadStatus.subscribe,
DownloadStatus.timeout,
DownloadStatus.diskisfull,
DownloadStatus.diskioerror,
DownloadStatus.neterror -> builder.setContentText("已暂停连接WiFi自动下载")
else -> builder.setContentText("暂停中")
}
builder.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
}
when (entity.status) {
DownloadStatus.done -> {
builder.setSortKey("A")
builder.setOngoing(true) // 垃圾华为 sortKey 不起效 priority 也不起效,要将下载完成任务的通知置顶只能设置为 ongoing喷了
}
DownloadStatus.downloading -> builder.setSortKey("B")
else -> builder.setSortKey("C")
}
val notification = builder.build() // 可能会抛出异常
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
if (xapkStatus == XapkUnzipStatus.FAILURE.name) {

View File

@ -22,7 +22,6 @@ import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.common.utils.NewFlatLogUtils
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.SimulatorEntity
@ -274,13 +273,13 @@ object DownloadObserver {
)
else -> {
if (!downloadEntity.isVGame()) {
if (!downloadEntity.asVGame()) {
Utils.toast(mApplication, downloadEntity.name + " - 下载完成")
}
}
}
} else {
if (!downloadEntity.isVGame()) {
if (!downloadEntity.asVGame()) {
Utils.toast(mApplication, downloadEntity.name + " - 下载完成")
}
}
@ -315,11 +314,9 @@ object DownloadObserver {
Utils.toast(mApplication, R.string.install_failure_hint)
downloadManager.cancel(downloadEntity.url)
} else {
if (PackageUtils.isCanLaunchSetup(
mApplication,
downloadEntity.path
) || downloadType == Constants.SMOOTH_GAME
) {
if (PackageUtils.isCanLaunchSetup(mApplication, downloadEntity.path)
|| downloadType == Constants.VGAME
|| downloadType == Constants.DUAL_DOWNLOAD_VGAME) {
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
tryWithDefaultCatch {
NewFlatLogUtils.logGameInstall(
@ -333,7 +330,7 @@ object DownloadObserver {
gameName = downloadEntity.name,
action = "自动安装"
)
PackageInstaller.install(mApplication, downloadEntity, false)
PackageInstaller.install(mApplication, downloadEntity, false, ignoreAsVGame = false)
}
} else {
// 弹出卸载提示框
@ -401,7 +398,7 @@ object DownloadObserver {
private fun statDoneEvent(downloadEntity: DownloadEntity) {
var type: ExposureUtils.DownloadType
if (downloadEntity.isUpdate) {
if (downloadEntity.isVGame()) {
if (downloadEntity.asVGame()) {
type = ExposureUtils.DownloadType.FUN_UPDATE
} else {
type = ExposureUtils.DownloadType.UPDATE
@ -410,7 +407,7 @@ object DownloadObserver {
}
}
} else {
type = if (downloadEntity.isVGame()) {
type = if (downloadEntity.asVGame()) {
ExposureUtils.DownloadType.FUN_DOWNLOAD
} else {
ExposureUtils.DownloadType.DOWNLOAD
@ -450,7 +447,7 @@ object DownloadObserver {
type
)
if (downloadEntity.isVGame()) {
if (downloadEntity.asVGame()) {
SensorsBridge.trackEventWithExposureSource(
"HaloFunGameDownloadDone",
exposureEvent?.source,
@ -464,11 +461,18 @@ object DownloadObserver {
"space_schema_type",
if (downloadEntity.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) "32位" else "64位"
)
} else if(downloadEntity.gameId == Constants.HALO_FUN_NEW_32_GAME_ID) {
SensorsBridge.trackEvent(
"HaloFunDownloadDone",
"space_schema_type",
"32位(新)"
)
}
if (downloadEntity.gameId != Constants.GHZS_GAME_ID
&& downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) != Constants.SIMULATOR_DOWNLOAD
&& downloadEntity.gameId != Constants.HALO_FUN_GAME_ID) {
&& downloadEntity.gameId != Constants.HALO_FUN_GAME_ID
&& downloadEntity.gameId != Constants.HALO_FUN_NEW_32_GAME_ID) {
SensorsBridge.trackEventWithExposureSource(
"DownloadProcessFinish",
exposureEvent?.source,
@ -481,7 +485,8 @@ object DownloadObserver {
"page_business_id", getCurrentPageEntity().pageBusinessId,
"last_page_name", getLastPageEntity().pageName,
"last_page_id", getLastPageEntity().pageId,
"last_page_business_id", getLastPageEntity().pageBusinessId
"last_page_business_id", getLastPageEntity().pageBusinessId,
"download_type", if (downloadEntity.asVGame()) "畅玩下载" else "本地下载",
)
}

View File

@ -28,7 +28,6 @@ import com.gh.gamecenter.common.view.dsbridge.CompletionHandler
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.core.utils.EmptyCallback
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.feature.entity.ApkEntity
@ -204,10 +203,16 @@ object GameActivityDownloadHelper {
) {
val apk = getApk(gameEntity, event, true) ?: return
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
val str = GameUtils.getDownloadBtnText(context, gameEntity, PluginLocation.only_game)
if (downloadEntity != null &&
str != context.getString(R.string.install) &&
str != context.getString(R.string.launch)
val str = GameUtils.getDownloadBtnText(
context = context,
gameEntity = gameEntity,
isFromList = true,
fixedAsVGame = false,
pluginLocation = PluginLocation.only_game
)
if (downloadEntity != null
&& str != context.getString(R.string.install)
&& str != context.getString(R.string.launch)
) {
ToastUtils.toast("${gameEntity.name}已加入下载队列")
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
@ -261,7 +266,7 @@ object GameActivityDownloadHelper {
GamePermissionDialogFragment.show((context as AppCompatActivity), gameEntity, gameEntity.info) {
CertificationDialog.showCertificationDialog(context, gameEntity) {
DialogUtils.checkDownload(context, apk.size, gameEntity.id, gameEntity.name, gameEntity.categoryChinese) { isSubscribe: Boolean ->
download(context, gameEntity, apk, isSubscribe, entrance, location, traceEvent)
download(context, gameEntity, apk, false, isSubscribe, entrance, location, traceEvent)
}
}
}
@ -287,7 +292,7 @@ object GameActivityDownloadHelper {
gameEntity.name,
gameEntity.categoryChinese
) { isSubscribe: Boolean ->
download(context, gameEntity, apk, isSubscribe, entrance, location, traceEvent)
download(context, gameEntity, apk, true, isSubscribe, entrance, location, traceEvent)
}
}
}
@ -354,12 +359,10 @@ object GameActivityDownloadHelper {
}
}
if (gameEntity.isVGame()) {
if (downloadEntity?.isVGameDownloadInDualDownloadMode() == true) {
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
} else {
downloadEntity?.run {
install(context, gameEntity, apk, this)
}
downloadEntity?.run { install(context, gameEntity, apk, this) }
}
}
@ -383,7 +386,16 @@ object GameActivityDownloadHelper {
if (simulatorDownloadEntity != null) {
val file = File(simulatorDownloadEntity.path)
if (!file.exists()) {
download(context, gameEntity, apk, false, entrance, location, traceEvent)
download(
context = context,
gameEntity = gameEntity,
apk = apk,
asVGame = false,
isSubscribe = false,
entrance = entrance,
location = location,
traceEvent = traceEvent
)
return
}
NewFlatLogUtils.logSimulatorGameCardClick("启动")
@ -392,15 +404,7 @@ object GameActivityDownloadHelper {
return
}
if (gameEntity.isVGame()) {
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
return
}
if (entrance.contains("我的游戏")) {
MtaHelper.onEvent("我的游戏_启动", "启动", gameEntity.name)
}
PackageLauncher.launchApp(context, gameEntity, gameEntity.getApk()[0].packageName)
PackageLauncher.launch(context, gameEntity)
}
// 处理更新状态
@ -463,6 +467,7 @@ object GameActivityDownloadHelper {
context: Context,
gameEntity: GameEntity,
apk: ApkEntity,
asVGame: Boolean,
isSubscribe: Boolean,
entrance: String,
location: String,
@ -470,11 +475,7 @@ object GameActivityDownloadHelper {
) {
val msg = FileUtils.isCanDownload(context, apk.size)
if (TextUtils.isEmpty(msg)) {
DownloadManager.createDownload(
context, apk, gameEntity, context.getString(
R.string.download
), entrance, location, isSubscribe, traceEvent
)
DownloadManager.createDownload(context, apk, gameEntity, asVGame, gameEntity.isDualBtnModeEnabled(), entrance, location, isSubscribe, traceEvent)
ToastUtils.toast("${gameEntity.name}已加入下载队列")
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
val toast = context.getString(R.string.unsupported_browser_install_hint)
@ -499,7 +500,7 @@ object GameActivityDownloadHelper {
) {
val msg = FileUtils.isCanDownload(context, apk.size)
if (TextUtils.isEmpty(msg)) {
DownloadManager.createDownload(context, apk, gameEntity, "插件化", entrance, location, isSubscribe, traceEvent)
DownloadManager.createDownload(context, apk, gameEntity, false, false, entrance, location, isSubscribe, traceEvent)
ToastUtils.toast("${gameEntity.name}已加入下载队列")
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
val toast = context.getString(R.string.unsupported_browser_install_hint)
@ -554,7 +555,7 @@ object GameActivityDownloadHelper {
isSubscribe: Boolean,
traceEvent: ExposureEvent?
) {
DownloadManager.createDownload(context, apk, gameEntity, "更新", entrance, location, isSubscribe, traceEvent)
DownloadManager.createDownload(context, apk, gameEntity, false, false, entrance, location, isSubscribe, traceEvent)
ToastUtils.toast("${gameEntity.name}已加入下载队列")
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
val toast = context.getString(R.string.unsupported_browser_install_hint)

View File

@ -1,272 +0,0 @@
package com.gh.common.util;
import android.content.Context;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.gh.common.constant.Config;
import com.gh.common.simulator.SimulatorGameManager;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.feature.view.DownloadButton;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.R;
import com.gh.gamecenter.core.AppExecutor;
import com.gh.gamecenter.feature.entity.ApkEntity;
import com.gh.gamecenter.feature.entity.ApkLink;
import com.gh.gamecenter.feature.entity.GameCollectionEntity;
import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.entity.GameUpdateEntity;
import com.gh.gamecenter.feature.entity.PluginLocation;
import com.gh.gamecenter.feature.entity.SettingsEntity;
import com.gh.gamecenter.manager.PackagesManager;
import com.gh.vspace.VHelper;
import com.lightgame.download.DownloadEntity;
import com.lightgame.download.DownloadStatus;
import java.util.ArrayList;
import java.util.List;
public class GameUtils {
/**
* 去除与重复sourceList相同的数据
*/
public static List<GameEntity> removeDuplicateData(List<GameEntity> sourceList, List<GameEntity> rawList) {
if (sourceList == null || sourceList.isEmpty()
|| rawList == null || rawList.isEmpty()) {
return rawList;
}
String id;
for (int i = 0; i < rawList.size(); i++) {
id = rawList.get(i).getId();
for (GameEntity gameEntity : sourceList) {
if (id.equals(gameEntity.getId())) {
rawList.remove(i);
i--;
break;
}
}
}
return rawList;
}
/**
* 设置下载按钮状态
*/
public static void setDownloadBtnStatus(Context context, GameEntity gameEntity, DownloadButton downloadBtn, PluginLocation pluginLocation) {
// getDownloadBtnText 里包括查询数据库、根据包名读取包体 meta 信息等
AppExecutor.getLightWeightIoExecutor().execute(() -> {
String status = getDownloadBtnText(context, gameEntity, pluginLocation);
AppExecutor.getUiExecutor().execute(() -> {
downloadBtn.setText(status);
if (context.getString(R.string.pluggable).equals(status)) {
downloadBtn.setButtonStyle(DownloadButton.ButtonStyle.PLUGIN);
String pluginDesc = gameEntity.getPluginDesc();
if (pluginDesc.length() > 3) pluginDesc = pluginDesc.substring(0, 3);
downloadBtn.setText((pluginDesc + ""));
} else {
downloadBtn.setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
}
});
});
}
/**
* 获取下载按钮文案 (相对耗时,请优先在子线程调用)
*/
@WorkerThread
public static String getDownloadBtnText(Context context, GameEntity gameEntity, PluginLocation pluginLocation) {
if (gameEntity.getApk().size() > 1) {
return "";
}
int doneCount = 0; // 下载完成数量
int pluginCount = 0; // 可插件化数量
int updateCount = 0; // 可更新数量
int installCount = 0; // 已安装数量
boolean isRelatedEmulatorInstalled = false; // 若该游戏是模拟器游戏时其对应的模拟器是否已经安装
boolean isInstalledNewSimulator = false;// 是否安装新模拟器
DownloadEntity downloadEntity = null;
Object gh_id;
apkFor:
for (ApkEntity apkEntity : gameEntity.getApk()) {
// filter by packageName
SettingsEntity settings = Config.getSettings();
if (settings != null && gameEntity.getApk().size() > 1) {
for (String pkgName : settings.getGameDownloadBlackList()) {
if (pkgName.equals(apkEntity.getPackageName())) {
continue apkFor;
}
}
}
downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity);
// 在下载管理找不到下载实体,并且为畅玩游戏的时候到畅玩数据库里找
if (downloadEntity == null && gameEntity.isVGame()) {
downloadEntity = VHelper.getVDownloadEntitySnapshot(gameEntity.getId(), apkEntity.getPackageName());
}
if (downloadEntity != null) {
if (downloadEntity.getStatus().equals(DownloadStatus.done)) {
doneCount++;
} else if (downloadEntity.isPluggable()) {
pluginCount++;
} else if (downloadEntity.isUpdate()) {
updateCount++;
}
}
if (PackagesManager.INSTANCE.isCanUpdate(gameEntity.getId(), apkEntity.getPackageName())) {
updateCount++;
}
if (PackagesManager.isInstalled(apkEntity.getPackageName())) {
gh_id = PackageUtils.getMetaData(context, apkEntity.getPackageName(), "gh_id");
if (!TextUtils.isEmpty(apkEntity.getGhVersion())
&& !PackageUtils.isSignedByGh(context, apkEntity.getPackageName())
&& apkEntity.isShowPlugin(pluginLocation)) {
pluginCount++;
} else if (gh_id == null
|| gh_id.equals(gameEntity.getId())
// 当使用镜像时,可能会存在镜像 gh_id 与当前游戏 id 不一样的情况,这时也让它通过,避免装完还是显示`下载`
|| gameEntity.shouldUseMirrorInfo()) {
installCount++;
}
}
if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(context);
DownloadEntity simulatorDownloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apkEntity.getUrl());
if (simulatorDownloadEntity != null && gameEntity.getSimulator() != null) {
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(context, gameEntity.getSimulator().getApk().getPackageName());
if (isInstalled) {
installCount++;
isRelatedEmulatorInstalled = true;
} else {
doneCount++;
}
}
}
}
if ((isRelatedEmulatorInstalled || isInstalledNewSimulator) && doneCount != 0) {
return context.getString(R.string.launch);
}
if (gameEntity.isVGame()) {
// 如果 doneCount 为 0 或者数据库为空
// 表明本地并没有此游戏的数据库数据,需要重新下载
if (doneCount == 0
|| downloadEntity == null
|| !VHelper.isInstalled(downloadEntity.getPackageName())) {
installCount = 0;
} else {
doneCount = 0;
installCount = 1;
}
}
if (doneCount != 0) {
return context.getString(R.string.install);
} else if (pluginCount != 0 && !SimulatorGameManager.isSimulatorGame(gameEntity)) {
return context.getString(R.string.pluggable);
} else if (updateCount != 0 && !SimulatorGameManager.isSimulatorGame(gameEntity)) {
return context.getString(R.string.update);
} else if (installCount != 0) {
return context.getString(R.string.launch);
} else if ("demo".equals(gameEntity.getDownloadStatus())) {
return context.getString(R.string.attempt);
} else {
if (gameEntity.isVGame()) {
return context.getString(R.string.smooth);
} else {
if (Constants.V_GAME.equals(gameEntity.getDownloadStatus())
|| Constants.V_GAME_32.equals(gameEntity.getDownloadStatus())) {
GameEntity.GameCategory gameCategory = gameEntity.getGameCategory();
if (gameCategory.equals(GameEntity.GameCategory.ONLINE_GAME)
|| gameCategory.equals(GameEntity.GameCategory.INTERNATIONAL_ONLINE_GAME)) {
return context.getString(R.string.download);
} else {
return context.getString(R.string.attempt);
}
} else {
return context.getString(R.string.download);
}
}
}
}
/**
* 获取GameUpdateEntity(插件化)
*/
public static GameUpdateEntity getGameUpdateEntity(GameEntity gameEntity, ApkEntity apkEntity) {
GameUpdateEntity gameUpdateEntity = new GameUpdateEntity();
gameUpdateEntity.setId(gameEntity.getId());
gameUpdateEntity.setIcon(gameEntity.getIcon());
gameUpdateEntity.setRawIcon(gameEntity.getRawIcon());
gameUpdateEntity.setIconSubscript(gameEntity.getIconSubscript());
gameUpdateEntity.setIconFloat(gameEntity.getIconFloat());
gameUpdateEntity.setName(gameEntity.getName());
gameUpdateEntity.setPackageName(apkEntity.getPackageName());
gameUpdateEntity.setSize(apkEntity.getSize());
gameUpdateEntity.setVersion(apkEntity.getVersion());
gameUpdateEntity.setGhVersion(apkEntity.getGhVersion());
gameUpdateEntity.setUrl(apkEntity.getUrl());
gameUpdateEntity.setPlatform(apkEntity.getPlatform());
gameUpdateEntity.setEtag(apkEntity.getEtag());
gameUpdateEntity.setPluggable(true);
gameUpdateEntity.setTagStyle(gameEntity.getTagStyle());
gameUpdateEntity.setBrief(gameEntity.getBrief());
gameUpdateEntity.setPlugin(apkEntity.getPlugin());
gameUpdateEntity.setDownload(gameEntity.getDownload());
gameUpdateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
gameUpdateEntity.setPluginDesc(gameEntity.getPluginDesc());
gameUpdateEntity.setFormat(apkEntity.getFormat());
gameUpdateEntity.setCurrentVersion(PackageUtils.getVersionNameByPackageName(apkEntity.getPackageName()));
gameUpdateEntity.setCategory(gameEntity.getCategory());
GameCollectionEntity pluggableCollection = getPluggableCollectionFromGameEntity(gameEntity, apkEntity.getPackageName());
if (pluggableCollection != null) {
gameUpdateEntity.setPluggableCollection(pluggableCollection);
}
return gameUpdateEntity;
}
@Nullable
public static GameCollectionEntity getPluggableCollectionFromGameEntity(GameEntity gameEntity, String targetPkg) {
// 添加插件化包所在的合集
for (GameCollectionEntity collectionEntity : gameEntity.getCollection()) {
if (collectionEntity.getPackages().contains(targetPkg)) {
ArrayList<ApkEntity> saveApkEntity = new ArrayList<>();
for (String pkg : collectionEntity.getPackages()) {
for (ApkEntity apk : gameEntity.getApk()) {
if (pkg.equals(apk.getPackageName())) {
saveApkEntity.add(apk);
break;
}
}
}
ArrayList<ApkLink> apkLinks = gameEntity.getApkLink();
if (apkLinks != null) {
for (ApkLink apkLink : apkLinks) {
if (apkLink.getCollection().equals(collectionEntity.getId())) {
ApkEntity element = new ApkEntity();
element.setApkLink(apkLink);
if (saveApkEntity.size() > apkLink.getSort()) {
saveApkEntity.add(apkLink.getSort(), element);
} else {
saveApkEntity.add(element);
}
}
}
}
collectionEntity.setSaveApkEntity(saveApkEntity);
return collectionEntity;
}
}
return null;
}
}

View File

@ -0,0 +1,343 @@
package com.gh.common.util
import android.content.Context
import android.text.TextUtils
import androidx.annotation.WorkerThread
import com.gh.common.constant.Config
import com.gh.common.simulator.SimulatorGameManager.findDownloadEntityByUrl
import com.gh.common.simulator.SimulatorGameManager.isNewSimulatorInstalled
import com.gh.common.simulator.SimulatorGameManager.isSimulatorGame
import com.gh.download.DownloadManager
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.isLocalDownloadInDualDownloadMode
import com.gh.gamecenter.common.utils.isVGameDownloadInDualDownloadMode
import com.gh.gamecenter.core.AppExecutor.lightWeightIoExecutor
import com.gh.gamecenter.core.AppExecutor.uiExecutor
import com.gh.gamecenter.entity.GameUpdateEntity
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.feature.view.DownloadButton
import com.gh.gamecenter.manager.PackagesManager
import com.gh.gamecenter.manager.PackagesManager.isCanUpdate
import com.gh.vspace.VHelper
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
object GameUtils {
/**
* 去除与重复sourceList相同的数据
*/
fun removeDuplicateData(sourceList: MutableList<GameEntity>?, rawList: MutableList<GameEntity>?): MutableList<GameEntity>? {
if (sourceList.isNullOrEmpty() || rawList.isNullOrEmpty()) {
return rawList
}
var id: String
var i = 0
while (i < rawList.size) {
id = rawList[i].id
for (gameEntity in sourceList) {
if (id == gameEntity.id) {
rawList.removeAt(i)
i--
break
}
}
i++
}
return rawList
}
/**
* 设置下载按钮状态
*/
fun setDownloadBtnStatus(
context: Context,
gameEntity: GameEntity,
downloadBtn: DownloadButton,
pluginLocation: PluginLocation?
) {
// getDownloadBtnText 里包括查询数据库、根据包名读取包体 meta 信息等
lightWeightIoExecutor.execute {
val status = getDownloadBtnText(
context = context,
gameEntity = gameEntity,
isFromList = true,
fixedAsVGame = false,
pluginLocation = pluginLocation
)
uiExecutor.execute {
downloadBtn.text = status
if (context.getString(R.string.pluggable) == status) {
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.PLUGIN
var pluginDesc = gameEntity.pluginDesc
if (pluginDesc.length > 3) pluginDesc = pluginDesc.substring(0, 3)
downloadBtn.text = pluginDesc + ""
} else {
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
}
}
}
}
/**
* 获取下载按钮文案 (相对耗时,请优先在子线程调用)
*
* @param isFromList 调用方是否来源自普通列表 (普通列表根据优先级确定是显示成畅玩状态还是普通下载状态)
* @param fixedAsVGame 固定以畅玩游戏的类型来获取状态
*/
@WorkerThread
@JvmStatic
fun getDownloadBtnText(context: Context,
gameEntity: GameEntity,
isFromList: Boolean,
fixedAsVGame: Boolean,
pluginLocation: PluginLocation?): String {
if (gameEntity.getApk().size > 1) {
return ""
}
var doneCount = 0 // 下载完成数量
var pluginCount = 0 // 可插件化数量
var updateCount = 0 // 可更新数量
var installCount = 0 // 已安装数量
var isRelatedEmulatorInstalled = false // 若该游戏是模拟器游戏时其对应的模拟器是否已经安装
var isInstalledNewSimulator = false // 是否安装新模拟器
var downloadEntity: DownloadEntity? = null
var performAsVGame = false // 是否使用了畅玩作为 downloadEntity
var gh_id: Any?
apkFor@ for (apkEntity in gameEntity.getApk()) {
val isInstalledLocally = PackagesManager.isInstalled(apkEntity.packageName)
// filter by packageName
val settings = Config.getSettings()
if (settings != null && gameEntity.getApk().size > 1) {
for (pkgName in settings.gameDownloadBlackList) {
if (pkgName == apkEntity.packageName) {
continue@apkFor
}
}
}
downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
// 已安装的畅玩游戏实体
val vGameDownloadEntity = VHelper.getVDownloadEntitySnapshot(gameEntity.id, apkEntity.packageName)
performAsVGame = if (fixedAsVGame) {
true
} else if (isFromList) {
if (vGameDownloadEntity == null && isInstalledLocally) {
false
} else {
gameEntity.isVGamePreferred()
}
} else {
false
}
// 畅玩状态优先,且畅玩实体不为空时将 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
}
if (downloadEntity != null) {
if (downloadEntity.status == DownloadStatus.done) {
doneCount++
} else if (downloadEntity.isPluggable) {
pluginCount++
} else if (downloadEntity.isUpdate) {
updateCount++
}
}
if (isCanUpdate(gameEntity.id, apkEntity.packageName, performAsVGame)) {
updateCount++
}
if (isInstalledLocally) {
gh_id = PackageUtils.getMetaData(context, apkEntity.packageName, "gh_id")
if (!TextUtils.isEmpty(apkEntity.ghVersion)
&& !PackageUtils.isSignedByGh(context, apkEntity.packageName)
&& apkEntity.isShowPlugin(pluginLocation!!)
) {
pluginCount++
} else if (gh_id == null || gh_id == gameEntity.id || gameEntity.shouldUseMirrorInfo()) {
installCount++
}
}
if (isSimulatorGame(gameEntity)) {
isInstalledNewSimulator = isNewSimulatorInstalled(context)
val simulatorDownloadEntity = findDownloadEntityByUrl(apkEntity.url)
if (simulatorDownloadEntity != null && gameEntity.simulator != null) {
val isInstalled =
PackageUtils.isInstalledFromAllPackage(context, gameEntity.simulator!!.apk!!.packageName)
if (isInstalled) {
installCount++
isRelatedEmulatorInstalled = true
} else {
doneCount++
}
}
}
}
if ((isRelatedEmulatorInstalled || isInstalledNewSimulator) && doneCount != 0) {
return context.getString(R.string.launch)
}
if (performAsVGame) {
// 如果 doneCount 为 0 或者数据库为空
// 表明本地并没有此游戏的数据库数据,需要重新下载
if (doneCount == 0 || downloadEntity == null || !VHelper.isInstalled(downloadEntity.packageName)) {
installCount = 0
} else {
doneCount = 0
installCount = 1
}
} else {
if (gameEntity.isDualBtnModeEnabled()) {
// 双下载按钮模式下,若非更新,排除已安装的情况来影响按钮状态
if (installCount != 0 && doneCount != 0 && downloadEntity?.isUpdate == false) {
doneCount = 0
}
}
}
return if (doneCount != 0) {
context.getString(R.string.install)
} else if (pluginCount != 0 && !isSimulatorGame(gameEntity)) {
context.getString(R.string.pluggable)
} else if (updateCount != 0 && !isSimulatorGame(gameEntity)) {
context.getString(R.string.update)
} else if (installCount != 0) {
context.getString(R.string.launch)
} else if ("demo" == gameEntity.downloadStatus) {
context.getString(R.string.attempt)
} else {
if (performAsVGame) {
context.getString(R.string.smooth)
} else {
// if (Constants.V_GAME == gameEntity.downloadStatus || Constants.V_GAME_32 == gameEntity.downloadStatus) {
// val gameCategory = gameEntity.getGameCategory()
// if (gameCategory == GameEntity.GameCategory.ONLINE_GAME
// || gameCategory == GameEntity.GameCategory.INTERNATIONAL_ONLINE_GAME) {
// context.getString(R.string.download)
// } else {
// context.getString(R.string.attempt)
// }
// } else {
context.getString(R.string.download)
// }
}
}
}
/**
* 获取GameUpdateEntity(插件化)
*/
fun getGameUpdateEntity(gameEntity: GameEntity, apkEntity: ApkEntity): GameUpdateEntity {
val gameUpdateEntity = GameUpdateEntity()
gameUpdateEntity.id = gameEntity.id
gameUpdateEntity.icon = gameEntity.icon
gameUpdateEntity.rawIcon = gameEntity.rawIcon
gameUpdateEntity.iconSubscript = gameEntity.iconSubscript
gameUpdateEntity.iconFloat = gameEntity.iconFloat
gameUpdateEntity.name = gameEntity.name
gameUpdateEntity.packageName = apkEntity.packageName
gameUpdateEntity.size = apkEntity.size
gameUpdateEntity.version = apkEntity.version
gameUpdateEntity.ghVersion = apkEntity.ghVersion
gameUpdateEntity.url = apkEntity.url
gameUpdateEntity.platform = apkEntity.getPlatform()
gameUpdateEntity.etag = apkEntity.etag
gameUpdateEntity.isPluggable = true
gameUpdateEntity.tagStyle = gameEntity.tagStyle
gameUpdateEntity.brief = gameEntity.brief
gameUpdateEntity.plugin = apkEntity.plugin
gameUpdateEntity.download = gameEntity.download
gameUpdateEntity.indexPlugin = gameEntity.indexPlugin
gameUpdateEntity.pluginDesc = gameEntity.pluginDesc
gameUpdateEntity.format = apkEntity.format
gameUpdateEntity.currentVersion = PackageUtils.getVersionNameByPackageName(apkEntity.packageName)
gameUpdateEntity.category = gameEntity.category
val pluggableCollection = getPluggableCollectionFromGameEntity(gameEntity, apkEntity.packageName)
if (pluggableCollection != null) {
gameUpdateEntity.pluggableCollection = pluggableCollection
}
return gameUpdateEntity
}
@JvmStatic
fun getPluggableCollectionFromGameEntity(gameEntity: GameEntity, targetPkg: String?): GameCollectionEntity? {
// 添加插件化包所在的合集
for (collectionEntity in gameEntity.collection) {
if (collectionEntity.packages.contains(targetPkg)) {
val saveApkEntity = ArrayList<ApkEntity>()
for (pkg in collectionEntity.packages) {
for (apk in gameEntity.getApk()) {
if (pkg == apk.packageName) {
saveApkEntity.add(apk)
break
}
}
}
val apkLinks = gameEntity.apkLink
if (apkLinks != null) {
for (apkLink in apkLinks) {
if (apkLink.collection == collectionEntity.id) {
val element = ApkEntity()
element.apkLink = apkLink
if (saveApkEntity.size > apkLink.sort) {
saveApkEntity.add(apkLink.sort, element)
} else {
saveApkEntity.add(element)
}
}
}
}
collectionEntity.saveApkEntity = saveApkEntity
return collectionEntity
}
}
return null
}
/**
* 是否以畅玩游戏的形式来处理
*/
@JvmStatic
fun shouldPerformAsVGame(gameEntity: GameEntity): Boolean {
var performActionAsVGame = false
if (gameEntity.getApk().size != 1) {
performActionAsVGame = false
} else {
when (gameEntity.getGameDownloadButtonMode()) {
GameEntity.GAME_DOWNLOAD_BUTTON_MODE_VGAME -> performActionAsVGame = true
GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DOWNLOAD -> performActionAsVGame = false
GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DUAL -> {
val packageName = gameEntity.getApk().first().packageName
val isInstalledAtDevice = PackagesManager.isInstalled(packageName)
val isInstalledAtVSpace = VHelper.getVDownloadEntitySnapshot(gameEntity.id, packageName) != null
performActionAsVGame = if (isInstalledAtDevice && isInstalledAtVSpace) {
gameEntity.isVGamePreferred()
} else if (isInstalledAtDevice) {
false
} else if (isInstalledAtVSpace) {
true
} else {
gameEntity.isVGamePreferred()
}
}
}
}
return performActionAsVGame
}
}

View File

@ -1,14 +1,15 @@
package com.gh.common.util
import com.gh.gamecenter.common.entity.Display
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.common.entity.Display
import com.gh.gamecenter.entity.SubjectRecommendEntity
import com.halo.assistant.HaloApp
object HomeBottomBarHelper {
private const val GAME_BAR_KEY = "game_bar_key"
private const val VIDEO_BAR_KEY = "video_bar_key"
@JvmStatic
fun getDefaultGameBarData(): SubjectRecommendEntity {
@ -28,6 +29,7 @@ object HomeBottomBarHelper {
type = "block",
text = "游戏库",
name = "游戏库",
position = 2,
iconSelect = "https://resource.ghzs.com/image/game/library/entrance/5e183202913fbd002c75f247.png",
iconUnselect = "https://resource.ghzs.com/image/game/library/entrance/5e1831fd913fbd003024641e.png",
animationCode = animationCode,
@ -36,8 +38,42 @@ object HomeBottomBarHelper {
)
}
@JvmStatic
fun getDefaultVideoData(): SubjectRecommendEntity {
try {
val json = SPUtils.getString(VIDEO_BAR_KEY)
if (json.isNotEmpty()) {
return GsonUtils.fromJson(json, SubjectRecommendEntity::class.java)
}
} catch (ignore: Exception) {
}
return getDefaultVideoEntity()
}
@JvmStatic
fun getDefaultVideoEntity(): SubjectRecommendEntity {
val animationCode = HaloApp.getInstance().application.assets
.open("lottie/tab_video.json")
.bufferedReader().use { it.readText() }
return SubjectRecommendEntity(
type = "video_stream",
text = "视频",
name = "视频",
position = 4,
animationCode = animationCode,
default = false,
display = Display()
)
}
@JvmStatic
fun updateDefaultGameBarData(data: SubjectRecommendEntity) {
SPUtils.setString(GAME_BAR_KEY, data.toJson())
}
@JvmStatic
fun updateDefaultVideoBarData(data: SubjectRecommendEntity) {
SPUtils.setString(VIDEO_BAR_KEY, data.toJson())
}
}

View File

@ -11,6 +11,7 @@ import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.entity.CommunityEntity;
import com.gh.gamecenter.common.entity.ExposureEntity;
import com.gh.gamecenter.common.exposure.ExposureSource;
import com.gh.gamecenter.common.exposure.meta.Meta;
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.common.loghub.LoghubUtils;
@ -24,7 +25,6 @@ import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.feature.entity.PackageDialogEntity;
import com.gh.gamecenter.feature.entity.Questions;
import com.gh.gamecenter.feature.exposure.ExposureEvent;
import com.gh.gamecenter.common.exposure.ExposureSource;
import com.gh.gamecenter.login.user.UserManager;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.Utils;
@ -262,6 +262,7 @@ public class LogUtils {
object.put("version", PackageUtils.getGhVersionName());
object.put("channel", HaloApp.getInstance().getChannel());
object.put("dia", MetaUtil.getBase64EncodedAndroidId());
object.put("oaid", MetaUtil.INSTANCE.getMeta().getOaid());
object.put("time", Utils.getTime(context));
object.put("network", DeviceUtils.getNetwork(context));
object.put("user_id", UserManager.getInstance().getUserId());
@ -286,6 +287,7 @@ public class LogUtils {
metaObject.put("appVersion", meta.getAppVersion());
metaObject.put("channel", meta.getChannel());
metaObject.put("gid", meta.getGid());
metaObject.put("oaid", meta.getOaid());
metaObject.put("jnfj", MetaUtil.getBase64EncodedIMEI());
metaObject.put("mac", meta.getMac());
metaObject.put("manufacturer", meta.getManufacturer());
@ -568,7 +570,7 @@ public class LogUtils {
}
public static void uploadSearchGame(String event, String location, String key, String searchType) {
uploadSearchClick(event, location, key, searchType, "", "", 0, false);
uploadSearchClick(event, location, key, searchType, "", "", 0, false, "", "");
}
/**
@ -581,7 +583,9 @@ public class LogUtils {
String gameId,
String gameName,
int mirrorDataPosition,
Boolean isAdData) {
Boolean isAdData,
String adSpaceId,
String gameAdSourceId) {
JSONObject object = new JSONObject();
JSONObject payload = new JSONObject();
try {
@ -602,6 +606,8 @@ public class LogUtils {
payload.put("is_mirror2_data", true);
}
payload.put("is_ad_data", isAdData);
payload.put("ad_space_id", adSpaceId);
payload.put("game_ad_source_id", gameAdSourceId);
object.put(KEY_PAY_LOAD, payload);
} catch (JSONException e) {
e.printStackTrace();

View File

@ -566,6 +566,153 @@ object NewFlatLogUtils {
log(json)
}
// 进入社区搜索页面事件
@JvmStatic
fun logAccessToBbsSearch(
location: String,
bbsId: String
) {
json {
KEY_EVENT to "access_to_bbs_search"
"location" to location
"bbs_id" to bbsId
parseAndPutMeta()()
}.let(::log)
}
@JvmStatic
fun logSearchingContent(
location: String,
bbsId: String,
searchType: String,
key: String
) {
json {
KEY_EVENT to "searching_content"
"location" to location
"bbs_id" to bbsId
"search_type" to searchType
"key" to key
parseAndPutMeta()()
}.let(::log)
}
@JvmStatic
fun logSearchContentClick(
location: String,
bbsId: String,
searchType: String,
key: String,
contentId: String,
type: String,
title: String,
sequence: Int,
button: String
) {
json {
KEY_EVENT to "search_content_click"
"location" to location
"bbs_id" to bbsId
"search_type" to searchType
"key" to key
"content_id" to contentId
"type" to type
"title" to title
"sequence" to sequence
"button" to button
parseAndPutMeta()()
}.let(::log)
}
@JvmStatic
fun logSearchContentExposure(
location: String,
bbsId: String,
searchType: String,
searchKey: String,
contentId: String,
type: String,
title: String,
sequence: Int
) {
json {
KEY_EVENT to "search_content_exposure"
"location" to location
"bbs_id" to bbsId
"search_type" to searchType
"key" to searchKey
"content_id" to contentId
"type" to type
"title" to title
"sequence" to sequence
parseAndPutMeta()()
}.let(::log)
}
@JvmStatic
fun logSearchBbs(
searchType: String,
searchKey: String
) {
json {
KEY_EVENT to "search_bbs"
"search_type" to searchType
"key" to searchKey
parseAndPutMeta()()
}.let(::log)
}
@JvmStatic
fun logSearchBbsClick(
searchType: String,
searchKey: String,
bbsId: String,
sequence: Int,
name: String
) {
json {
KEY_EVENT to "search_bbs_click"
"search_type" to searchType
"key" to searchKey
"bbs_id" to bbsId
"sequence" to sequence
"name" to name
parseAndPutMeta()()
}.let(::log)
}
@JvmStatic
fun logSearchUser(
searchType: String,
searchKey: String
) {
json {
KEY_EVENT to "search_user"
"search_type" to searchType
"key" to searchKey
parseAndPutMeta()()
}.let(::log)
}
@JvmStatic
fun logSearchUserClick(
searchType: String,
searchKey: String,
userId: String,
name: String,
sequence: Int
) {
json {
KEY_EVENT to "search_user_click"
"search_type" to searchType
"key" to searchKey
"user_id" to userId
"name" to name
"sequence" to sequence
parseAndPutMeta()()
}.let(::log)
}
//点击社区-搜索页返回按钮
@JvmStatic
fun logClickSearchReturn(searchKey: String) {
@ -2327,7 +2474,10 @@ object NewFlatLogUtils {
blockId: String,
collectionName: String,
collectionId: String,
text: String
text: String,
linkType: String = "",
linkId: String = "",
linkText: String = ""
) {
val json = json {
KEY_EVENT to "game_list_collection_click"
@ -2337,6 +2487,9 @@ object NewFlatLogUtils {
"game_list_collection_id" to collectionId
"game_list_collection_name" to collectionName
"text" to text
"link_type" to linkType
"link_id" to linkId
"link_text" to linkText
parseAndPutMeta().invoke(this)
}
log(json)
@ -2439,4 +2592,69 @@ object NewFlatLogUtils {
}
log(json)
}
// 点击个人主页的认证文案事件
@JvmStatic
fun logClickAuthText(linkType: String, linkId: String, linkText: String, userId: String, text: String) {
val json = json {
KEY_EVENT to "click_authentication_text"
"link_type" to linkType
"link_id" to linkId
"link_text" to linkText
"link_user_id" to userId
"text" to text
parseAndPutMeta().invoke(this)
}
log(json)
}
// 关闭游戏广告
@JvmStatic
fun logCloseGameAd(
adSpaceId: String,
name: String,
position: String,
type: String,
gameAdSourceId: String,
gameAdSourceName: String
) {
val json = json {
KEY_EVENT to "close_game_ad"
"ad_space_id" to adSpaceId
"name" to name
"position" to position
"type" to type
"game_ad_source_id" to gameAdSourceId
"game_ad_source_name" to gameAdSourceName
parseAndPutMeta().invoke(this)
}
log(json)
}
// 点击游戏广告
@JvmStatic
fun logClickGameAd(
adSpaceId: String,
name: String,
position: String,
type: String,
gameAdSourceId: String,
gameAdSourceName: String,
gameId: String,
gameName: String
) {
val json = json {
KEY_EVENT to "click_game_ad"
"ad_space_id" to adSpaceId
"name" to name
"position" to position
"type" to type
"game_ad_source_id" to gameAdSourceId
"game_ad_source_name" to gameAdSourceName
"game_id" to gameId
"game_name" to gameName
parseAndPutMeta().invoke(this)
}
log(json)
}
}

View File

@ -2158,7 +2158,7 @@ object NewLogUtils {
//点击底部导航栏
@JvmStatic
fun logBottomNavigationClick(navigationName: String, linkType: String, linkText: String, linkId: String = "") {
fun logBottomNavigationClick(navigationName: String, linkType: String, linkText: String, linkId: String = "", sequence: Int) {
val json = json {
KEY_EVENT to "bottom_navigation_click"
"navigation_name" to navigationName
@ -2169,6 +2169,7 @@ object NewLogUtils {
"link_text" to linkText
}
"link_id" to linkId
"sequence" to sequence
KEY_TIMESTAMP to System.currentTimeMillis() / 1000
parseAndPutMeta().invoke(this)
}
@ -2486,4 +2487,209 @@ object NewLogUtils {
}
log(json, LOG_STORE_EVENT)
}
/**
* 埋点序号117
* 事件IDmessage_inform_push
* 事件名称:消息推送事件
* 触发时机:系统触发消息推送
* @param gameId 游戏ID
* @param gameName 游戏名称
* @param sessionMessageType 会话类型
* @param messageType 消息类型
*/
@JvmStatic
fun logMessageInformPush(
gameId: String,
gameName: String,
sessionMessageType: String,
messageType: String
) {
val json = json {
KEY_EVENT to "message_inform_push"
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
"session_message_type" to sessionMessageType
"message_type" to messageType
parseAndPutMeta().invoke(this)
}
log(json, LOG_STORE_EVENT)
}
/**
* 埋点序号118
* 事件IDlaunch_server_subscribe_add
* 事件名称:加入开服订阅事件
* 触发时机:点击开服表加入订阅
* @param gameId 游戏ID
* @param gameName 游戏名称
*/
@JvmStatic
fun logLaunchServerSubscribeAdd(
gameId: String,
gameName: String
) {
val json = json {
KEY_EVENT to "launch_server_subscribe_add"
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
parseAndPutMeta().invoke(this)
}
log(json, LOG_STORE_EVENT)
}
/**
* 埋点序号119
* 事件IDlaunch_server_subscribe_cancel
* 事件名称:取消开服订阅事件
* 触发时机:点击开服表取消订阅
* @param gameId 游戏ID
* @param gameName 游戏名称
*/
@JvmStatic
fun logLaunchServerSubscribeCancel(
gameId: String,
gameName: String
) {
val json = json {
KEY_EVENT to "launch_server_subscribe_cancel"
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
parseAndPutMeta().invoke(this)
}
log(json, LOG_STORE_EVENT)
}
/**
* 埋点序号120
* 事件IDlaunch_server_subscribe_click
* 事件名称:点击开服订阅事件
* 触发时机:点击开服管理的开服记录
* @param gameId 游戏ID
* @param gameName 游戏名称
* @param launchServerTime 以秒为单位的时间戳,若为日期则是当天0点的时间戳
*/
@JvmStatic
fun logLaunchServerSubscribeClick(
gameId: String,
gameName: String,
launchServerTime: Int
) {
val json = json {
KEY_EVENT to "launch_server_subscribe_click"
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
"launch_server_time" to launchServerTime
parseAndPutMeta().invoke(this)
}
log(json, LOG_STORE_EVENT)
}
/**
* 埋点序号121
* 事件IDlaunch_server_reminder_add
* 事件名称:添加开服提醒事件
* 触发时机:点击开服表的添加提醒
* @param gameId 游戏ID
* @param gameName 游戏名称
* @param reminderTime 设置提醒时间: 已知服是上传以秒为单位的时间戳未知服则是当天0点的时间戳
* @param reminderType 提醒类型: 已知服/未知服
* @param launchServerTime 设置开服时间: 已知服是上传以秒为单位的时间戳未知服则是当天0点的时间戳
* @param serverName 服务器名字
* @param isWechat 是否微信提醒
* @param isApp 是否APP提醒
*/
@JvmStatic
fun logLaunchServerReminderAdd(
gameId: String,
gameName: String,
reminderTime: Int,
reminderType: String,
launchServerTime: Int,
serverName: String,
isWechat: Boolean,
isApp: Boolean
) {
val json = json {
KEY_EVENT to "launch_server_reminder_add"
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
"reminder_time" to reminderTime
"reminder_type" to reminderType
"launch_server_time" to launchServerTime
"server_name" to serverName
"is_wechat" to isWechat
"is_app" to isApp
parseAndPutMeta().invoke(this)
}
log(json, LOG_STORE_EVENT)
}
/**
* 埋点序号122
* 事件IDlaunch_server_reminder_cancel
* 事件名称:取消开服提醒事件
* 触发时机:点击开服表的取消提醒
* @param gameId 游戏ID
* @param gameName 游戏名称
* @param reminderTime 设置提醒时间: 已知服是上传以秒为单位的时间戳未知服则是当天0点的时间戳
* @param reminderType 提醒类型: 已知服/未知服
* @param launchServerTime 设置开服时间: 已知服是上传以秒为单位的时间戳未知服则是当天0点的时间戳
* @param serverName 服务器名字
* @param isWechat 是否微信提醒
* @param isApp 是否APP提醒
*/
@JvmStatic
fun logLaunchServerReminderCancel(
gameId: String,
gameName: String,
reminderTime: Int,
reminderType: String,
launchServerTime: Int,
serverName: String,
isWechat: Boolean,
isApp: Boolean
) {
val json = json {
KEY_EVENT to "launch_server_reminder_cancel"
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
"reminder_time" to reminderTime
"reminder_type" to reminderType
"launch_server_time" to launchServerTime
"server_name" to serverName
"is_wechat" to isWechat
"is_app" to isApp
parseAndPutMeta().invoke(this)
}
log(json, LOG_STORE_EVENT)
}
/**
* 埋点序号123
* 事件IDlaunch_server_reminder_click
* 事件名称:点击开服提醒事件
* 触发时机:点击开服管理的提醒记录
* @param gameId 游戏ID
* @param gameName 游戏名称
* @param reminderTime 设置提醒时间: 已知服是上传以秒为单位的时间戳未知服则是当天0点的时间戳
* @param status 记录状态: todo 待提醒 coming 即将开服 opened 已开服 has_new 有新服 expired 已过期
*/
@JvmStatic
fun logLaunchServerReminderClick(
gameId: String,
gameName: String,
reminderTime: Int,
status: String,
) {
val json = json {
KEY_EVENT to "launch_server_reminder_click"
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
"reminder_time" to reminderTime
"status" to status
parseAndPutMeta().invoke(this)
}
log(json, LOG_STORE_EVENT)
}
}

View File

@ -15,13 +15,11 @@ import com.gh.common.xapk.XapkInstaller
import com.gh.download.server.BrowserInstallHelper
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.DialogHelper
import com.gh.gamecenter.common.utils.categoryChinese
import com.gh.gamecenter.common.utils.getExtension
import com.gh.gamecenter.common.utils.getMetaExtra
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.install.InstallService
import com.gh.gamecenter.vpn.VpnHelper
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
@ -37,7 +35,7 @@ object PackageInstaller {
*/
@JvmStatic
fun install(context: Context, downloadEntity: DownloadEntity?) {
downloadEntity?.let { install(context, downloadEntity, true) }
downloadEntity?.let { install(context, downloadEntity, showUnzipToast = true, ignoreAsVGame = false) }
}
/**
@ -46,16 +44,25 @@ object PackageInstaller {
* 兼容所有包安装(apk,xapk),后续可加上apks
*
* 主动点击安装如果是xapk则需要toast提示
*
* @param ignoreAsVGame 是否不需要以畅玩形式安装
*
*
*/
@JvmStatic
fun install(context: Context, downloadEntity: DownloadEntity, showUnzipToast: Boolean) {
fun install(context: Context,
downloadEntity: DownloadEntity,
showUnzipToast: Boolean,
ignoreAsVGame: Boolean,
) {
val pkgPath = downloadEntity.path
val isXapk = XapkInstaller.XAPK_EXTENSION_NAME == pkgPath.getExtension()
val isVGame = downloadEntity.getMetaExtra(Constants.SMOOTH_GAME) == "true"
val isDownloadAsVGame = downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.VGAME
|| downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.DUAL_DOWNLOAD_VGAME
val currentActivity = CurrentActivityHolder.getCurrentActivity() ?: return
if (isVGame) {
if (!ignoreAsVGame && isDownloadAsVGame) {
VHelper.install(currentActivity, downloadEntity)
return
}
@ -153,6 +160,13 @@ object PackageInstaller {
*/
private fun install(context: Context, pkgPath: 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)
}

View File

@ -1,13 +1,77 @@
package com.gh.common.util
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.utils.isVGameDownloadInDualDownloadMode
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.feature.entity.GameInstall
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.GameInstall
import com.gh.gamecenter.packagehelper.PackageRepository
import com.gh.vspace.VHelper
object PackageLauncher {
/**
* 自动选择启动已安装的畅玩或本地已安装的游戏
* 仅适用于 gameEntity 只有一个 apk 的情况
*/
@JvmStatic
fun launch(
context: Context,
gameEntity: GameEntity,
location: String? = null
) {
if (gameEntity.getApk().isEmpty() || gameEntity.getApk().size > 1) {
return
}
val packageName = gameEntity.getApk().first().packageName
// 根据下载按钮类型进行进行不一样的处理
when (gameEntity.getGameDownloadButtonMode()) {
GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DOWNLOAD -> {
launchApp(context, gameEntity, packageName)
}
GameEntity.GAME_DOWNLOAD_BUTTON_MODE_VGAME -> {
VHelper.installOrLaunch(context as AppCompatActivity, gameEntity, location)
}
GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DUAL -> {
val vGameIsInstalled = VHelper.isInstalled(packageName)
val localGameIsInstalled = PackageUtils.isInstalled(context, packageName)
when {
vGameIsInstalled && localGameIsInstalled -> {
if (gameEntity.isVGamePreferred()) {
VHelper.installOrLaunch(context as AppCompatActivity, gameEntity, location)
} else {
launchApp(context, gameEntity, packageName)
}
}
vGameIsInstalled -> {
VHelper.installOrLaunch(context as AppCompatActivity, gameEntity, location)
}
localGameIsInstalled -> {
launchApp(context, gameEntity, packageName)
}
else -> {
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
if (downloadEntity?.isVGameDownloadInDualDownloadMode() == true) {
VHelper.installOrLaunch(context as AppCompatActivity, gameEntity, location)
} else {
ToastUtils.toast("下载异常,请重新下载")
}
}
}
}
}
}
/*
* 启动应用
*/

View File

@ -41,7 +41,6 @@ import com.gh.gamecenter.manager.PackagesManager;
import com.gh.vspace.VHelper;
import com.gh.vspace.db.VGameEntity;
import com.halo.assistant.HaloApp;
import com.lg.vspace.VirtualAppManager;
import com.lightgame.utils.Utils;
import net.dongliu.apk.parser.ApkFile;
@ -110,10 +109,12 @@ public class PackageUtils {
return !(MD5Str.equals(MD5Utils.calculateMD5(file)));
}
/*
* 判断是否可以更新只判断gh_version的大小
/**
* 判断是否可以更新
* @param gameEntity 游戏摘要实体
* @param isVGame 是否为畅玩游戏(走特殊的判断更新逻辑)
*/
public static List<GameUpdateEntity> getUpdateData(GameEntity gameEntity) {
public static List<GameUpdateEntity> getUpdateData(GameEntity gameEntity, boolean isVGame) {
List<GameUpdateEntity> updateList = new ArrayList<>();
@ -169,7 +170,7 @@ public class PackageUtils {
boolean shouldShowUpdate = apkEntity.getForce();
// 普通游戏根据本地是否有安装来确定是否 qualified畅玩游戏直接进判断
boolean isUpdateQualified =
gameEntity.isVGame() || (!TextUtils.isEmpty(versionFromRequest) && !TextUtils.isEmpty(versionFromInstalledApp));
isVGame || (!TextUtils.isEmpty(versionFromRequest) && !TextUtils.isEmpty(versionFromInstalledApp));
if (shouldShowUpdate && isUpdateQualified) {
@ -182,12 +183,11 @@ public class PackageUtils {
}
// 畅玩游戏根据 md5 是否一致确定是否需要更新
if (gameEntity.isVGame()) {
if (isVGame) {
VGameEntity vGameEntity = VHelper.getVGameSnapshot(gameEntity.getId(), apkEntity.getPackageName());
if (vGameEntity != null) {
String md5FromInstalledVGame = ExtensionsKt.getMetaExtra(vGameEntity.getDownloadEntity(), Constants.APK_MD5);
String md5FromRequest = apkEntity.getMd5();
apkEntity.setPlatform(VHelper.PLATFORM_V);
shouldShowUpdate = md5FromRequest != null && !md5FromRequest.equals(md5FromInstalledVGame);
} else {
@ -219,6 +219,7 @@ public class PackageUtils {
updateEntity.setFormat(apkEntity.getFormat());
updateEntity.setSignature(apkEntity.getSignature());
updateEntity.setCategory(gameEntity.getCategory());
updateEntity.setVGameUpdate(isVGame);
updateEntity.setCurrentVersion(PackageUtils.getVersionNameByPackageName(apkEntity.getPackageName()));
if (gameEntity.isLandPageAddressDialog()) {
updateEntity.setLandPageAddressDialog(gameEntity.getLandPageAddressDialog());
@ -727,6 +728,13 @@ public class PackageUtils {
for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
JSONObject jsonObject = new JSONObject();
// 这里的 pm.getApplicationLabel 有极小机率会返回 null 值 (明明方法标示了返回值 nonnull
// Attempt to invoke interface method 'java.lang.String java.lang.CharSequence.toString()' on a null object reference
// 所以要是为空就 continue忽略掉它
if (pm.getApplicationLabel(packageInfo.applicationInfo) == null) {
continue;
}
jsonObject.put("name", pm.getApplicationLabel(packageInfo.applicationInfo).toString());
jsonObject.put("package", packageInfo.packageName);
jsonObject.put("version", packageInfo.versionName);

View File

@ -23,7 +23,13 @@ object RecommendPopupHelper {
//判断是否为多版本游戏
if (gameEntity.getApk().isEmpty() || gameEntity.getApk().size > 1) return null
val downloadBtnText = GameUtils.getDownloadBtnText(HaloApp.getInstance(), gameEntity, PluginLocation.only_game)
val downloadBtnText = GameUtils.getDownloadBtnText(
context = HaloApp.getInstance(),
gameEntity = gameEntity,
isFromList = false,
fixedAsVGame = false,
pluginLocation = PluginLocation.only_game
)
val filterEntities = arrayListOf<RecommendPopupEntity>()
loop@ for (entity in popups) {

View File

@ -75,7 +75,7 @@ class ImageContainerView : LinearLayout {
calculateWidth()
}
fun bindData(entity: AnswerEntity, entrance: String = "", path: String = "") {
fun bindData(entity: AnswerEntity, entrance: String = "", path: String = "", imageClick: (() -> Unit)? = null) {
imageViewList.clear()
if (entity.id != mAnswerEntity?.id) {
removeAllViews()
@ -103,13 +103,15 @@ class ImageContainerView : LinearLayout {
images.forEachIndexed { index, url ->
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
bindImage(url, width, height, images.size == 1)
bindImage(url, width, height, images.size == 1, imageClick)
}
}
entity.getPassVideos().isNotEmpty() -> {
val video = entity.getPassVideos()[0]
bindVideo(video, video.width, video.height, true)
}
else -> {
// do noting
}
@ -125,7 +127,7 @@ class ImageContainerView : LinearLayout {
val imagesInfo = entity.imagesInfo
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
bindImage(url, width, height, false)
bindImage(url, width, height, false, imageClick)
}
} else {
val images = entity.images.take(3)
@ -133,7 +135,7 @@ class ImageContainerView : LinearLayout {
val imagesInfo = entity.imagesInfo
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
bindImage(url, width, height, images.size == 1)
bindImage(url, width, height, images.size == 1, imageClick)
}
}
}
@ -171,7 +173,13 @@ class ImageContainerView : LinearLayout {
index++
}
private fun bindImage(url: String, width: Int, height: Int, isChangeRatio: Boolean) {
private fun bindImage(
url: String,
width: Int,
height: Int,
isChangeRatio: Boolean,
imageClick: (() -> Unit)?
) {
val oldView = if (childCount == 0 || index >= childCount) null else getChildAt(index)
val binding = if (oldView != null) {
ItemCommunityImageBinding.bind(oldView)
@ -188,7 +196,7 @@ class ImageContainerView : LinearLayout {
displayImage(binding, url, width.toFloat(), height.toFloat(), isChangeRatio)
binding.root.setOnClickListener {
if (mAnswerEntity?.status == "pending" || mAnswerEntity?.status == "fail") return@setOnClickListener
imageClick?.invoke()
debounceActionWithInterval(it.id, 1000) {
if (mAnswerEntity == null) return@debounceActionWithInterval
val position = if (mAnswerEntity?.type == "community_article") {
@ -232,10 +240,12 @@ class ImageContainerView : LinearLayout {
ImageUtils.display(binding.image, url, false, TopCutProcess(mMinRatio))
}
}
picRatio >= mMaxRatio -> {
params.height = (mFixdWidth / mMaxRatio).toInt()
ImageUtils.display(binding.image, url, false)
}
else -> {
params.height = (mFixdWidth / picRatio).toInt()
ImageUtils.display(binding.image, url, false)

View File

@ -128,6 +128,10 @@ public class RichEditor extends WebView {
private WebResourceRequestInterceptor mWebResourceRequestInterceptor;
private PageFinishedListener mPageFinishedListener;
private OnLinkClickListener mOnLinkClickListener;
private ImageListener mImageListener;
public RichEditor(Context context) {
this(context, null);
}
@ -146,6 +150,8 @@ public class RichEditor extends WebView {
ExtensionsKt.fixUiModeIfNeeded(this);
addJavascriptInterface(new NativeCallBack(), "NativeCallBack");
addJavascriptInterface(new LinkClickNativeCallback(), "OnLinkClickListener");
addJavascriptInterface(new ImageNativeCallback(), "imagelistener");
setVerticalScrollBarEnabled(false);
setHorizontalScrollBarEnabled(false);
@ -195,6 +201,14 @@ public class RichEditor extends WebView {
mInitialLayoutCallback = layoutCallback;
}
public void setOnLinkClickListener(OnLinkClickListener onLinkClickListener) {
this.mOnLinkClickListener = onLinkClickListener;
}
public void setImageListener(ImageListener imageListener) {
this.mImageListener = imageListener;
}
private void callback(String text) {
mContents = text.replaceFirst(CALLBACK_SCHEME, "");
if (mTextChangeListener != null) {
@ -864,6 +878,96 @@ public class RichEditor extends WebView {
}
}
class LinkClickNativeCallback {
/**
* 链接点击回调
* @param content 回调内容
*/
@JavascriptInterface
public void onClick(String content) {
if (mOnLinkClickListener != null) {
mOnLinkClickListener.onClick(content);
}
}
/**
* 视频点击回调
* @param content 回调内容
*/
@JavascriptInterface
public void onVideoClick(String content) {
if (mOnLinkClickListener != null) {
mOnLinkClickListener.onVideoClick(content);
}
}
/**
* 视频点击回调
* @param url 视频链接
* @param poster 视频封面
*/
@JavascriptInterface
public void onVideoClick(String url, String poster) {
if (mOnLinkClickListener != null) {
mOnLinkClickListener.onVideoClick(url, poster);
}
}
/**
* 视频点击回调
* @param url 视频链接
* @param poster 视频封面
* @param position 视频下标位置
*/
@JavascriptInterface
public void onVideoClick(String url, String poster, long position) {
if (mOnLinkClickListener != null) {
mOnLinkClickListener.onVideoClick(url, poster, position);
}
}
}
class ImageNativeCallback {
/**
* 图片点击回调
* @param url 图片链接
*/
@JavascriptInterface
public void imageClick(String url) {
if (mImageListener != null) {
mImageListener.onImageClick(url);
}
}
/**
* 图片加载回调
* @param url 图片链接
*/
@JavascriptInterface
public void imageArr(String url) {
if (mImageListener != null) {
mImageListener.onImageLoad(url);
}
}
}
public interface OnLinkClickListener {
void onClick(String content);
void onVideoClick(String content);
void onVideoClick(String url, String poster);
void onVideoClick(String url, String poster, long position);
}
public interface ImageListener {
void onImageLoad(String url);
void onImageClick(String url);
}
@Override
public void invalidate() {
super.invalidate();

View File

@ -123,6 +123,7 @@ object DownloadDataHelper {
payloadObject.put("package", downloadEntity.packageName)
payloadObject.put("certification", RealNameHelper.getCertificationStatus())
payloadObject.put("filename", getFileName(downloadEntity))
payloadObject.put("download_type", if (downloadEntity.asVGame()) "畅玩下载" else "本地下载")
payloadObject.put("task_num", NDataChanger.downloadingTaskUrlSet.size)
jsonObject.put("payload", payloadObject)
} catch (e: Exception) {
@ -250,6 +251,7 @@ object DownloadDataHelper {
payloadObject.put("certification", RealNameHelper.getCertificationStatus())
payloadObject.put("filename", getFileName(downloadEntity))
payloadObject.put("total_size", sizeInMB)
payloadObject.put("download_type", if (downloadEntity.asVGame()) "畅玩下载" else "本地下载")
if (parallel != null) {
payloadObject.put("parallel", parallel)
}
@ -353,6 +355,7 @@ object DownloadDataHelper {
sheet.put("package", downloadEntity.packageName)
sheet.put("certification", RealNameHelper.getCertificationStatus())
sheet.put("filename", getFileName(downloadEntity))
sheet.put("download_type", if (downloadEntity.asVGame()) "畅玩下载" else "本地下载")
sheet.put("total_size", downloadEntity.size / 1024 / 1024)
sheet.put("current_progress_size", downloadEntity.progress / 1024)
mDownloadHeartbeatSheet[downloadEntity.url] = sheet
@ -410,6 +413,7 @@ object DownloadDataHelper {
metaObject.put("appVersion", meta.appVersion)
metaObject.put("channel", meta.channel)
metaObject.put("gid", meta.gid)
metaObject.put("oaid", meta.oaid)
metaObject.put("manufacturer", meta.manufacturer)
metaObject.put("model", meta.model)
metaObject.put("network", DeviceUtils.getNetwork(context))

View File

@ -25,7 +25,6 @@ import com.gh.common.exposure.ExposureUtils;
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
import com.gh.common.history.HistoryHelper;
import com.gh.common.simulator.SimulatorGameManager;
import com.gh.gamecenter.core.utils.AppDebugConfig;
import com.gh.common.util.DataCollectionUtils;
import com.gh.gamecenter.common.utils.DeviceUtils;
import com.gh.common.util.DialogUtils;
@ -233,7 +232,7 @@ public class DownloadManager implements DownloadStatusListener {
*
* @param context 上下文
* @param gameEntity 游戏实体 (取 apk 里的第一个来进行下载)
* @param method 下载类型
* @param asVGame 是否以畅玩游戏的形式下载
* @param entrance 来源 (细节见 https://git.ghzs.com/halo/android/assistant-android/-/wikis/entrance)
* @param location 跟来源是类似的东西,我也不知道具体规则是怎么样的 C
* @param isSubscribe 是否是订阅下载在WiFi环境下才下载
@ -241,30 +240,32 @@ public class DownloadManager implements DownloadStatusListener {
*/
public static void createDownload(Context context,
GameEntity gameEntity,
String method,
boolean asVGame,
String entrance,
String location,
boolean isSubscribe,
@Nullable ExposureEvent traceEvent) {
createDownload(context, gameEntity.getApk().get(0), gameEntity, method, entrance, location, isSubscribe, traceEvent);
createDownload(context, gameEntity.getApk().get(0), gameEntity, asVGame, gameEntity.isDualBtnModeEnabled(), entrance, location, isSubscribe, traceEvent);
}
/**
* 创建下载任务
*
* @param context 上下文
* @param gameEntity 游戏实体 (信息用于)
* @param apkEntity 安装包实体,实际用于下载的信息文件
* @param method 下载类型
* @param entrance 来源 (细节见 https://git.ghzs.com/halo/android/assistant-android/-/wikis/entrance)
* @param location 跟来源是类似的东西,我也不知道具体规则是怎么样的 C
* @param isSubscribe 是否是订阅下载在WiFi环境下才下载
* @param traceEvent 曝光来源实体,用于记录一些简单的下载路径
* @param context 上下文
* @param gameEntity 游戏实体 (信息用于)
* @param apkEntity 安装包实体,实际用于下载的信息文件
* @param entrance 来源 (细节见 https://git.ghzs.com/halo/android/assistant-android/-/wikis/entrance)
* @param location 来源是类似的东西,我也不知道具体规则是怎么样的 C
* @param isSubscribe 是否是订阅下载在WiFi环境下才下载
* @param traceEvent 曝光来源实体,用于记录一些简单的下载路径
* @param asVGame 作为畅玩游戏下载
* @param isDualDownloadTypeEnabled 双下载按钮模式是否启用
*/
public static void createDownload(final Context context,
ApkEntity apkEntity,
GameEntity gameEntity,
String method,
boolean asVGame,
boolean isDualDownloadTypeEnabled,
String entrance,
String location,
boolean isSubscribe,
@ -340,14 +341,22 @@ public class DownloadManager implements DownloadStatusListener {
ExtensionsKt.addMetaExtra(downloadEntity, Constants.SIMULATOR, GsonUtils.toJson(gameEntity.getSimulator()));
}
if (gameEntity.isVGame()) {
ExtensionsKt.addMetaExtra(downloadEntity, Constants.SMOOTH_GAME, "true");
ExtensionsKt.addMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE, Constants.SMOOTH_GAME);
if (asVGame) {
ExtensionsKt.addMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE, Constants.VGAME);
ExtensionsKt.addMetaExtra(downloadEntity, DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200");
ExtensionsKt.addMetaExtra(downloadEntity, VHelper.KEY_REQUIRED_G_APPS, gameEntity.getGAppsSwitch());
ExtensionsKt.addMetaExtra(downloadEntity, VHelper.KEY_BIT, apkEntity.getBit());
}
// 记录是否为双下载按钮模式
if (isDualDownloadTypeEnabled) {
if (asVGame) {
ExtensionsKt.setVGameDownloadModeInDualDownloadMode(downloadEntity);
} else {
ExtensionsKt.setLocalDownloadModeInDualDownloadMode(downloadEntity);
}
}
HashMap<String, String> map = PageSwitchDataHelper.popLastPageData();
if (map != null && map.containsKey(PageSwitchDataHelper.PAGE_GAME_DETAIL_RECOMMEND)) {
ExtensionsKt.addMetaExtra(downloadEntity, PageSwitchDataHelper.PAGE_GAME_DETAIL_RECOMMEND, "true");
@ -371,7 +380,7 @@ public class DownloadManager implements DownloadStatusListener {
downloadEntity.setPlugin(!TextUtils.isEmpty(apkEntity.getGhVersion()));
ExposureUtils.DownloadType downloadType = ExposureUtils.getDownloadType(apkEntity, gameEntity.getId(), gameEntity.isVGame());
ExposureUtils.DownloadType downloadType = ExposureUtils.getDownloadType(apkEntity, gameEntity.getId(), asVGame);
gameEntity.setIsPlatformRecommend(apkEntity.getRecommend() != null);
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, downloadType);
@ -385,11 +394,7 @@ public class DownloadManager implements DownloadStatusListener {
DownloadManager.getInstance().add(downloadEntity);
}
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodWithParams(DownloadManager.class, apkEntity.getUrl(), downloadEntity.getUrl(), method, entrance, location);
}
if (gameEntity.isVGame()) {
if (asVGame) {
SensorsBridge.trackEventWithExposureSource("HaloFunGameDownloadClick",
downloadExposureEvent.getSource(),
"game_name", gameEntity.getName(),
@ -397,6 +402,13 @@ public class DownloadManager implements DownloadStatusListener {
"game_schema_type", gameEntity.getGameBitChinese());
}
String trackDownloadType = "";
if (asVGame) {
trackDownloadType = "畅玩下载";
} else {
trackDownloadType = "本地下载";
}
SensorsBridge.trackEventWithExposureSource("DownloadProcessBegin",
downloadExposureEvent.getSource(),
"game_id", gameEntity.getId(),
@ -408,7 +420,8 @@ public class DownloadManager implements DownloadStatusListener {
"page_business_id", GlobalActivityManager.getCurrentPageEntity().getPageBusinessId(),
"last_page_name", GlobalActivityManager.getLastPageEntity().getPageName(),
"last_page_id", GlobalActivityManager.getLastPageEntity().getPageId(),
"last_page_business_id", GlobalActivityManager.getLastPageEntity().getPageBusinessId()
"last_page_business_id", GlobalActivityManager.getLastPageEntity().getPageBusinessId(),
"download_type", trackDownloadType
);
//TODO remove
@ -435,7 +448,6 @@ public class DownloadManager implements DownloadStatusListener {
SentryHelper.INSTANCE.onEvent("CLEAR_DELETED_TASK_ERROR", "exception_digest", e.getLocalizedMessage());
}
}
/**
* 添加一个下载任务
* <p>
@ -443,13 +455,25 @@ public class DownloadManager implements DownloadStatusListener {
*/
@Deprecated
public void add(DownloadEntity downloadEntity) {
add(downloadEntity, false);
}
/**
* 添加一个下载任务
* <p>
* 请优先使用 createDownload()
*
* @param ignoreDownloaded 忽略已经下载的内容
*/
@Deprecated
public void add(DownloadEntity downloadEntity, boolean ignoreDownloaded) {
updateDownloadMetaMap();
if (downloadEntity != null) {
String url = downloadEntity.getUrl();
checkDownloadEntryRecordValidate(url);
if (isDownloadCompleted(url)) {
if (isDownloadCompleted(url) && !ignoreDownloaded) {
downloadEntity.setStatus(DownloadStatus.done);
NDataChanger.INSTANCE.notifyDataChanged(downloadEntity);
} else if (!isTaskDownloading(url)) {
@ -608,24 +632,23 @@ public class DownloadManager implements DownloadStatusListener {
@Nullable
public DownloadEntity getDownloadEntitySnapshot(GameEntity gameEntity) {
if (gameEntity == null || gameEntity.getApk().size() == 0) return null;
return getDownloadEntitySnapshot(gameEntity.getApk().get(0).getUrl(), gameEntity.getId(), gameEntity.isVGame());
return getDownloadEntitySnapshot(gameEntity.getApk().get(0).getUrl(), gameEntity.getId());
}
/**
* 获取快照
* <p>
* 畅玩游戏优先根据游戏 ID 获取,非畅玩游戏根据 url 获取
* 优先根据游戏 ID 获取,次选根据 url 获取
*
* @param url 下载链接
* @param isVGame 是不是畅玩游戏
* @param gameId 游戏 ID
* @param url 下载链接
* @param gameId 游戏 ID
* @return null表示下载列表中不存在该任务否则返回下载任务
*/
@Nullable
public DownloadEntity getDownloadEntitySnapshot(String url, String gameId, boolean isVGame) {
public DownloadEntity getDownloadEntitySnapshot(String url, String gameId) {
DownloadEntity snapshot = null;
if (isVGame && !TextUtils.isEmpty(gameId)) {
if (!TextUtils.isEmpty(gameId)) {
snapshot = mDownloadDao.getSnapshotByGameId(gameId);
}
@ -753,7 +776,8 @@ public class DownloadManager implements DownloadStatusListener {
ArrayList<DownloadEntity> filteredDownloadEntityList = new ArrayList<>();
for (DownloadEntity downloadEntity : downloadList) {
if (Constants.SMOOTH_GAME.equals(ExtensionsKt.getMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE))) {
if (Constants.VGAME.equals(ExtensionsKt.getMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE))
|| Constants.DUAL_DOWNLOAD_VGAME.equals(ExtensionsKt.getMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE))) {
filteredDownloadEntityList.add(downloadEntity);
}
}
@ -768,9 +792,11 @@ public class DownloadManager implements DownloadStatusListener {
for (DownloadEntity downloadEntity : downloadEntityList) {
if (!ExtensionsKt.isSimulatorGame(downloadEntity)) {
if (!Constants.SILENT_UPDATE.equals(ExtensionsKt.getMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE))
&& !Constants.SIMULATOR_DOWNLOAD.equals(ExtensionsKt.getMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE))
&& !Constants.SMOOTH_GAME.equals(ExtensionsKt.getMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE))
String extraDownloadType = ExtensionsKt.getMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE);
if (!Constants.SILENT_UPDATE.equals(extraDownloadType)
&& !Constants.SIMULATOR_DOWNLOAD.equals(extraDownloadType)
&& !Constants.VGAME.equals(extraDownloadType)
&& !Constants.DUAL_DOWNLOAD_VGAME.equals(extraDownloadType)
) {
filteredDownloadEntityList.add(downloadEntity);
}
@ -858,6 +884,8 @@ public class DownloadManager implements DownloadStatusListener {
initGameMap();
entry.setUpdate(false);
if (cancelSilently) {
entry.setStatus(DownloadStatus.cancel);
cancelAndNotify(entry, true);
@ -1290,7 +1318,7 @@ public class DownloadManager implements DownloadStatusListener {
public void resumeAllInvisiblePendingTask() {
for (DownloadEntity task : mInvisiblePendingTaskList) {
if ("false".equals(task.getMeta().get("force_real_name"))) {
add(task);
add(task, false);
}
}
mInvisiblePendingTaskList.clear();
@ -1329,6 +1357,8 @@ public class DownloadManager implements DownloadStatusListener {
map.put(HttpDnsManager.TOKEN, UserManager.getInstance().getToken());
map.put(HttpDnsManager.IS_OVERWRITE, isOverwrite);
map.put(HttpDnsManager.INSTALL_TYPE, installType);
map.put(HttpDnsManager.ANDROID_ID, MetaUtil.getBase64EncodedAndroidId());
map.put(HttpDnsManager.ANDROID_SDK_VERSION, String.valueOf(Build.VERSION.SDK_INT));
HttpDnsManager.metaMap = map;
}

View File

@ -2,19 +2,16 @@ package com.gh.download
import android.annotation.SuppressLint
import android.text.TextUtils
import com.gh.common.util.*
import com.gh.gamecenter.feature.utils.ConcernUtils
import com.gh.common.util.DataCollectionUtils
import com.gh.common.util.PackageInstaller
import com.gh.common.util.PackageUtils
import com.gh.common.xapk.XapkInstaller
import com.gh.download.server.BrowserInstallHelper
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.loghub.LoghubUtils
import com.gh.gamecenter.common.retrofit.EmptyResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.NewFlatLogUtils
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.isVGame
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ThirdPartyPackageHelper
@ -22,12 +19,13 @@ import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.entity.GameDigestEntity
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.manager.PackagesManager
import com.gh.gamecenter.packagehelper.PackageRepository
import com.gh.gamecenter.packagehelper.PackageViewModel
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.download.FileUtils
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
@ -108,16 +106,24 @@ object PackageObserver {
if (gh_id == null) {
ThirdPartyPackageHelper.saveGameId(mDownloadEntity.packageName, mDownloadEntity.gameId)
}
if (mDownloadEntity.isVGame()) {
// 畅玩游戏安装完成的同时直接删除文件
runOnIoThread { FileUtils.deleteFile(mDownloadEntity.path) }
}
if (mDownloadEntity.format == Constants.XAPK_FORMAT) {
XapkInstaller.onInstalled(mDownloadEntity.path)
}
DownloadManager.getInstance().cancel(mDownloadEntity.url, false, true, false)
// 双下载模式
if (mDownloadEntity.isVGameDownloadInDualDownloadMode() || mDownloadEntity.isLocalDownloadInDualDownloadMode()) {
// 当双下载都完成或者是更新下载的时候清理任务
// 畅玩下载不需要实名,如果用户没有本地实名信息,安装完成后也清理任务,避免可以免实名安装到本地
if (mDownloadEntity.isUpdate
|| (PackagesManager.isInstalled(packageName) && VHelper.isInstalled(packageName))
|| (busFour.isVGame && RealNameHelper.getCertificationStatus() != 2)
) {
DownloadManager.getInstance().cancel(mDownloadEntity.url, true, true, false)
}
} else {
DownloadManager.getInstance().cancel(mDownloadEntity.url, true, true, false)
}
if (SPUtils.getBoolean(Constants.SP_CONCERN_GAME, true)) { //设置页面控制是否安装后自动关注
// 安装后关注游戏
@ -148,10 +154,10 @@ object PackageObserver {
}
if (EBPackage.TYPE_UNINSTALLED == busFour.type) {
mPackageViewModel.addUninstalledGame(packageName)
mPackageViewModel.addUninstalledGame(packageName, busFour.isVGame)
mDownloadEntity?.let {
if (it.isVGame()) return@let
if (it.asVGame()) return@let
if (it.isPluggable
|| (it.isUpdate && !PackageUtils.isInstalled(application, it.packageName))) {
@ -193,6 +199,7 @@ object PackageObserver {
try {
dataObject.put("type", "POST")
dataObject.put("device_id", HaloApp.getInstance().gid)
dataObject.put("oaid", HaloApp.getInstance().oaid)
dataObject.put("app", packageObject)
dataObject.put("time", Utils.getTime(HaloApp.getInstance().application))
wrapperObject.put("content", dataObject.toString())
@ -230,6 +237,7 @@ object PackageObserver {
try {
dataObject.put("type", "DELETE")
dataObject.put("device_id", HaloApp.getInstance().gid)
dataObject.put("oaid", HaloApp.getInstance().oaid)
dataObject.put("package", packageName)
dataObject.put("time", Utils.getTime(HaloApp.getInstance().application))
wrapperObject.put("content", dataObject.toString())

View File

@ -233,16 +233,12 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
val gameEntity = viewModel.gameEntity
itemView.setOnClickListener {
var mtaValue = "未知"
when (itemView.getTag(DownloadDialogAdapter.ITEM_TAG_KEY)) {
DownloadDialogItemStatus.DOWNLOAD -> {
createDownloadTask(it.context, apkEntity, gameEntity, "下载", traceEvent, entrance, location)
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_下载"
createDownloadTask(it.context, apkEntity, gameEntity, traceEvent, entrance, location)
}
DownloadDialogItemStatus.LAUNCH -> {
PackageLauncher.launchApp(it.context, gameEntity, apkEntity.packageName)
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_启动"
}
DownloadDialogItemStatus.DOWNLOADING -> {
// 打开下载管理界面
@ -256,18 +252,6 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
if (AppManager.getInstance().currentActivity() is DownloadManagerActivity) {
viewModel.dismissLiveData.postValue(Any())
}
val downloadEntity = DownloadManager.getInstance().getDownloadEntityByUrl(apkEntity.url)
if (downloadEntity?.status == DownloadStatus.pause) {
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_暂停中"
} else if (downloadEntity?.status == DownloadStatus.waiting) {
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_等待中"
} else if (downloadEntity?.status == DownloadStatus.subscribe) {
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_排队中"
} else {
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_下载中"
}
}
DownloadDialogItemStatus.INSTALL -> {
val downloadEntity = DownloadManager.getInstance().getDownloadEntityByUrl(apkEntity.url)
@ -303,52 +287,34 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
PackageInstaller.install(it.context, downloadEntity)
}
}
if (downloadEntity.isPluggable) {
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_插件化安装"
} else {
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_安装"
}
}
DownloadDialogItemStatus.PLUGGABLE -> {
createDownloadTask(it.context, apkEntity, gameEntity, "插件化", traceEvent, entrance, location)
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_插件化"
createDownloadTask(it.context, apkEntity, gameEntity, traceEvent, entrance, location)
}
DownloadDialogItemStatus.UPDATE -> {
createDownloadTask(it.context, apkEntity, gameEntity, "更新", traceEvent, entrance, location)
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_更新"
createDownloadTask(it.context, apkEntity, gameEntity, traceEvent, entrance, location)
}
DownloadDialogItemStatus.COLLECTION -> {
val apkCollection = apkEntity.apkCollection
if (apkCollection != null) {
viewModel.collectionLiveData.postValue(apkCollection)
mtaValue = gameEntity.name + "_" + apkCollection.name + "_查看合集"
} else if (apkEntity.downloadInstruction.isNotEmpty()) {
val fakeCollection = GameCollectionEntity()
fakeCollection.saveApkEntity = arrayListOf(apkEntity)
fakeCollection.name = apkEntity.getPlatformName()
fakeCollection.downloadInstruction = apkEntity.downloadInstruction
viewModel.collectionLiveData.postValue(fakeCollection)
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_查看详情"
} else {
throwExceptionInDebug("合集和下载说明至少一个不为空")
}
}
DownloadDialogItemStatus.LINK -> {
directToLinkPage(it.context, apkEntity.apkLink?.getLinkEntity()!!, entrance, path)
mtaValue = gameEntity.name + "_" + apkEntity.apkLink?.name
}
DownloadDialogItemStatus.INSTALLED -> {
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_已安装"
// do nothing
}
}
throwExceptionInDebug("无法识别当前状态", mtaValue == "未知")
// MtaHelper.onEvent(DownloadDialog.MTA_KEY, "点击", mtaValue)
}
}
@ -356,7 +322,6 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
context: Context,
apkEntity: ApkEntity,
gameEntity: GameEntity,
downloadMethod: String,
traceEvent: ExposureEvent?,
entrance: String,
location: String
@ -367,7 +332,7 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
BrowserInstallHelper.showBrowserInstallHintDialog(
context,
gameEntity,
gameEntity.isVGame() || gameEntity.isSplitXApk()
gameEntity.isSplitXApk()
) {
DownloadDialogHelper.findAvailableDialogAndShow(
context,
@ -393,7 +358,8 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
context,
apkEntity,
gameEntity,
downloadMethod,
false,
false,
entrance,
location,
isSubscribe, traceEvent

View File

@ -95,8 +95,6 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
private GameEntity mGameEntity;
private boolean mIsScroll;
private String mListStatus; // 记录列表领取状态(防止状态在详情改变导致列表状态改变)
private String mName;
private String mTitle;
private boolean isClickReceiveBtnIn = false;//是否点击领取按钮进入
@ -141,7 +139,7 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
if (!"pause".equals(DownloadManager.getInstance().
getStatus(downloadEntity.getUrl()))) {
mDownloadEntity = downloadEntity;
DetailDownloadUtils.detailInvalidate(getDetailViewHolder());
DetailDownloadUtils.updateViewHolder(getDetailViewHolder());
}
}
}
@ -156,8 +154,7 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
private DetailViewHolder getDetailViewHolder() {
// 每次获取需要重新创建, 防止数据刷新
return new DetailViewHolder(mContentView, mGameEntity, mDownloadEntity,
false, mEntrance, mName, mTitle, null); // 下载按钮ViewHolder
return new DetailViewHolder(mContentView, mGameEntity, false, mEntrance, mName, mTitle, null, false); // 下载按钮ViewHolder
}
public static Intent getIntent(Context context, LibaoEntity libaoEntity, boolean isClickReceiveBtnIn, String entrance) {
@ -262,7 +259,7 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
super.onResume();
if (mGameEntity != null
&& (mGameEntity.getApk().size() == 1 || mGameEntity.isReservable())) {
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), true);
DetailDownloadUtils.updateViewHolder(getDetailViewHolder());
}
DownloadManager.getInstance().addObserver(dataWatcher);
}
@ -308,7 +305,6 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
if ((("linged").equals(status) || ("taoed").equals(status)) &&
("ling".equals(beforeStatus) || "tao".equals(beforeStatus))) { //检查是否到了重复领取时间
mListStatus = mLibaoEntity.getStatus();
if (isCanLing()) {
mBaseHandler.sendEmptyMessage(1);
} else {
@ -428,7 +424,7 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
mGameEntity.setWelcomeDialogInfoIfAvailable();
}
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), true);
DetailDownloadUtils.updateViewHolder(getDetailViewHolder());
mAdapter.addLibaoDetail(LibaoDetailActivity.this, true);
}
@ -449,19 +445,6 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
mIsScroll = isScroll;
}
/*@Override
public boolean handleBackPressed() {
// 重置领取状态
if (mLibaoEntity == null) {
return false;
}
String status = mLibaoEntity.getStatus();
if (!TextUtils.isEmpty(status) && status.contains("repeat")) {
mLibaoEntity.setStatus(mListStatus);
}
return false;
}*/
@Override
public void loadDone() {
if (mLlLoading != null) {
@ -549,7 +532,7 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
&& mGameEntity.getApk().size() == 1) {
String url = mGameEntity.getApk().get(0).getUrl();
if (url.equals(status.getUrl())) {
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), false);
DetailDownloadUtils.updateViewHolder(getDetailViewHolder());
}
}
}
@ -563,7 +546,7 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
String packageName = apkEntity.getPackageName();
if (packageName.equals(busFour.getPackageName())) {
ApkActiveUtils.filterHideApk(mGameEntity);
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), false);
DetailDownloadUtils.updateViewHolder(getDetailViewHolder());
}
}
}
@ -583,7 +566,7 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
mDetailBottom.setBackgroundColor(ContextCompat.getColor(this, R.color.background));
mLibaoDetailRv.getRecycledViewPool().clear();
mAdapter.notifyItemRangeChanged(0, mAdapter.getItemCount());
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), false);
DetailDownloadUtils.updateViewHolder(getDetailViewHolder());
if (mLibaoDetailRv.getItemDecorationCount() > 0) {
mLibaoDetailRv.removeItemDecorationAt(0);
mLibaoDetailRv.addItemDecoration(getItemDecoration());

View File

@ -142,6 +142,8 @@ import io.reactivex.SingleSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
@ -299,6 +301,8 @@ public class MainActivity extends BaseActivity {
Config.getGhzsSettings();
} else if (Config.getVSettingEntity() == null) {
Config.refreshVSettingEntity();
} else if (Config.getVNewSettingEntity() == null) {
Config.getNewSetting();
}
// 耗时操作
@ -516,25 +520,31 @@ public class MainActivity extends BaseActivity {
FrameLayout adsFl = findViewById(R.id.adsFl);
int screenWidthInPx = DisplayUtils.getScreenWidth(this);
int screenHeightInPx = DisplayUtils.getScreenHeight(this) + DisplayUtils.getStatusBarHeight(this.getResources());
int screenHeightInPx = DisplayUtils.getScreenHeight(this)
+ DisplayUtils.getStatusBarHeight(this.getResources())
- ExtensionsKt.dip2px(112F);
float screenWidthInDp = DisplayUtils.px2dip(this, screenWidthInPx);
float screenHeightInDp = DisplayUtils.px2dip(this, screenHeightInPx);
AdDelegateHelper.requestSplashAd(
this,
screenWidthInPx,
screenHeightInPx,
screenWidthInDp,
screenHeightInDp,
startAdContainer,
sdkStartAdContainer,
adsFl,
(BaseHandler) mBaseHandler,
() -> {
hideSplashAd();
return null;
}
);
if (startAdContainer != null && sdkStartAdContainer != null && adsFl != null) {
AdDelegateHelper.requestSplashAd(
this,
screenWidthInPx,
screenHeightInPx,
screenWidthInDp,
screenHeightInDp,
startAdContainer,
sdkStartAdContainer,
adsFl,
(BaseHandler) mBaseHandler,
() -> {
hideSplashAd();
return null;
}
);
} else {
hideSplashAd();
}
} else {
hideSplashAd();
}
@ -562,7 +572,7 @@ public class MainActivity extends BaseActivity {
View maskContainer = findViewById(R.id.maskContainer);
if (maskContainer != null) {
maskContainer.setVisibility(View.GONE);
ExtensionsKt.removeFromParent(maskContainer);
ExtensionsKt.removeFromParent(maskContainer, true);
}
}
@ -575,15 +585,21 @@ public class MainActivity extends BaseActivity {
View startAdContainer = findViewById(R.id.startAdContainer);
if (startAdContainer != null) {
startAdContainer.setVisibility(View.GONE);
ExtensionsKt.removeFromParent(startAdContainer);
ExtensionsKt.removeFromParent(startAdContainer, true);
}
View startSdkAdContainer = findViewById(R.id.sdkStartAdContainer);
if (startSdkAdContainer != null) {
startSdkAdContainer.setVisibility(View.GONE);
ExtensionsKt.removeFromParent(startSdkAdContainer);
ExtensionsKt.removeFromParent(startSdkAdContainer, true);
AdDelegateHelper.INSTANCE.cancelSplashAd(this);
}
View startSdkAdIcpContainer = findViewById(R.id.sdkStartAdIcpContainer);
if (startSdkAdIcpContainer != null) {
startSdkAdIcpContainer.setVisibility(View.GONE);
ExtensionsKt.removeFromParent(startSdkAdIcpContainer, true);
}
// 通知优先级高的弹窗可以显示了
AppExecutor.getUiExecutor().execute(() -> {
mMainWrapperFragment.showDialog();
@ -718,14 +734,11 @@ public class MainActivity extends BaseActivity {
ToastUtils.showToast("游戏启动中,请稍后~");
handler.postDelayed(() -> {
VHelper.postOnInitialized(() -> {
if (VHelper.isInstalled(gamePackageName)) {
VHelper.launch(this, gamePackageName, false, true);
} else {
ToastUtils.showToast("应用已被卸载!");
}
return null;
});
if (VHelper.isLegacyGame(gamePackageName)) {
VHelper.postOnInitialized(launchGame(gamePackageName));
} else {
launchGame(gamePackageName).invoke();
}
}, 500);
break;
case KEY_MARKET_DETAILS:
@ -743,6 +756,18 @@ public class MainActivity extends BaseActivity {
}, 500);
}
@NonNull
private Function0<Unit> launchGame(String gamePackageName) {
return () -> {
if (!VHelper.isInnerInstalled(gamePackageName) && !VHelper.isInstalled(gamePackageName)) {
ToastUtils.showToast("应用已被卸载!");
} else {
VHelper.launch(this, gamePackageName, false, true);
}
return null;
};
}
/**
* 应用跳转
*/
@ -875,6 +900,7 @@ public class MainActivity extends BaseActivity {
@Override
protected void onSaveInstanceState(@NotNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.clear();
outState.putInt(CURRENT_PAGE, mMainWrapperFragment.getCurrentItem());
if (mMainWrapperFragment != null) {
outState.putInt(BaseFragment_ViewPager.ARGS_INDEX, mMainWrapperFragment.getCurrentItem());
@ -919,6 +945,8 @@ public class MainActivity extends BaseActivity {
Config.getGhzsSettings();
} else if (Config.getVSettingEntity() == null) {
Config.refreshVSettingEntity();
} else if (Config.getVNewSettingEntity() == null) {
Config.getNewSetting();
}
mPackageViewModel.checkData();
@ -985,7 +1013,7 @@ public class MainActivity extends BaseActivity {
downloadEntity.getName(),
"自动安装"
);
PackageInstaller.install(this, downloadEntity, false);
PackageInstaller.install(this, downloadEntity, false, false);
}
}
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "");

View File

@ -129,7 +129,6 @@ public class NewsDetailActivity extends DownloadToolbarActivity implements OnCli
private GameEntity gameEntity;
private NewsEntity mNewsEntity;
private DownloadEntity mDownloadEntity;
private ExposureEvent mExposureEvent;
@ -143,32 +142,30 @@ public class NewsDetailActivity extends DownloadToolbarActivity implements OnCli
private RecyclerView.ItemDecoration mItemDecoration;
private DataWatcher dataWatcher = new DataWatcher() {
private final DataWatcher dataWatcher = new DataWatcher() {
@Override
public void onDataChanged(DownloadEntity downloadEntity) {
if (gameEntity != null && gameEntity.getApk().size() == 1) {
String url = gameEntity.getApk().get(0).getUrl();
if (url.equals(downloadEntity.getUrl())) {
if (!"pause".equals(DownloadManager.getInstance().
getStatus(downloadEntity.getUrl()))) {
mDownloadEntity = downloadEntity;
DetailDownloadUtils.detailInvalidate(getDetailViewHolder());
if (!"pause".equals(DownloadManager.getInstance().getStatus(downloadEntity.getUrl()))) {
DetailDownloadUtils.updateViewHolder(getDetailViewHolder());
}
}
} else if (gameEntity != null && gameEntity.getApk().size() > 1) {
if (DownloadStatus.downloading.equals(downloadEntity.getStatus())) {
if (getDetailViewHolder().mDownloadTips.getVisibility() == View.GONE || !getDetailViewHolder().mDownloadTips.isAnimating()) {
getDetailViewHolder().mDownloadTips.setVisibility(View.VISIBLE);
ExtensionsKt.setDownloadTipsAnimation(getDetailViewHolder().mDownloadTips, true);
if (getDetailViewHolder().getDownloadTips().getVisibility() == View.GONE || !getDetailViewHolder().getDownloadTips().isAnimating()) {
getDetailViewHolder().getDownloadTips().setVisibility(View.VISIBLE);
ExtensionsKt.setDownloadTipsAnimation(getDetailViewHolder().getDownloadTips(), true);
}
} else if (DownloadStatus.waiting.equals(downloadEntity.getStatus()) || DownloadStatus.done.equals(downloadEntity.getStatus()) ||
DownloadStatus.pause.equals(downloadEntity.getStatus()) || DownloadStatus.timeout.equals(downloadEntity.getStatus()) ||
DownloadStatus.subscribe.equals(downloadEntity.getStatus()) || DownloadStatus.overflow.equals(downloadEntity.getStatus()) ||
DownloadStatus.neterror.equals(downloadEntity.getStatus())) {
getDetailViewHolder().mDownloadTips.setVisibility(View.VISIBLE);
ExtensionsKt.setDownloadTipsAnimation(getDetailViewHolder().mDownloadTips, false);
getDetailViewHolder().getDownloadTips().setVisibility(View.VISIBLE);
ExtensionsKt.setDownloadTipsAnimation(getDetailViewHolder().getDownloadTips(), false);
} else {
getDetailViewHolder().mDownloadTips.setVisibility(View.GONE);
getDetailViewHolder().getDownloadTips().setVisibility(View.GONE);
}
}
}
@ -199,8 +196,15 @@ public class NewsDetailActivity extends DownloadToolbarActivity implements OnCli
private DetailViewHolder getDetailViewHolder() {
// 每次获取需要重新创建, 防止数据刷新
return new DetailViewHolder(mContentView, gameEntity, mDownloadEntity,
true, mEntrance, "新闻详情", adapter.getTitle(), mExposureEvent); // 下载按钮ViewHolder
return new DetailViewHolder(
mContentView,
gameEntity,
true,
mEntrance,
"新闻详情",
adapter.getTitle(),
mExposureEvent,
false); // 下载按钮ViewHolder
}
/**
@ -464,7 +468,7 @@ public class NewsDetailActivity extends DownloadToolbarActivity implements OnCli
super.onResume();
if (gameEntity != null
&& (gameEntity.getApk().size() == 1 || gameEntity.isReservable())) {
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), true);
DetailDownloadUtils.updateViewHolder(getDetailViewHolder());
}
DownloadManager.getInstance().addObserver(dataWatcher);
}
@ -713,7 +717,7 @@ public class NewsDetailActivity extends DownloadToolbarActivity implements OnCli
}
}
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), true);
DetailDownloadUtils.updateViewHolder(getDetailViewHolder());
}
});
}
@ -772,7 +776,7 @@ public class NewsDetailActivity extends DownloadToolbarActivity implements OnCli
if ("delete".equals(status.getStatus()) && gameEntity != null && gameEntity.getApk().size() == 1) {
String url = gameEntity.getApk().get(0).getUrl();
if (url.equals(status.getUrl())) {
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), false);
DetailDownloadUtils.updateViewHolder(getDetailViewHolder());
}
}
}
@ -783,7 +787,7 @@ public class NewsDetailActivity extends DownloadToolbarActivity implements OnCli
if (gameEntity != null && gameEntity.getApk().size() == 1) {
String packageName = gameEntity.getApk().get(0).getPackageName();
if (packageName.equals(busFour.getPackageName())) {
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), false);
DetailDownloadUtils.updateViewHolder(getDetailViewHolder());
}
}
}

View File

@ -10,10 +10,11 @@ import android.view.inputmethod.EditorInfo
import android.widget.*
import androidx.core.widget.doAfterTextChanged
import androidx.core.widget.doOnTextChanged
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.common.util.*
import com.gh.common.util.LogUtils
import com.gh.gamecenter.DisplayType.*
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.db.SearchHistoryDao
@ -108,9 +109,13 @@ open class SearchActivity : BaseActivity() {
updateDisplayType(DEFAULT)
}
SensorsBridge.trackEvent(
"SearchPageShow",
"source_entrance",
trackSearchPageShow()
}
protected open fun trackSearchPageShow(){
SensorsBridge.trackSearchPageShow(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
intent.getStringExtra(EntranceConsts.KEY_SOURCE_ENTRANCE) ?: ""
)
}
@ -178,7 +183,7 @@ open class SearchActivity : BaseActivity() {
mSearchKey = key
updateDisplayType(GAME_DIGEST)
LogUtils.uploadSearchGame("searching", "搜索页", key, "自动搜索")
SensorsBridge.trackEvent("SearchButtonClick", "search_content", key ?: "", "search_type", "输入搜索")
trackSearchButtonClick(key, TRACK_SEARCH_TYPE_INPUT)
}
}
@ -188,7 +193,8 @@ open class SearchActivity : BaseActivity() {
searchEt.setSelection(searchEt.text.length)
updateDisplayType(GAME_DETAIL)
LogUtils.uploadSearchGame("searching", "搜索页", key, "默认搜索")
SensorsBridge.trackEvent("SearchButtonClick", "search_content", key ?: "", "search_type", "默认搜索")
trackSearchButtonClick(key, TRACK_SEARCH_TYPE_DEFAULT)
// MtaHelper.onEvent("游戏搜索", "默认搜索", key)
}
@ -205,7 +211,7 @@ open class SearchActivity : BaseActivity() {
searchEt.setSelection(searchEt.text.length)
updateDisplayType(GAME_DETAIL)
LogUtils.uploadSearchGame("searching", "搜索页", key, "历史搜索")
SensorsBridge.trackEvent("SearchButtonClick", "search_content", key ?: "", "search_type", "历史搜索")
trackSearchButtonClick(key, TRACK_SEARCH_TYPE_HISTORY)
// MtaHelper.onEvent("游戏搜索", "历史搜索", key)
}
@ -220,7 +226,8 @@ open class SearchActivity : BaseActivity() {
} else if (newSearchKey != mSearchKey || mDisplayType != GAME_DETAIL) {
mSearchKey = newSearchKey
if (!TextUtils.isEmpty(mSearchKey)) {
SensorsBridge.trackEvent("SearchButtonClick", "search_content", newSearchKey, "search_type", "输入搜索")
trackSearchButtonClick(newSearchKey, TRACK_SEARCH_TYPE_INPUT)
mDao?.add(mSearchKey)
updateDisplayType(GAME_DETAIL)
} else {
@ -241,6 +248,7 @@ open class SearchActivity : BaseActivity() {
}
transaction.replace(R.id.search_result, fragment, SearchDefaultFragment::class.java.name)
}
GAME_DIGEST -> {
val digestListFragment =
supportFragmentManager.findFragmentByTag(SearchGameIndexFragment::class.java.name) as? SearchGameIndexFragment
@ -248,6 +256,7 @@ open class SearchActivity : BaseActivity() {
digestListFragment.setParams(mSearchKey ?: "", mSearchType.value)
transaction.replace(R.id.search_result, digestListFragment, SearchGameIndexFragment::class.java.name)
}
GAME_DETAIL -> {
val detailListFragment =
supportFragmentManager.findFragmentByTag(SearchGameResultFragment::class.java.name) as? SearchGameResultFragment
@ -255,6 +264,7 @@ open class SearchActivity : BaseActivity() {
detailListFragment.setParams(mSearchKey ?: "", mSearchType.value)
transaction.replace(R.id.search_result, detailListFragment, SearchGameResultFragment::class.java.name)
}
else -> {
//do nothing
}
@ -273,6 +283,7 @@ open class SearchActivity : BaseActivity() {
this, mSearchKey, mSearchType.value, "搜索页面",
search.gameId, search.gameName
)
"search" -> {
DataCollectionUtils.uploadSearch(
this, mSearchKey, mSearchType.value, "搜索页面",
@ -304,6 +315,48 @@ open class SearchActivity : BaseActivity() {
private const val KEY_SEARCH_IMMEDIATELY = "search_immediately"
private const val HINT_TEXT = "搜索游戏..."
const val TRACK_SEARCH_TYPE_INPUT = "输入搜索"
const val TRACK_SEARCH_TYPE_DEFAULT = "默认搜索"
const val TRACK_SEARCH_TYPE_HISTORY = "历史搜索"
@JvmStatic
fun toTrackSearchType(type: String) = when (type) {
SearchType.AUTO.value, SearchType.MANUAL.value -> TRACK_SEARCH_TYPE_INPUT
SearchType.HISTORY.value -> TRACK_SEARCH_TYPE_HISTORY
else -> TRACK_SEARCH_TYPE_DEFAULT
}
@JvmStatic
fun trackSearchResultClick(key: String, type: String) {
SensorsBridge.trackSearchResultClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
key,
toTrackSearchType(type)
)
}
@JvmStatic
fun trackSearchButtonClick(key: String?, type: String) {
SensorsBridge.trackSearchButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
key ?: "",
type
)
}
@JvmStatic
fun trackSearchResultReturn(key: String?, type: String, hasResult: Boolean) {
SensorsBridge.trackSearchResultReturn(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
key ?: "",
toTrackSearchType(type),
hasResult
)
}
@JvmStatic
fun getIntent(
context: Context,

View File

@ -50,25 +50,19 @@ import android.util.Base64;
import androidx.annotation.Nullable;
import com.alibaba.android.arouter.launcher.ARouter;
import com.gh.common.util.CheckLoginUtils;
import com.gh.common.util.DirectUtils;
import com.gh.common.util.DownloadItemUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.gamecenter.common.base.activity.BaseActivity;
import com.gh.gamecenter.common.constant.EntranceConsts;
import com.gh.gamecenter.common.constant.RouteConsts;
import com.gh.gamecenter.common.entity.CommunityEntity;
import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.common.entity.SimpleGameEntity;
import com.gh.gamecenter.core.provider.IQGameProvider;
import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.ToastUtils;
import com.gh.gamecenter.entity.SubjectRecommendEntity;
import com.gh.gamecenter.entity.VideoLinkEntity;
import com.gh.gamecenter.feature.utils.PlatformUtils;
import com.gh.gamecenter.login.entity.UserInfoEntity;
import com.gh.gamecenter.login.user.UserManager;
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel;
import com.gh.gamecenter.video.videomanager.VideoManagerActivity;
import com.gh.vspace.shortcut.OnCreateShortcutResult;
@ -82,11 +76,6 @@ import com.muugi.shortcut.core.Executor;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.function.Function;
import kotlin.Unit;
import kotlin.jvm.functions.Function2;
/**
* Created by LGT on 2016/11/16.
* 链接跳转用
@ -263,7 +252,7 @@ public class SkipActivity extends BaseActivity {
DirectUtils.directToLegacyVideoDetail(this, path, location,
false, TextUtils.isEmpty(gameId) ? "" : gameId, ENTRANCE_BROWSER, "浏览器", TextUtils.isEmpty(referer) ? "" : referer,
TextUtils.isEmpty(type) ? "" : type, TextUtils.isEmpty(act) ? "" : act, TextUtils.isEmpty(paginationType) ? "page" : paginationType, TextUtils.isEmpty(fieldId) ? "" : fieldId,
TextUtils.isEmpty(sectionName) ? "" : sectionName);
TextUtils.isEmpty(sectionName) ? "" : sectionName, false);
break;
case HOST_VIDEO_STREAMING_HOME:
// 把切换放到 MainActivity 处理
@ -396,7 +385,7 @@ public class SkipActivity extends BaseActivity {
EntranceConsts.ENTRANCE_BROWSER);
break;
case EntranceConsts.HOST_GAME_CALENDAR:
DirectUtils.directToGameServerCalendar(this, uri.getQueryParameter(EntranceConsts.KEY_GAME_ID));
DirectUtils.directToGameServerCalendar(this, uri.getQueryParameter(EntranceConsts.KEY_GAME_ID), 0);
break;
case EntranceConsts.HOST_HISTORY_APK:
DirectUtils.directToHistoryApk(this, uri.getQueryParameter(EntranceConsts.KEY_GAME_ID));

View File

@ -1,57 +1,40 @@
package com.gh.gamecenter
import android.Manifest
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.preference.PreferenceManager
import android.text.method.ScrollingMovementMethod
import android.view.KeyEvent
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.app.ActivityCompat
import androidx.viewpager.widget.PagerAdapter
import androidx.viewpager.widget.ViewPager
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.g00fy2.versioncompare.Version
import com.gh.ad.AdDelegateHelper
import com.gh.common.dialog.NewPrivacyPolicyDialogFragment
import com.gh.common.util.*
import com.gh.common.util.GameSubstituteRepositoryHelper.updateGameSubstituteRepository
import com.gh.common.util.UsageStatsHelper.checkAndPostUsageStats
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.callback.SimpleCallback
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.tracker.TrackerLogger
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.provider.IAppProvider
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.entity.PrivacyPolicyEntity
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.feature.utils.PlatformUtils
import com.gh.gamecenter.pkg.PkgHelper
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lightgame.download.FileUtils
import org.json.JSONObject
import pub.devrel.easypermissions.AfterPermissionGranted
import pub.devrel.easypermissions.EasyPermissions
import java.io.BufferedReader
import java.io.File
import java.io.IOException
import java.io.InputStreamReader
import splitties.systemservices.notificationManager
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.ArrayList
/**
* 引导页面
@ -61,14 +44,9 @@ class SplashScreenActivity : BaseActivity() {
private var mSharedPreferences: SharedPreferences? = null
private var mIsNewForThisVersion = false
private var mStartMainActivityDirectly = false // 是否不需要用户点击立即体验就直接跳转首页
private var mViewModel: SplashScreenViewModel? = null
private var mShouldPrefetchData = true
private val mPermissions = arrayOf(
PermissionHelper.PERMISSION_GET_INSTALLED_LIST
)
override fun onCreate(savedInstanceState: Bundle?) {
mViewModel = viewModelProvider()
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
@ -96,18 +74,11 @@ class SplashScreenActivity : BaseActivity() {
// 判断是不是这个版本的新用户
if (mIsNewForThisVersion) {
mContentView.setPadding(0, 0, 0, 0)
val guideLayout = findViewById<ViewPager>(R.id.splash_intro_vp_guide)
guideLayout.adapter = GuidePagerAdapter()
// 判断是不是光环的新用户
if (HaloApp.getInstance().isBrandNewInstall) {
// 引导页需用户点击 “立即体验” 按钮才进入首页所以这里不能置为true
// https://git.ghzs.com/pm/halo-app-issues/-/issues/1422第3点
// mStartMainActivityDirectly = true;
SPUtils.setLong(Constants.SP_INITIAL_USAGE_TIME, System.currentTimeMillis())
if (!PackageFlavorHelper.IS_TEST_FLAVOR) {
showPrivacyDialog(guideLayout)
showPrivacyDialog()
} else {
// Test dex2oat
executeDex2OatInAdvance()
@ -119,11 +90,11 @@ class SplashScreenActivity : BaseActivity() {
"测试环境",
{
SPUtils.setBoolean(Constants.SP_IS_DEV_ENV, false)
showPrivacyDialog(guideLayout)
showPrivacyDialog()
},
{
SPUtils.setBoolean(Constants.SP_IS_DEV_ENV, true)
showPrivacyDialog(guideLayout)
showPrivacyDialog()
},
false,
"",
@ -132,15 +103,10 @@ class SplashScreenActivity : BaseActivity() {
}
} else {
cancelPreviousUpdateTask()
guideLayout.visibility = View.VISIBLE
//requestPermission()
}
} else {
if (com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
showGitLogDialogIfNeeded()
} else {
launchMainActivity()
}
} else {
launchMainActivity()
}
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "")
@ -172,41 +138,63 @@ class SplashScreenActivity : BaseActivity() {
SPUtils.setBoolean(Constants.SP_SENSORS_IS_FIRST_TIME, false)
}
private fun showPrivacyDialog(guideLayout: ViewPager) {
private fun showPrivacyDialog() {
NewPrivacyPolicyDialogFragment.show(this, null) { isSuccess: Boolean ->
if (isSuccess) {
mShouldPrefetchData = false
prefetchData()
val callback = object : SimpleCallback<Boolean> {
override fun onCallback(arg: Boolean) {
// Dialog dismiss 后的回调
guideLayout.visibility = View.VISIBLE
SPUtils.setBoolean(Constants.SP_BRAND_NEW_USER, false)
if (arg) {
requestPermission()
} else {
mStartMainActivityDirectly = false
}
}
}
SPUtils.setBoolean(Constants.SP_BRAND_NEW_USER, false)
mViewModel?.showPrivacyPolicy({
DialogUtils.showPrivacyPolicyDialog(this@SplashScreenActivity, it, callback)
}, {
DialogUtils.showPrivacyPolicyDialog(this@SplashScreenActivity, PrivacyPolicyEntity.createDefaultData(), callback)
})
// 荣耀高版本系统设备在获取已安装列表权限时,会把存储权限等的东西也一并弹出来,导致超量获取权限
// 神奇的是,只需要在获取权限前弹出一条通知,再获取权限就会恢复正常.....
val isMalfunctioningHonorDevice = Build.MANUFACTURER.lowercase() == "honor"
&& Build.VERSION.SDK_INT > Build.VERSION_CODES.R
if (isMalfunctioningHonorDevice) {
showHonorNotification()
mBaseHandler.postDelayed({
requestGetInstallListPermissionAndLaunchMainActivity()
}, 100L)
} else {
requestGetInstallListPermissionAndLaunchMainActivity()
}
} else {
DialogUtils.showPrivacyPolicyDisallowDialog(
this,
PrivacyPolicyEntity.createDefaultData()
) {
showPrivacyDialog(guideLayout)
DialogUtils.showPrivacyPolicyDisallowDialog(this) {
showPrivacyDialog()
}
}
}
}
@RequiresApi(Build.VERSION_CODES.O)
private fun showHonorNotification() {
val channel =
NotificationChannel(HONOR_CULPRIT_CHANNEL, HONOR_CULPRIT_CHANNEL, NotificationManager.IMPORTANCE_MIN)
notificationManager.createNotificationChannel(channel)
val builder = NotificationCompat.Builder(HaloApp.getInstance().application, HONOR_CULPRIT_CHANNEL)
.setSmallIcon(R.mipmap.logo)
.setContentTitle("光环助手荣耀设备启动服务")
val notification = builder.build()
notificationManager.notify(HONOR_CULPRIT_CHANNEL, HONOR_CULPRIT_ID, notification)
notificationManager.cancel(HONOR_CULPRIT_ID)
}
// 尝试获取安装应用列表权限并启动首页(不在乎结果)
private fun requestGetInstallListPermissionAndLaunchMainActivity() {
if (PackageUtils.isSupportGetInstalledAppsPermission(this)
&& PermissionHelper.isGetInstalledListPermissionDisabled(this)
) {
PermissionHelper.requestGetInstalledAppsListPermission(this, true) {
launchMainActivity()
}
} else {
launchMainActivity()
}
}
// 删除更新后的光环助手包
private fun cancelPreviousUpdateTask() {
val all = DownloadManager.getInstance().allDownloadEntity
@ -229,26 +217,12 @@ class SplashScreenActivity : BaseActivity() {
}
}
private fun requestPermission() {
if (!EasyPermissions.hasPermissions(this, *mPermissions)) {
checkAndRequestPermission()
}
}
override fun getLayoutId(): Int {
return if (mIsNewForThisVersion) {
R.layout.activity_splash_intro
} else 0
}
override fun getLayoutId() = 0
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && event.repeatCount == 0) {
if (mIsNewForThisVersion && EasyPermissions.hasPermissions(this, *mPermissions)) {
if (com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
showGitLogDialogIfNeeded()
} else {
launchMainActivity()
}
if (mIsNewForThisVersion) {
launchMainActivity()
} else {
return true
}
@ -282,80 +256,7 @@ class SplashScreenActivity : BaseActivity() {
private fun doFlavorInit() {
HaloApp.getInstance().flavorProvider.init(HaloApp.getInstance(), this, PkgHelper.getActivateRatio())
if (HaloApp.getInstance().channel == "GH_206" || PackageFlavorHelper.IS_TEST_FLAVOR) {
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
}
}
private fun getGitLogString(): String {
if (com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
val stringBuilder = StringBuilder()
var bufferedReader: BufferedReader? = null
var inputStreamReader: InputStreamReader? = null
try {
inputStreamReader = InputStreamReader(assets.open("gitlog.txt"))
bufferedReader = BufferedReader(inputStreamReader)
var line: String?
stringBuilder.append("本光环安装包最近20次代码变更如下")
stringBuilder.append(System.getProperty("line.separator"))
while (bufferedReader.readLine().also { line = it } != null) {
line?.let {
val urlRegex = Regex("http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?")
if (urlRegex.containsMatchIn(it)) {
line = urlRegex.replace(it, "")
}
}
stringBuilder.append(line)
stringBuilder.append(System.getProperty("line.separator"))
}
} catch (e: IOException) {
e.printStackTrace()
} finally {
inputStreamReader?.close()
bufferedReader?.close()
}
return stringBuilder.toString()
} else {
return ""
}
}
private fun showGitLogDialogIfNeeded() {
if (com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
val gitLog = getGitLogString()
if (gitLog.isNotEmpty()) {
val md5 = MD5Utils.getContentMD5(gitLog)
if (SPUtils.getString(Constants.GIT_LOG_MD5, "") != md5) {
SPUtils.setString(Constants.GIT_LOG_MD5, md5)
DialogHelper.showDialog(
this,
"${PackageUtils.getGhVersionName()} ${com.gh.gamecenter.common.BuildConfig.BUILD_TIME}",
gitLog,
"确定",
"",
{
launchMainActivity()
},
extraConfig = DialogHelper.Config(
centerTitle = true,
centerContent = false
),
uiModificationCallback = { binding ->
binding.contentTv.run {
maxHeight = 500F.dip2px()
textSize = 10F
isVerticalScrollBarEnabled = true
movementMethod = ScrollingMovementMethod.getInstance()
}
},
)
} else {
launchMainActivity()
}
} else {
launchMainActivity()
}
}
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
}
private fun prefetchData() {
@ -387,107 +288,11 @@ class SplashScreenActivity : BaseActivity() {
}
}
@AfterPermissionGranted(REQUEST_PERMISSION_TAG)
private fun checkAndRequestPermission() {
if (EasyPermissions.hasPermissions(this, *mPermissions)) {
onPermissionsGranted(REQUEST_PERMISSION_TAG, ArrayList(mPermissions.toList()))
if (mStartMainActivityDirectly) {
if (com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
showGitLogDialogIfNeeded()
} else {
launchMainActivity()
}
}
} else {
ActivityCompat.requestPermissions(this, mPermissions, REQUEST_PERMISSION_TAG)
}
}
override fun onPermissionsDenied(requestCode: Int, perms: List<String>) {
if (mStartMainActivityDirectly) {
if (com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
showGitLogDialogIfNeeded()
} else {
launchMainActivity()
}
}
}
override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>?) {
super.onPermissionsGranted(requestCode, perms)
if (perms?.contains(Manifest.permission.READ_EXTERNAL_STORAGE) == true) {
// 恢复畅玩数据
VHelper.recoverVDataIfPossible()
// 检查是否有旧版本光环,有就删掉
runOnIoThread { deleteOutdatedUpdatePackage() }
}
}
// 检查下载文件夹下是否有旧版本的光环助手的包,有则删除
private fun deleteOutdatedUpdatePackage() {
try {
val folder = File(FileUtils.getDownloadDir(this) + File.separator)
if (folder.isDirectory) {
for (file in folder.listFiles()) {
if (!file.isDirectory && file.name.startsWith("光环助手V")) {
val name = file.name
val index = name.indexOf("_")
if (index != -1) {
val versionString = name.substring(name.indexOf("V") + 1, index)
val currentVersion = Version(PackageUtils.getGhVersionName())
if (currentVersion.isHigherThan(versionString) || currentVersion.isEqual(versionString)) {
file.delete()
}
}
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private inner class GuidePagerAdapter : PagerAdapter() {
private val mPics = intArrayOf(R.drawable.splash_01)
override fun getCount(): Int {
return mPics.size
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val view = View.inflate(container.context, R.layout.splash_guide_item, null)
val ivImage = view.findViewById<ImageView>(R.id.splsh_guide_iv_image)
ivImage.setImageResource(mPics[position])
if (position == mPics.size - 1) {
val tvSkip = view.findViewById<TextView>(R.id.splsh_guide_tv_skip)
// 如果屏幕特短,或者是平板的横屏显示,把图片改成按高度显示
if (DisplayUtils.isUltraShortScreen(this@SplashScreenActivity)) {
ivImage.scaleType = ImageView.ScaleType.CENTER_INSIDE
}
tvSkip.setOnClickListener {
if (com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
showGitLogDialogIfNeeded()
} else {
launchMainActivity()
}
}
}
container.addView(view)
return view
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
container.removeView(`object` as View)
}
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view === `object`
}
}
companion object {
private const val REQUEST_PERMISSION_TAG = 30001
const val HONOR_CULPRIT_ID = 12324
const val HONOR_CULPRIT_CHANNEL = "荣耀通道"
@JvmStatic
fun getSplashScreenIntent(context: Context?, bundle: Bundle?): Intent {

View File

@ -15,7 +15,6 @@ import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.feature.entity.AuthDialogEntity
import com.gh.gamecenter.entity.DeviceDialogEntity
import com.gh.gamecenter.entity.PrivacyPolicyEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.android.schedulers.AndroidSchedulers
@ -91,25 +90,6 @@ class SplashScreenViewModel(application: Application) : AndroidViewModel(applica
})
}
/**
* 获取隐私政策指引概要
*/
@SuppressLint("CheckResult")
fun showPrivacyPolicy(successCallBack: (PrivacyPolicyEntity) -> Unit, onFailureCallBack: () -> Unit) {
mApi.privacyPolicy
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<PrivacyPolicyEntity>() {
override fun onSuccess(data: PrivacyPolicyEntity) {
successCallBack.invoke(data)
}
override fun onFailure(exception: Exception) {
onFailureCallBack.invoke()
}
})
}
/**
* 判断新老用户
*/

View File

@ -0,0 +1,34 @@
package com.gh.gamecenter
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.utils.updateStatusBarColor
import com.halo.assistant.fragment.user.auth.UserAuthFragment
class UserAuthActivity : ToolBarActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setNavigationTitle("已获得认证")
updateStatusBarColor(R.color.background_white, R.color.background_white)
}
override fun isAutoResetViewBackgroundEnabled(): Boolean = false
override fun onDarkModeChanged() {
super.onDarkModeChanged()
updateStatusBarColor(R.color.background_white, R.color.background_white)
}
companion object {
fun getIntent(context: Context?): Intent? {
return getTargetIntent(
context,
UserAuthActivity::class.java,
UserAuthFragment::class.java
)
}
}
}

View File

@ -132,26 +132,6 @@ open class WebActivity : ToolBarActivity() {
)
}
// 获取安全认证页
@JvmStatic
fun getSecurityCertificationIntent(context: Context): Intent {
val bundle = Bundle()
bundle.putString(
EntranceConsts.KEY_GAMENAME,
context.getString(R.string.comment_security_certification)
)
bundle.putString(
EntranceConsts.KEY_URL,
context.getString(R.string.comment_security_certification_url)
)
bundle.putBoolean(WebFragment.KEY_IS_SECURITY_CERTIFICATION, true)
return getTargetIntent(
context,
WebActivity::class.java,
WebFragment::class.java, bundle
)
}
// 获取工具箱页面
@JvmStatic
fun getWebByCollectionTools(

View File

@ -0,0 +1,104 @@
package com.gh.gamecenter.adapter
import android.content.Context
import android.content.Intent
import android.util.SparseIntArray
import android.view.ViewGroup
import androidx.core.util.forEach
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import com.gh.gamecenter.common.BuildConfig
/***
* 支持替换Fragment的FragmentPagerAdapter
*/
class MainFragmentPagerAdapter(
private val mContext: Context,
private val mFragmentManager: FragmentManager,
private val mFragmentsList: ArrayList<Fragment>,
) : FragmentPagerAdapter(mFragmentManager) {
private val mFragmentPositionSparseArray = SparseIntArray() // 记录Fragment的位置
private val mFragmentPositionUpdateSparseArray = SparseIntArray() // 记录更新后Fragment的位置
init {
setFragmentPositionSparseArray()
setFragmentPositionSparseArrayForUpdate()
}
private fun setFragmentPositionSparseArray() {
mFragmentPositionSparseArray.clear()
mFragmentsList.forEachIndexed { index, _ ->
mFragmentPositionSparseArray.put(getItemId(index).toInt(), index)
}
}
private fun setFragmentPositionSparseArrayForUpdate() {
mFragmentPositionUpdateSparseArray.clear()
mFragmentsList.forEachIndexed { index, _ ->
mFragmentPositionUpdateSparseArray.put(getItemId(index).toInt(), index)
}
}
fun replaceFragment(position: Int, newFragment: Fragment) {
val oldFragment = mFragmentsList[position]
mFragmentManager.beginTransaction().run {
remove(oldFragment)
commitNowAllowingStateLoss()
}
mFragmentsList.remove(oldFragment)
mFragmentsList.add(position, newFragment)
notifyItemChanged()
}
private fun notifyItemChanged() {
setFragmentPositionSparseArrayForUpdate()
notifyDataSetChanged()
setFragmentPositionSparseArray()
}
override fun getCount(): Int = mFragmentsList.size
override fun getItemPosition(`object`: Any): Int {
val hashCode = `object`.hashCode()
val position = mFragmentPositionUpdateSparseArray.get(hashCode, -1)
if (position == -1) {
return POSITION_NONE
} else {
mFragmentPositionSparseArray.forEach { key, value ->
if (key == hashCode) {
return if (position == value) {
POSITION_UNCHANGED
} else {
POSITION_NONE
}
}
}
}
return POSITION_UNCHANGED
}
override fun getItem(position: Int): Fragment = mFragmentsList[position]
override fun getItemId(position: Int): Long = mFragmentsList[position].hashCode().toLong()
override fun finishUpdate(container: ViewGroup) {
// 替换Fragment闪退关联问题REPLACE_FRAGMENT_CRASH
try {
super.finishUpdate(container)
} catch (e: Throwable) {
if (BuildConfig.DEBUG) {
throw e
} else {
e.printStackTrace()
// 重启APP
val pm = mContext.packageManager
val intent = pm?.getLaunchIntentForPackage(mContext.packageName)
val mainIntent = Intent.makeRestartActivityTask(intent!!.component)
mContext.startActivity(mainIntent)
Runtime.getRuntime().exit(0)
}
}
}
}

View File

@ -1,569 +0,0 @@
package com.gh.gamecenter.adapter.viewholder;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
import com.airbnb.lottie.LottieAnimationView;
import com.gh.common.chain.BrowserInstallHandler;
import com.gh.common.chain.CertificationHandler;
import com.gh.common.chain.ChainBuilder;
import com.gh.common.chain.ChainHandler;
import com.gh.common.chain.CheckDownloadHandler;
import com.gh.common.chain.CheckStoragePermissionHandler;
import com.gh.common.chain.DownloadDialogHelperHandler;
import com.gh.common.chain.GamePermissionHandler;
import com.gh.common.chain.LandPageAddressHandler;
import com.gh.common.chain.OverseaDownloadHandler;
import com.gh.common.chain.PackageCheckHandler;
import com.gh.common.chain.UnsupportedFeatureHandler;
import com.gh.common.chain.UpdateNewSimulatorHandler;
import com.gh.common.chain.ValidateVSpaceHandler;
import com.gh.common.chain.VersionNumberHandler;
import com.gh.common.constant.Config;
import com.gh.common.dialog.DeviceRemindDialog;
import com.gh.common.dialog.GameOffServiceDialogFragment;
import com.gh.common.filter.RegionSetting;
import com.gh.common.filter.RegionSettingHelper;
import com.gh.common.history.HistoryHelper;
import com.gh.common.simulator.NewSimulatorGameManager;
import com.gh.common.simulator.SimulatorDownloadManager;
import com.gh.common.simulator.SimulatorGameManager;
import com.gh.common.util.CheckLoginUtils;
import com.gh.common.util.DetailDownloadUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DirectUtils;
import com.gh.common.util.LogUtils;
import com.gh.common.util.PackageInstaller;
import com.gh.common.util.PackageLauncher;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.ReservationHelper;
import com.gh.common.xapk.XapkInstaller;
import com.gh.common.xapk.XapkUnzipStatus;
import com.gh.download.DownloadManager;
import com.gh.download.dialog.DownloadDialog;
import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WebActivity;
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.eventbus.EBReuse;
import com.gh.gamecenter.common.utils.DataLogUtils;
import com.gh.gamecenter.common.utils.DialogHelper;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.common.utils.NewFlatLogUtils;
import com.gh.gamecenter.common.utils.PermissionHelper;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.core.utils.PageSwitchDataHelper;
import com.gh.gamecenter.core.utils.StringUtils;
import com.gh.gamecenter.eventbus.EBScroll;
import com.gh.gamecenter.feature.entity.ApkEntity;
import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.feature.entity.SimulatorEntity;
import com.gh.gamecenter.feature.exposure.ExposureEvent;
import com.gh.gamecenter.feature.view.DownloadButton;
import com.gh.gamecenter.gamedetail.GameDetailFragment;
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment;
import com.gh.gamecenter.teenagermode.TeenagerModeActivity;
import com.gh.vspace.VDownloadManagerActivity;
import com.gh.vspace.VHelper;
import com.lightgame.download.DownloadEntity;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.Utils;
import org.greenrobot.eventbus.EventBus;
import java.io.File;
import java.util.HashMap;
/**
* Created by khy on 27/06/17.
* 详情页面下载ViewHolder
*/
public class DetailViewHolder {
public Context context;
public GameEntity gameEntity;
public DownloadEntity downloadEntity;
public ExposureEvent traceEvent;
public boolean isNewsDetail; // 新闻详情不显示下载的游戏名, 只显示下载状态
public View downloadBottom;
public DownloadButton mDownloadPb;
public LottieAnimationView mDownloadTips;
public TextView mOverlayTv; // 额外的文字 (用于一些含图片的情况)
public TextView mMultiVersionDownloadTv; // 多版本下载文字
// 注意View的命名
public DetailViewHolder(View view, GameEntity gameEntity, DownloadEntity downloadEntity,
boolean isNewsDetail, String entrance, String name, String title, @Nullable ExposureEvent traceEvent) {
downloadBottom = view.findViewById(R.id.detail_ll_bottom);
mDownloadPb = view.findViewById(R.id.detail_progressbar);
mDownloadTips = view.findViewById(R.id.downloadTipsLottie);
mOverlayTv = view.findViewById(R.id.overlayTv);
mMultiVersionDownloadTv = view.findViewById(R.id.multiVersionDownloadTv);
this.gameEntity = gameEntity;
this.downloadEntity = downloadEntity;
this.traceEvent = traceEvent;
this.isNewsDetail = isNewsDetail;
this.context = view.getContext();
final OnDetailDownloadClickListener listener = new OnDetailDownloadClickListener(this, entrance, name, title, traceEvent);
mDownloadPb.setOnClickListener(listener);
ExtensionsKt.putWidgetBusinessName(mDownloadPb, "游戏详情页");
ExtensionsKt.putObject(mDownloadPb, gameEntity);
restoreDialogFragment();
}
public TextView getOverlayTv() {
return mOverlayTv;
}
private void restoreDialogFragment() {
DialogFragment gamePermissionDialogFragment =
(DialogFragment) ((AppCompatActivity) context).getSupportFragmentManager().findFragmentByTag(GamePermissionDialogFragment.class.getName());
if (gamePermissionDialogFragment != null) {
gamePermissionDialogFragment.dismissAllowingStateLoss();
}
}
static class OnDetailDownloadClickListener implements View.OnClickListener {
private final DetailViewHolder mViewHolder;
private final GameEntity mGameEntity;
private DownloadEntity mDownloadEntity;
private final String mEntrance;
private final String mName;
private final String mTitle;
private final ExposureEvent mTraceEvent;
public OnDetailDownloadClickListener(DetailViewHolder viewHolder, String entrance, String name, String title, ExposureEvent traceEvent) {
mViewHolder = viewHolder;
mGameEntity = viewHolder.gameEntity;
mDownloadEntity = viewHolder.downloadEntity;
mEntrance = entrance;
mName = name;
mTitle = title;
mTraceEvent = traceEvent;
}
@Override
public void onClick(View v) {
v.setTag(null);
if (mViewHolder.mDownloadPb.getButtonStyle() != DownloadButton.ButtonStyle.INSTALL_NORMAL
&& mViewHolder.mDownloadPb.getButtonStyle() != DownloadButton.ButtonStyle.INSTALL_PLUGIN
&& mViewHolder.mDownloadPb.getButtonStyle() != DownloadButton.ButtonStyle.LAUNCH_OR_OPEN) {
if (mGameEntity.isVGame() && !VHelper.INSTANCE.shouldLaunchGameAfterInstallation()) {
// 畅玩游戏的非真实点击下载按钮下载不需要滚动到特定地方
} else {
EventBus.getDefault().post(new EBScroll(Constants.EB_GAME_DETAIL, mGameEntity.getId()));
}
}
if (mDownloadEntity == null) {
mDownloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity);
}
if (mDownloadEntity != null) {
String xapkStatus = mDownloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
if (XapkUnzipStatus.SUCCESS.name().equals(xapkStatus) && XapkInstaller.INSTANCE.isInstalling(mDownloadEntity.getPath())) {// 安装过程中避免重复点击
return;
}
if (XapkUnzipStatus.UNZIPPING.name().equals(xapkStatus)) {
XapkInstaller.cancelUnzipTask(mDownloadEntity);
return;
} else if (XapkUnzipStatus.FAILURE.name().equals(xapkStatus)) {
PermissionHelper.checkStoragePermissionBeforeAction(
mViewHolder.context,
mGameEntity.getId(),
mGameEntity.getName() != null ? mGameEntity.getName() : "",
mGameEntity.getCategoryChinese(),
() -> {
if (mDownloadEntity != null) {
final String path = mDownloadEntity.getPath();
if (FileUtils.isEmptyFile(path)) {
Utils.toast(mViewHolder.context, R.string.install_failure_hint);
DownloadManager.getInstance().cancel(mDownloadEntity.getUrl());
} else {
NewFlatLogUtils.INSTANCE.logGameInstall(
mDownloadEntity.getGameId(),
mDownloadEntity.getName(),
"主动安装"
);
SensorsBridge.trackInstallGameClick(
mDownloadEntity.getGameId(),
mDownloadEntity.getName(),
"主动安装"
);
PackageInstaller.install(mViewHolder.context, mDownloadEntity);
}
}
});
return;
}
}
switch (mViewHolder.mDownloadPb.getButtonStyle()) {
case NONE_WITH_HINT:
case NONE:
String offStatus = mGameEntity.getDownloadOffStatus();
if (offStatus != null && !"off".equals(offStatus)) {
if ("dialog".equals(offStatus)) {
showOffServiceDialog(mGameEntity.getDownloadOffDialog());
} else if ("toast".equals(offStatus)) {
EventBus.getDefault().post(new EBReuse(GameDetailFragment.SKIP_RATING));
Utils.toast(mViewHolder.context, "该游戏因故暂不提供下载,具体详情可在相关评论中查看,敬请谅解~");
}
} else {
Utils.toast(mViewHolder.context, "该游戏已关闭下载");
}
break;
case NORMAL:
final RegionSetting.GameH5Download gameH5Download = RegionSettingHelper.getGameH5DownloadByGameId(mGameEntity.getId());
if (gameH5Download != null) {
DialogUtils.showGameH5DownloadDialog(mViewHolder.context, mGameEntity, gameH5Download);
break;
} else {
DataLogUtils.uploadGameLog(mViewHolder.context, mGameEntity.getId(), mGameEntity.getName(), mEntrance);
}
case PLUGIN:
ChainBuilder builder = new ChainBuilder();
builder.addHandler(new UnsupportedFeatureHandler());
builder.addHandler(new UpdateNewSimulatorHandler());
builder.addHandler(new GamePermissionHandler());
builder.addHandler(new CheckStoragePermissionHandler());
builder.addHandler(new ValidateVSpaceHandler());
if (mGameEntity.getApk().size() == 1) {
builder.addHandler(new BrowserInstallHandler());
builder.addHandler(new PackageCheckHandler());
builder.addHandler(new DownloadDialogHelperHandler());
builder.addHandler(new CertificationHandler());
builder.addHandler(new VersionNumberHandler());
builder.addHandler(new LandPageAddressHandler());
builder.addHandler(new OverseaDownloadHandler());
builder.addHandler(new CheckDownloadHandler());
builder.setProcessEndCallback(o -> {
download((boolean) o);
return null;
});
final ChainHandler chainHandler = builder.buildHandlerChain();
if (chainHandler != null) {
chainHandler.handleRequest(v.getContext(), mGameEntity);
}
} else {
builder.addHandler(new CertificationHandler());
builder.addHandler(new VersionNumberHandler());
builder.setProcessEndCallback(o -> {
DownloadDialog.showDownloadDialog(
mViewHolder.context,
mGameEntity,
mTraceEvent,
StringUtils.buildString(mEntrance, "+(", mName, "[", mTitle, "])"),
mName + ":" + mTitle);
return null;
});
final ChainHandler chainHandler = builder.buildHandlerChain();
if (chainHandler != null) {
chainHandler.handleRequest(v.getContext(), mGameEntity);
}
}
break;
case LAUNCH_OR_OPEN:
if (mGameEntity.getApk().size() == 1) {
//启动模拟器游戏
if (SimulatorGameManager.isSimulatorGame(mGameEntity)) {
if (NewSimulatorGameManager.shouldShowUpdateNewSimulatorAlert(mViewHolder.context)) {
NewSimulatorGameManager.showUpdateNewsSimulator(mViewHolder.context, mGameEntity, null);
return;
}
DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(mGameEntity.getApk().get(0).getUrl());
if (downloadEntity != null) {
File file = new File(downloadEntity.getPath());
if (!file.exists()) {
download(false);
return;
}
SimulatorGameManager.launchSimulatorGame(downloadEntity, mGameEntity);
}
return;
}
if (mGameEntity.isVGame()) {
VHelper.installOrLaunch(mViewHolder.context, mGameEntity, null);
return;
}
PackageLauncher.launchApp(mViewHolder.context, mGameEntity, mGameEntity.getApk().get(0).getPackageName());
} else {
GamePermissionDialogFragment.show((AppCompatActivity) mViewHolder.context, mGameEntity, mGameEntity.getInfo(), () -> {
PermissionHelper.checkStoragePermissionBeforeAction(
mViewHolder.context,
mGameEntity.getId(),
mGameEntity.getName() != null ? mGameEntity.getName() : "",
mGameEntity.getCategoryChinese(),
() -> {
DownloadDialog.showDownloadDialog(
mViewHolder.context,
mGameEntity,
mTraceEvent,
StringUtils.buildString(mEntrance, "+(", mName, "[", mTitle, "])"),
mName + ":" + mTitle);
});
});
}
break;
case INSTALL_PLUGIN:
case INSTALL_NORMAL:
if (mGameEntity.getApk().isEmpty()) return;
NewFlatLogUtils.INSTANCE.logGameInstall(
mDownloadEntity.getGameId(),
mDownloadEntity.getName(),
"主动安装"
);
SensorsBridge.trackInstallGameClick(
mDownloadEntity.getGameId(),
mDownloadEntity.getName(),
"主动安装"
);
ApkEntity apk = mGameEntity.getApk().get(0);
DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apk.getUrl());
if (mGameEntity.getSimulator() != null) {
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(mViewHolder.context, mGameEntity.getSimulator().getApk().getPackageName());
boolean isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(mViewHolder.context);
boolean isInstalledOldSimulator = SimulatorGameManager.isOldSimulatorInstalled(mViewHolder.context);
SimulatorEntity simulator = mGameEntity.getSimulator();
SimulatorEntity newSimulator = Config.getNewSimulatorEntitySetting();
if (!isInstalledOldSimulator && newSimulator != null && newSimulator.getActive()) {
simulator = newSimulator;
}
if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(mGameEntity) && !isInstalled && !isInstalledNewSimulator) {
SimulatorDownloadManager.getInstance().showDownloadDialog(mViewHolder.context, simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH, mGameEntity.getId(), mGameEntity.getName(), mGameEntity.getCategoryChinese(), null);
return;
}
}
if (mGameEntity.isVGame()) {
VHelper.installOrLaunch(v.getContext(), mGameEntity, null);
return;
}
PermissionHelper.checkStoragePermissionBeforeAction(
mViewHolder.context,
mGameEntity.getId(),
mGameEntity.getName() != null ? mGameEntity.getName() : "",
mGameEntity.getCategoryChinese(),
() -> {
if (mDownloadEntity == null) {
mDownloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity);
}
if (mDownloadEntity != null) {
final String path = mDownloadEntity.getPath();
if (FileUtils.isEmptyFile(path)) {
Utils.toast(mViewHolder.context, R.string.install_failure_hint);
DownloadManager.getInstance().cancel(mDownloadEntity.getUrl());
} else {
PackageInstaller.install(mViewHolder.context, mDownloadEntity);
}
}
});
break;
case RESERVABLE:
GamePermissionDialogFragment.show((AppCompatActivity) mViewHolder.context, mGameEntity, mGameEntity.getInfo(), () -> {
SensorsBridge.trackEvent("AppointmentGame", "game_name", mGameEntity.getName(), "game_id", mGameEntity.getId());
CheckLoginUtils.checkLogin(mViewHolder.context, mEntrance, () -> {
ReservationHelper.reserve(mViewHolder.context, mGameEntity.getId(), mGameEntity.getName(), () -> {
LogUtils.logReservation(mGameEntity, mTraceEvent);
DetailDownloadUtils.detailInitDownload(mViewHolder, false);
});
});
});
break;
case RESERVED:
if ("download".equals(mGameEntity.getReserveStatus())) {
ReservationHelper.showDeleteReservationDialog(mViewHolder.context, () -> {
ReservationHelper.deleteReservation(mGameEntity, () -> {
DetailDownloadUtils.detailInitDownload(mViewHolder, false);
});
});
} else {
ReservationHelper.showCancelReservationDialog(mViewHolder.context, () -> {
ReservationHelper.cancelReservation(mGameEntity, () -> {
DetailDownloadUtils.detailInitDownload(mViewHolder, false);
});
});
}
break;
case H5_GAME:
LinkEntity linkEntity = mGameEntity.getH5Link();
boolean isPlay = "play".equals(linkEntity.getType()); // 是否为开始玩
if (isPlay) {
HistoryHelper.insertGameEntity(mGameEntity);
}
GamePermissionDialogFragment.show((AppCompatActivity) mViewHolder.context, mGameEntity, mGameEntity.getInfo(), () -> {
Intent i = new Intent(WebActivity.getIntentForWebGame(mViewHolder.context, linkEntity.getLink(), mGameEntity.getName(), isPlay, linkEntity.getCloseButton()));
mViewHolder.context.startActivity(i);
});
break;
case UPDATING:
Utils.toast(mViewHolder.context, "正在加急更新版本,敬请后续留意");
break;
case TEENAGER_MODE:
SensorsBridge.trackAdolescentModeDialogShow(
mGameEntity.getId(),
mGameEntity.getName() != null ? mGameEntity.getName() : "",
mGameEntity.getCategoryChinese()
);
DialogHelper.showCenterDialog(
mViewHolder.context,
"提示", "当前处于儿童/青少年模式, \n暂不提供游戏下载", "退出青少年模式", "关闭",
() -> {
mViewHolder.context.startActivity(TeenagerModeActivity.getIntent(mViewHolder.context));
SensorsBridge.trackAdolescentModeDialogClick(
"退出青少年模式",
mGameEntity.getId(),
mGameEntity.getName() != null ? mGameEntity.getName() : "",
mGameEntity.getCategoryChinese()
);
},
() -> {
SensorsBridge.trackAdolescentModeDialogClick(
"关闭",
mGameEntity.getId(),
mGameEntity.getName() != null ? mGameEntity.getName() : "",
mGameEntity.getCategoryChinese()
);
},
() -> {
SensorsBridge.trackAdolescentModeDialogClick(
"关闭弹窗",
mGameEntity.getId(),
mGameEntity.getName() != null ? mGameEntity.getName() : "",
mGameEntity.getCategoryChinese()
);
}
);
break;
case SPECIAL_DOWNLOAD:
RegionSetting.GameSpecialDownloadInfo info = RegionSettingHelper.getGameSpecialDownloadInfo(mGameEntity.getId());
if (info != null && !TextUtils.isEmpty(info.getBbsId())) {
if (!TextUtils.isEmpty(info.getTopId())) {
HashMap<String, String> map = new HashMap<>();
map.put(EntranceConsts.KEY_TOP_ID, info.getTopId());
PageSwitchDataHelper.pushCurrentPageData(map);
}
DirectUtils.directForumDetail(mViewHolder.context, info.getBbsId(), mEntrance);
}
break;
case WAITING:
Utils.toast(mViewHolder.context, "最多只能同时下载三个任务,请稍等");
break;
case DOWNLOADING_NORMAL:
case DOWNLOADING_PLUGIN:
if (mDownloadEntity == null) {
mDownloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity);
}
if (mDownloadEntity != null) {
if (mViewHolder.mDownloadPb.getText().contains("继续加载")) {
DownloadManager.getInstance().resume(mDownloadEntity, true);
} else {
DownloadManager.getInstance().pause(mDownloadEntity.getUrl());
mViewHolder.mDownloadPb.setText("继续加载 " + mDownloadEntity.getPercent() + "%");
}
}
break;
default:
if (mGameEntity.isVGame()) {
mViewHolder.context.startActivity(VDownloadManagerActivity.getIntent(mViewHolder.context, true));
} else if (!mGameEntity.getApk().isEmpty()) {
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(mViewHolder.context,
mGameEntity.getApk().get(0).getUrl(),
StringUtils.buildString(mEntrance, "+(", mName, "[", mTitle, "])"));
mViewHolder.context.startActivity(intent);
}
break;
}
}
private void showOffServiceDialog(GameEntity.Dialog dialog) {
GameOffServiceDialogFragment dialogFragment = GameOffServiceDialogFragment.getInstance(dialog);
dialogFragment.show(((FragmentActivity) mViewHolder.context).getSupportFragmentManager(), "off_service_dialog");
}
private void download(boolean isSubscribe) {
String str = mViewHolder.mDownloadPb.getText().toString();
String method;
if (str.contains("更新")) {
method = "更新";
} else if (str.contains("插件化")) {
method = "插件化";
} else {
method = mViewHolder.context.getString(R.string.download);
}
if (mGameEntity.getApk().size() == 0) {
Utils.toast(mViewHolder.context, "暂时无法下载,请稍后再试");
return;
}
ApkEntity apkEntity = mGameEntity.getApk().get(0);
String msg = FileUtils.isCanDownload(mViewHolder.context, apkEntity.getSize());
if (TextUtils.isEmpty(msg)) {
if (mGameEntity.isVGame() && "更新".equals(method)) {
VHelper.updateOrReDownload(mGameEntity);
} else {
DownloadManager.createDownload(mViewHolder.context,
apkEntity,
mGameEntity,
method,
StringUtils.buildString(mEntrance, "+(", mName, "[", mTitle, "])"),
mName + ":" + mTitle,
isSubscribe,
mTraceEvent);
}
mViewHolder.mDownloadPb.setProgress(0);
mViewHolder.mDownloadPb.setButtonStyle("插件化".equals(method) ?
DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN : DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
DeviceRemindDialog.Companion.showDeviceRemindDialog(mViewHolder.context, mGameEntity);
//去掉游戏详情页启动畅玩游戏弹出加载框的行为 https://jira.shanqu.cc/browse/GHZS-2087
/*if (mGameEntity.isVGame()
&& mViewHolder.context.getString(R.string.download).equals(method)
&& VHelper.INSTANCE.shouldLaunchGameAfterInstallation()
&& !(VHelper.INSTANCE.isGAppsRequired(mGameEntity) && !VHelper.INSTANCE.isGAppsInstalled())) {
mViewHolder.context.startActivity(VSpaceLoadingActivity.getIntent(mViewHolder.context, mGameEntity, false));
}*/
} else {
Utils.toast(mViewHolder.context, msg);
}
}
}
}

View File

@ -0,0 +1,647 @@
package com.gh.gamecenter.adapter.viewholder
import android.content.Context
import android.content.Intent
import android.text.TextUtils
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentActivity
import com.airbnb.lottie.LottieAnimationView
import com.gh.common.chain.*
import com.gh.common.constant.Config
import com.gh.common.dialog.DeviceRemindDialog
import com.gh.common.dialog.GameOffServiceDialogFragment
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.history.HistoryHelper
import com.gh.common.simulator.NewSimulatorGameManager
import com.gh.common.simulator.SimulatorDownloadManager
import com.gh.common.simulator.SimulatorGameManager
import com.gh.common.util.*
import com.gh.common.util.LogUtils
import com.gh.common.xapk.XapkInstaller
import com.gh.common.xapk.XapkUnzipStatus
import com.gh.download.DownloadManager
import com.gh.download.dialog.DownloadDialog
import com.gh.gamecenter.DownloadManagerActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.eventbus.EBReuse
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.NewFlatLogUtils
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.PageSwitchDataHelper
import com.gh.gamecenter.core.utils.StringUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.eventbus.EBScroll
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.view.DownloadButton
import com.gh.gamecenter.feature.view.DownloadButton.ButtonStyle
import com.gh.gamecenter.gamedetail.GameDetailFragment
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
import com.gh.gamecenter.teenagermode.TeenagerModeActivity.Companion.getIntent
import com.gh.vspace.VHelper
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import com.lightgame.download.FileUtils
import org.greenrobot.eventbus.EventBus
import java.io.File
// 虽然叫 ViewHolder但其实就是一个用来临时放 View 和相关操作的包裹类
class DetailViewHolder(
view: View,
val gameEntity: GameEntity,
val isNewsDetail: Boolean, // 新闻详情不显示下载的游戏名, 只显示下载状态
entrance: String?,
name: String,
title: String?,
val traceEvent: ExposureEvent?,
val isSupportDualButton: Boolean = false // 是否支持双下载按钮,不支持的时候跟普通列表意义选用优先级高的那个来显示
) {
var context: Context
var downloadBottom: View
// 本地下载的占位下载按钮
val localDownloadButton: DownloadButton?
// 本地下载的尺寸 TV
val localDownloadSizeTv: TextView?
// 本地下载的标题 TV
val localDownloadTitleTv: TextView?
// 本地下载的外层包裹 View
val localDownloadContainer: View?
// 额外的文字 (用于一些含图片的情况)
val overlayTv: TextView?
var downloadPb: DownloadButton
var downloadTips: LottieAnimationView
// 多版本下载文字
var multiVersionDownloadTv: TextView?
// 注意 View 的命名
init {
downloadBottom = view.findViewById(R.id.detail_ll_bottom)
downloadPb = view.findViewById(R.id.detail_progressbar)
downloadTips = view.findViewById(R.id.downloadTipsLottie)
overlayTv = view.findViewById(R.id.overlayTv)
multiVersionDownloadTv = view.findViewById(R.id.multiVersionDownloadTv)
localDownloadContainer = view.findViewById(R.id.localDownloadContainer)
localDownloadSizeTv = view.findViewById(R.id.localDownloadSizeTv)
localDownloadTitleTv = view.findViewById(R.id.localDownloadTitleTv)
localDownloadButton = view.findViewById(R.id.localDownloadButton)
context = view.context
var gameDownloadMode = gameEntity.getGameDownloadButtonMode()
val localDownloadListener = OnDetailDownloadClickListener(
mViewHolder = this,
mEntrance = entrance,
mName = name,
mTitle = title ?: "",
mAsVGame = false,
mShowDualDownloadButton = gameDownloadMode == GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DUAL,
mTraceEvent = traceEvent
)
val vGameDownloadListener = OnDetailDownloadClickListener(
mViewHolder = this,
mEntrance = entrance,
mName = name,
mTitle = title ?: "",
mAsVGame = true,
mShowDualDownloadButton = gameDownloadMode == GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DUAL,
mTraceEvent = traceEvent
)
// 不支持双下载按钮的情况时,优选一个下载方式显示
if (!isSupportDualButton) {
val performAsVGame = GameUtils.shouldPerformAsVGame(gameEntity)
gameDownloadMode = if (performAsVGame) {
GameEntity.GAME_DOWNLOAD_BUTTON_MODE_VGAME
} else {
GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DOWNLOAD
}
}
when (gameDownloadMode) {
GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DOWNLOAD -> {
// 仅显示下载按钮
downloadPb.setOnClickListener(localDownloadListener)
localDownloadButton?.setOnClickListener(null)
}
GameEntity.GAME_DOWNLOAD_BUTTON_MODE_VGAME -> {
// 仅显示畅玩按钮
downloadPb.setOnClickListener(vGameDownloadListener)
localDownloadButton?.setOnClickListener(null)
}
GameEntity.GAME_DOWNLOAD_BUTTON_MODE_DUAL -> {
// 显示双按钮
downloadPb.setOnClickListener(vGameDownloadListener)
localDownloadButton?.setOnClickListener(localDownloadListener)
localDownloadButton?.putObject(gameEntity)
localDownloadButton?.setTag(R.string.download, context.getString(R.string.download_local))
}
}
downloadPb.putWidgetBusinessName("游戏详情页")
downloadPb.putObject(gameEntity)
restoreDialogFragment()
}
private fun restoreDialogFragment() {
val gamePermissionDialogFragment = (context as AppCompatActivity).supportFragmentManager.findFragmentByTag(
GamePermissionDialogFragment::class.java.name
) as DialogFragment?
gamePermissionDialogFragment?.dismissAllowingStateLoss()
}
internal class OnDetailDownloadClickListener(
private val mViewHolder: DetailViewHolder,
private val mEntrance: String?,
private val mName: String,
private val mTitle: String,
private val mAsVGame: Boolean,
private val mShowDualDownloadButton: Boolean,
private val mTraceEvent: ExposureEvent?
) : View.OnClickListener {
private val mGameEntity: GameEntity = mViewHolder.gameEntity
private var mDownloadEntity: DownloadEntity? = null
override fun onClick(v: View) {
v.tag = null
val downloadButton: DownloadButton = if (mAsVGame) {
mViewHolder.downloadPb
} else if (mShowDualDownloadButton) {
mViewHolder.localDownloadButton ?: mViewHolder.downloadPb
} else {
mViewHolder.downloadPb
}
if (downloadButton.buttonStyle !== ButtonStyle.INSTALL_NORMAL && downloadButton.buttonStyle !== ButtonStyle.INSTALL_PLUGIN && downloadButton.buttonStyle !== ButtonStyle.LAUNCH_OR_OPEN && downloadButton.buttonStyle !== ButtonStyle.NONE && downloadButton.buttonStyle !== ButtonStyle.NONE_WITH_HINT) {
// 畅玩游戏的非真实点击下载按钮下载不需要滚动到特定地方
if (!mAsVGame || VHelper.shouldLaunchGameAfterInstallation()) {
EventBus.getDefault().post(EBScroll(Constants.EB_GAME_DETAIL, mGameEntity.id))
}
}
if (mDownloadEntity == null) {
mDownloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
}
if (mDownloadEntity != null) {
val xapkStatus = mDownloadEntity!!.meta[XapkInstaller.XAPK_UNZIP_STATUS]
// 安装过程中避免重复点击
if (XapkUnzipStatus.SUCCESS.name == xapkStatus && XapkInstaller.isInstalling(mDownloadEntity!!.path)) {
return
}
if (XapkUnzipStatus.UNZIPPING.name == xapkStatus) {
XapkInstaller.cancelUnzipTask(mDownloadEntity!!)
return
} else if (XapkUnzipStatus.FAILURE.name == xapkStatus) {
PermissionHelper.checkStoragePermissionBeforeAction(
context = mViewHolder.context,
gameId = mGameEntity.id,
gameName = (if (mGameEntity.name != null) mGameEntity.name else "")!!,
gameType = mGameEntity.categoryChinese,
gameFormat = mGameEntity.getApk().firstOrNull()?.format
) {
if (mDownloadEntity != null) {
val path = mDownloadEntity!!.path
if (FileUtils.isEmptyFile(path)) {
ToastUtils.toast(mViewHolder.context.getString(R.string.install_failure_hint))
DownloadManager.getInstance().cancel(mDownloadEntity!!.url)
} else {
NewFlatLogUtils.logGameInstall(
mGameEntity.id,
mGameEntity.name ?: "",
"主动安装"
)
SensorsBridge.trackInstallGameClick(
mGameEntity.id,
mGameEntity.name ?: "",
"主动安装"
)
PackageInstaller.install(mViewHolder.context, mDownloadEntity)
}
}
}
return
}
}
when (downloadButton.buttonStyle) {
ButtonStyle.NONE_WITH_HINT, ButtonStyle.NONE -> {
val offStatus = mGameEntity.downloadOffStatus
if (offStatus != null && "off" != offStatus) {
if ("dialog" == offStatus) {
showOffServiceDialog(mGameEntity.downloadOffDialog)
} else if ("toast" == offStatus) {
EventBus.getDefault().post(EBReuse(GameDetailFragment.SKIP_RATING))
ToastUtils.toast("该游戏因故暂不提供下载,具体详情可在相关评论中查看,敬请谅解~")
}
} else {
ToastUtils.toast("该游戏已关闭下载")
}
}
ButtonStyle.NORMAL -> {
val gameH5Download = RegionSettingHelper.getGameH5DownloadByGameId(mGameEntity.id)
if (gameH5Download != null) {
DialogUtils.showGameH5DownloadDialog(mViewHolder.context, mGameEntity, gameH5Download)
return
} else {
DataLogUtils.uploadGameLog(mViewHolder.context, mGameEntity.id, mGameEntity.name, mEntrance)
}
preDownload()
}
ButtonStyle.PLUGIN -> {
preDownload()
}
ButtonStyle.LAUNCH_OR_OPEN -> if (mGameEntity.getApk().size == 1) {
//启动模拟器游戏
if (SimulatorGameManager.isSimulatorGame(mGameEntity)) {
if (NewSimulatorGameManager.shouldShowUpdateNewSimulatorAlert(mViewHolder.context)) {
NewSimulatorGameManager.showUpdateNewsSimulator(mViewHolder.context, mGameEntity, null)
return
}
val downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(mGameEntity.getApk()[0].url)
if (downloadEntity != null) {
val file = File(downloadEntity.path)
if (!file.exists()) {
download(asVGame = false, isSubscribe = false)
return
}
SimulatorGameManager.launchSimulatorGame(downloadEntity, mGameEntity)
}
return
}
if (mAsVGame) {
VHelper.installOrLaunch(mViewHolder.context, mGameEntity, null)
} else {
PackageLauncher.launchApp(mViewHolder.context, mGameEntity, mGameEntity.getUniquePackageName())
}
} else {
GamePermissionDialogFragment.show(
activity = (mViewHolder.context as AppCompatActivity),
game = mGameEntity,
gameInfo = mGameEntity.info
) {
PermissionHelper.checkStoragePermissionBeforeAction(
context = mViewHolder.context,
gameId = mGameEntity.id,
gameName = mGameEntity.name ?: "",
gameType = mGameEntity.categoryChinese,
gameFormat = mGameEntity.getApk().firstOrNull()?.format
) {
DownloadDialog.showDownloadDialog(
context = mViewHolder.context,
gameEntity = mGameEntity,
traceEvent = mTraceEvent,
entrance = StringUtils.buildString(mEntrance, "+(", mName, "[", mTitle, "])"),
location = "$mName:$mTitle"
)
}
}
}
ButtonStyle.INSTALL_PLUGIN, ButtonStyle.INSTALL_NORMAL -> {
if (mGameEntity.getApk().isEmpty()) return
NewFlatLogUtils.logGameInstall(
gameId = mGameEntity.id,
gameName = mGameEntity.name ?: "",
trigger = "主动安装"
)
SensorsBridge.trackInstallGameClick(
gameId = mGameEntity.id,
gameName = mGameEntity.name ?: "",
action = "主动安装"
)
val (_, _, _, url) = mGameEntity.getApk()[0]
val downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(url)
if (mGameEntity.simulator != null) {
val isInstalled = PackageUtils.isInstalledFromAllPackage(
mViewHolder.context,
mGameEntity.simulator!!.apk!!.packageName
)
val isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(mViewHolder.context)
val isInstalledOldSimulator = SimulatorGameManager.isOldSimulatorInstalled(mViewHolder.context)
var simulator = mGameEntity.simulator
val newSimulator = Config.getNewSimulatorEntitySetting()
if (!isInstalledOldSimulator && newSimulator != null && newSimulator.active) {
simulator = newSimulator
}
if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(mGameEntity) && !isInstalled && !isInstalledNewSimulator) {
SimulatorDownloadManager.getInstance().showDownloadDialog(
context = mViewHolder.context,
simulator = simulator,
location = SimulatorDownloadManager.SimulatorLocation.LAUNCH,
gameId = mGameEntity.id,
gameName = mGameEntity.name!!,
gameCategoryChinese = mGameEntity.categoryChinese,
cancelCallback = null
)
return
}
}
if (mAsVGame) {
VHelper.installOrLaunch(v.context, mGameEntity, null)
return
}
PermissionHelper.checkStoragePermissionBeforeAction(
context = mViewHolder.context,
gameId = mGameEntity.id,
gameName = (if (mGameEntity.name != null) mGameEntity.name else "")!!,
gameType = mGameEntity.categoryChinese,
gameFormat = mGameEntity.getApk().firstOrNull()?.format
) {
if (mDownloadEntity == null) {
mDownloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
}
if (mDownloadEntity != null) {
val path = mDownloadEntity!!.path
if (FileUtils.isEmptyFile(path)) {
ToastUtils.toast(mViewHolder.context.getString(R.string.install_failure_hint))
DownloadManager.getInstance().cancel(mDownloadEntity!!.url)
} else {
PackageInstaller.install(
context = mViewHolder.context,
downloadEntity = mDownloadEntity!!,
showUnzipToast = false,
ignoreAsVGame = true
)
}
}
}
}
ButtonStyle.RESERVABLE -> {
GamePermissionDialogFragment.show(
activity = (mViewHolder.context as AppCompatActivity),
game = mGameEntity,
gameInfo = mGameEntity.info
) {
SensorsBridge.trackEvent(
"AppointmentGame",
"game_name",
mGameEntity.name!!,
"game_id",
mGameEntity.id
)
CheckLoginUtils.checkLogin(mViewHolder.context, mEntrance) {
ReservationHelper.reserve(mViewHolder.context, mGameEntity.id, mGameEntity.name!!) {
LogUtils.logReservation(mGameEntity, mTraceEvent)
DetailDownloadUtils.updateViewHolder(mViewHolder)
}
}
}
}
ButtonStyle.RESERVED -> {
if ("download" == mGameEntity.reserveStatus) {
ReservationHelper.showDeleteReservationDialog(mViewHolder.context) {
ReservationHelper.deleteReservation(mGameEntity) {
DetailDownloadUtils.updateViewHolder(mViewHolder)
}
}
} else {
ReservationHelper.showCancelReservationDialog(mViewHolder.context) {
ReservationHelper.cancelReservation(mGameEntity) {
DetailDownloadUtils.updateViewHolder(mViewHolder)
}
}
}
}
ButtonStyle.H5_GAME -> {
val linkEntity = mGameEntity.h5Link
val isPlay = "play" == linkEntity!!.type // 是否为开始玩
if (isPlay) {
HistoryHelper.insertGameEntity(mGameEntity)
}
GamePermissionDialogFragment.show(
(mViewHolder.context as AppCompatActivity), mGameEntity, mGameEntity.info
) {
val i = Intent(
WebActivity.getIntentForWebGame(
mViewHolder.context,
linkEntity.link,
mGameEntity.name,
isPlay,
linkEntity.closeButton
)
)
mViewHolder.context.startActivity(i)
}
}
ButtonStyle.UPDATING -> ToastUtils.toast("正在加急更新版本,敬请后续留意")
ButtonStyle.TEENAGER_MODE -> {
SensorsBridge.trackAdolescentModeDialogShow(
mGameEntity.id,
(if (mGameEntity.name != null) mGameEntity.name else "")!!,
mGameEntity.categoryChinese
)
DialogHelper.showCenterDialog(
context = mViewHolder.context,
title = "提示",
content = "当前处于儿童/青少年模式, \n暂不提供游戏下载",
positiveText = "退出青少年模式",
negativeText = "关闭",
positiveClickCallback = {
mViewHolder.context.startActivity(getIntent(mViewHolder.context))
SensorsBridge.trackAdolescentModeDialogClick(
"退出青少年模式",
mGameEntity.id,
(if (mGameEntity.name != null) mGameEntity.name else "")!!,
mGameEntity.categoryChinese
)
},
negativeClickCallback = {
SensorsBridge.trackAdolescentModeDialogClick(
"关闭弹窗",
mGameEntity.id,
(if (mGameEntity.name != null) mGameEntity.name else "")!!,
mGameEntity.categoryChinese
)
}
) {
SensorsBridge.trackAdolescentModeDialogClick(
"关闭",
mGameEntity.id,
(if (mGameEntity.name != null) mGameEntity.name else "")!!,
mGameEntity.categoryChinese
)
}
}
ButtonStyle.SPECIAL_DOWNLOAD -> {
val info = RegionSettingHelper.getGameSpecialDownloadInfo(mGameEntity.id)
if (info != null && !TextUtils.isEmpty(info.bbsId)) {
if (!TextUtils.isEmpty(info.topId)) {
val map = HashMap<String, String>()
map[EntranceConsts.KEY_TOP_ID] = info.topId
PageSwitchDataHelper.pushCurrentPageData(map)
}
DirectUtils.directForumDetail(mViewHolder.context, info.bbsId, mEntrance)
}
}
ButtonStyle.WAITING -> ToastUtils.toast("最多只能同时下载三个任务,请稍等")
ButtonStyle.DOWNLOADING_NORMAL, ButtonStyle.DOWNLOADING_PLUGIN -> {
if (mDownloadEntity == null) {
mDownloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
}
if (mDownloadEntity != null) {
if (downloadButton.text.contains("继续加载")) {
DownloadManager.getInstance().resume(mDownloadEntity, true)
} else {
DownloadManager.getInstance().pause(mDownloadEntity!!.url)
downloadButton.text = "继续加载 " + mDownloadEntity!!.percent + "%"
}
}
}
else -> if (mGameEntity.getApk().isNotEmpty()) {
val intent = DownloadManagerActivity.getDownloadMangerIntent(
mViewHolder.context,
mGameEntity.getApk()[0].url,
StringUtils.buildString(mEntrance, "+(", mName, "[", mTitle, "])")
)
mViewHolder.context.startActivity(intent)
}
}
}
private fun showOffServiceDialog(dialog: GameEntity.Dialog?) {
val dialogFragment = GameOffServiceDialogFragment.getInstance(dialog!!)
dialogFragment.show((mViewHolder.context as FragmentActivity).supportFragmentManager, "off_service_dialog")
}
private fun download(asVGame: Boolean, isSubscribe: Boolean) {
var buttonText = mViewHolder.downloadPb.text
if (buttonText.isEmpty()) buttonText = mViewHolder.overlayTv?.text.toString()
if (mGameEntity.getApk().size == 0) {
ToastUtils.toast("暂时无法下载,请稍后再试")
return
}
val apkEntity = mGameEntity.getApk()[0]
val msg = FileUtils.isCanDownload(mViewHolder.context, apkEntity.size)
if (TextUtils.isEmpty(msg)) {
if (asVGame && mViewHolder.context.getString(R.string.update_v) == buttonText) {
VHelper.updateOrReDownload(mGameEntity)
} else {
DownloadManager.createDownload(
mViewHolder.context,
apkEntity,
mGameEntity,
asVGame,
mGameEntity.isDualBtnModeEnabled(),
StringUtils.buildString(mEntrance, "+(", mName, "[", mTitle, "])"),
"$mName:$mTitle",
isSubscribe,
mTraceEvent
)
}
mViewHolder.downloadPb.progress = 0
mViewHolder.downloadPb.buttonStyle =
if (buttonText.contains("插件化")) ButtonStyle.DOWNLOADING_PLUGIN else ButtonStyle.DOWNLOADING_NORMAL
DeviceRemindDialog.showDeviceRemindDialog(mViewHolder.context, mGameEntity)
} else {
ToastUtils.toast(msg)
}
}
private fun preDownload() {
val builder = DownloadChainBuilder()
builder.addHandler(UnsupportedFeatureHandler())
builder.addHandler(UpdateNewSimulatorHandler())
builder.addHandler(GamePermissionHandler())
builder.addHandler(CheckStoragePermissionHandler())
builder.addHandler(ValidateVSpaceHandler())
if (mGameEntity.getApk().size == 1) {
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
// 双按钮下载,且是以另外一种状态进行下载完成的,那么更新它的下载触发源并直接唤起安装
if (mShowDualDownloadButton
&& downloadEntity != null
&& downloadEntity.status == DownloadStatus.done
&& !FileUtils.isEmptyFile(downloadEntity.path)) {
if (downloadEntity.getMetaExtra(Constants.APK_MD5) != mGameEntity.getApk().firstOrNull()?.md5) {
// 已下载的 md5 与接口返回的不一样,不使用快速安装功能,重新下载安装
DownloadManager.getInstance().cancel(downloadEntity.url)
} else if (mAsVGame && downloadEntity.isLocalDownloadInDualDownloadMode()) {
runOnIoThread {
// 由于不想执行上面的 builder 相关的判断,所以这里还是丑陋的修改 downloadEntity 实体并保存到数据库中
downloadEntity.setVGameDownloadModeInDualDownloadMode()
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
PackageInstaller.install(mViewHolder.context, downloadEntity)
}
return
} else if (!mAsVGame && downloadEntity.isVGameDownloadInDualDownloadMode()) {
runOnIoThread {
downloadEntity.setLocalDownloadModeInDualDownloadMode()
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
PackageInstaller.install(mViewHolder.context, downloadEntity)
}
return
}
}
builder.addHandler(BrowserInstallHandler())
builder.addHandler(PackageCheckHandler())
builder.addHandler(DownloadDialogHelperHandler())
builder.addHandler(CertificationHandler())
builder.addHandler(VersionNumberHandler())
builder.addHandler(LandPageAddressHandler())
builder.addHandler(OverseaDownloadHandler())
builder.addHandler(CheckDownloadHandler())
builder.setProcessEndCallback { asVGame: Boolean, isSubscribe: Any? ->
download(asVGame, isSubscribe as Boolean)
}
} else {
builder.addHandler(CertificationHandler())
builder.addHandler(VersionNumberHandler())
builder.setProcessEndCallback { _: Boolean?, _: Any? ->
DownloadDialog.showDownloadDialog(
mViewHolder.context,
mGameEntity,
mTraceEvent,
StringUtils.buildString(
mEntrance,
"+(",
mName,
"[",
mTitle,
"])"
),
"$mName:$mTitle"
)
}
}
val chainHandler = builder.buildHandlerChain()
chainHandler?.handleRequest(
mViewHolder.context,
mGameEntity,
mAsVGame
)
}
}
}

View File

@ -2,11 +2,11 @@ package com.gh.gamecenter.adapter.viewholder
import android.view.View
import android.view.ViewGroup
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.databinding.GameHeadItemBinding
import com.gh.gamecenter.entity.SubjectEntity
@ -31,12 +31,11 @@ class GameHeadViewHolder(var binding: GameHeadItemBinding) :
binding.arrowIv.visibility = View.GONE
val text = if ("change" == subject.home) {
"换一批"
} else if (subject.type == "game_list_collection" && subject.style?.contains("slide") == true) {
"游戏单广场"
} else {
when (subject.home) {
"more" -> "更多"
"hide" -> ""
"game_list_square" -> "游戏单广场"
else -> "全部"
}
}

View File

@ -5,6 +5,7 @@ import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.RecyclerView
@ -36,7 +37,6 @@ import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.fragment.HomeSearchToolWrapperFragment
import com.gh.gamecenter.gamedetail.rating.RatingFragment
import com.google.android.material.appbar.AppBarLayout
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import org.greenrobot.eventbus.Subscribe
@ -54,6 +54,7 @@ class AmwayFragment : LazyListFragment<AmwayListItemData, AmwayViewModel>() {
private var mAdapter: AmwayAdapter? = null
private var mIsFromMainWrapper = false
private var mUseAlternativeLayout = false
private var mIsCollapsed = false
@ -73,6 +74,7 @@ class AmwayFragment : LazyListFragment<AmwayListItemData, AmwayViewModel>() {
override fun onCreate(savedInstanceState: Bundle?) {
mUseAlternativeLayout = arguments?.getBoolean(EntranceConsts.KEY_IS_HOME, false) ?: false
mIsFromMainWrapper = arguments?.getBoolean(EntranceConsts.KEY_IS_FROM_MAIN_WRAPPER, false) ?: false
super.onCreate(savedInstanceState)
}
@ -103,7 +105,7 @@ class AmwayFragment : LazyListFragment<AmwayListItemData, AmwayViewModel>() {
super.initRealView()
mExposureListener = ExposureListener(this, mAdapter!!)
mListRv.addOnScrollListener(mExposureListener)
mListRv?.addOnScrollListener(mExposureListener)
if (!mUseAlternativeLayout) {
initDefaultLayout()
@ -175,11 +177,14 @@ class AmwayFragment : LazyListFragment<AmwayListItemData, AmwayViewModel>() {
if (it) {
titleTv.alpha = 1F
titleTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_black))
toolbar.setNavigationIcon(R.drawable.ic_bar_back)
} else {
titleTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.white))
toolbar.navigationIcon =
ContextCompat.getDrawable(requireContext(), R.drawable.ic_toolbar_back_white)
}
if (mIsFromMainWrapper) {
toolbar.navigationIcon = null
} else {
toolbar.setNavigationIcon(if (it) R.drawable.ic_bar_back else R.drawable.ic_toolbar_back_white)
}
}
@ -189,19 +194,24 @@ class AmwayFragment : LazyListFragment<AmwayListItemData, AmwayViewModel>() {
}
}
appbar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { _, verticalOffset ->
appbar.addOnOffsetChangedListener { _, verticalOffset ->
val absOffset = abs(verticalOffset)
val invisibleOffset = DisplayUtils.dip2px(30F)
if (absOffset <= invisibleOffset) {
titleTv.alpha = 1 - (absOffset.toFloat() / invisibleOffset)
} else {
} else if (!mIsCollapsed) {
titleTv.alpha = 0F
}
mListRefresh?.isEnabled = absOffset <= 2
})
}
if (mIsFromMainWrapper) {
fab.layoutParams = (fab.layoutParams as MarginLayoutParams).apply {
setMargins(0, 0, 14F.dip2px(), 72F.dip2px())
}
}
fab.setOnClickListener {
MtaHelper.onEvent("发表评论", "进入", "上墙")
ifLogin("安利墙") {
@ -263,14 +273,18 @@ class AmwayFragment : LazyListFragment<AmwayListItemData, AmwayViewModel>() {
mElapsedHelper.resetCounting()
mElapsedHelper.resumeCounting()
if (mIsFromMainWrapper) {
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn && mIsCollapsed)
}
}
private fun scrollToTop() {
val firstItemPosition = mLayoutManager.findFirstVisibleItemPosition()
if (firstItemPosition >= 10) {
mListRv.scrollToPosition(6)
mListRv?.scrollToPosition(6)
}
mListRv.smoothScrollToPosition(0)
mListRv?.smoothScrollToPosition(0)
mDefaultBinding?.appbar?.setExpanded(true)
}
@ -348,5 +362,8 @@ class AmwayFragment : LazyListFragment<AmwayListItemData, AmwayViewModel>() {
mDefaultBinding?.collapsingToolbar?.setContentScrimColor(R.color.background_white.toColor(requireContext()))
mDefaultBinding?.listRefresh?.setBackgroundColor(R.color.background.toColor(requireContext()))
}
if (mIsFromMainWrapper) {
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn && mIsCollapsed)
}
}
}

View File

@ -66,6 +66,7 @@ class AmwaySearchActivity : SearchActivity() {
?: AmwaySearchDefaultFragment()
transaction.replace(R.id.search_result, fragment, SearchDefaultFragment::class.java.name)
}
else -> {
val fragment = supportFragmentManager.findFragmentByTag(AmwaySearchListFragment::class.java.name)
?: AmwaySearchListFragment()
@ -76,6 +77,9 @@ class AmwaySearchActivity : SearchActivity() {
transaction.commitAllowingStateLoss()
}
// 安利墙搜索页不需要神策埋点
override fun trackSearchPageShow() = Unit
companion object {
fun getIntent(context: Context): Intent {
val intent = Intent(context, AmwaySearchActivity::class.java)

View File

@ -193,7 +193,7 @@ class AuthorizationActivity : ToolBarActivity() {
val userAvatar = UserManager.getInstance().userInfoEntity?.icon
//授权成功,发送广播, 返回token
val intent = Intent()
intent.setClassName(remotePkgName, "$remotePkgName.AuthorizationReceiver")
intent.setClassName(remotePkgName, "com.va.host.receiver.AuthorizationReceiver")
intent.setPackage(remotePkgName)
intent.putExtra(EntranceConsts.KEY_TOKEN, token)
intent.putExtra(EntranceConsts.KEY_USER_ID, userId)

View File

@ -145,7 +145,7 @@ class NewCatalogListAdapter(
event
)
DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding), true, "star&brief")
DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding), "star&brief")
} else if (holder is FooterViewHolder) {
holder.initItemPadding()
holder.initFooterViewHolder(mViewModel, mIsLoading, mIsNetworkError, mIsOver)

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