Compare commits

...

117 Commits

Author SHA1 Message Date
7519612347 refactor: 更新maven拉取顺序 2023-12-19 14:16:05 +08:00
5966d4ab0d refactor: 更新apk文件路径 2023-12-19 11:47:11 +08:00
1f264cdced refactor: 下载插件到assets目录 2023-12-19 11:33:10 +08:00
c5af23caab refactor: 更新打包脚本 2023-12-19 11:29:44 +08:00
e7a46a03f7 refactor: update vasdk commit id. 2023-12-19 11:28:08 +08:00
8f7df48d4c feat: 展示64位va插件版本信息 https://jira.shanqu.cc/browse/GHZS-3885 2023-12-13 19:18:53 +08:00
32a0b64572 refactor: update vasdk commit id. 2023-12-13 15:14:10 +08:00
7578c109d6 fix: 过滤va项目的配置&修复错误的assets添加脚步 2023-12-13 15:13:44 +08:00
943c938af7 feat: 光环助手va组件兼容旧版畅玩助手游戏业务 2023-12-12 19:32:13 +08:00
490b4055da refactor: update vasdk commmit id 2023-12-04 10:27:59 +08:00
0203566bbc feat: 接入vasdk编译通过 2023-12-02 16:38:38 +08:00
7f38cdfb01 refactor: va模块引用 2023-12-02 15:53:38 +08:00
8f8feddb5c Merge branch 'release' into feat/CWZS-113 2023-12-02 14:04:08 +08:00
b5e1bf9124 feat: 加速器模块占用空间太大,给ci/cd集成增加时间成本,考虑到加速器变更频繁度较低,改为maven引用 2023-12-02 13:58:37 +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
811fb33ac3 feat: 同步vasdk的代码 2023-10-19 15:15:47 +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
bf2c359e95 feat: 接入va模块 2023-10-17 18:03:14 +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
476 changed files with 15123 additions and 4554 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"]
}
@ -188,7 +191,8 @@ android {
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 +204,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 +216,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 +230,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 +242,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 +328,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 +367,13 @@ 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")
}
File propFile = file('sign.properties')
@ -600,4 +615,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" />
<!-- 去掉 SDK 一些流氓权限 -->
<uses-permission
@ -474,6 +499,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 +787,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 +805,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" />

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,9 +4,9 @@ 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,
@ -14,9 +14,9 @@ class CheckStoragePermissionHandler : ChainHandler() {
gameEntity.categoryChinese
) {
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

@ -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

@ -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

@ -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
@ -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)) {
@ -836,17 +899,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 +933,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 +949,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 +969,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 +989,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 +1048,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 +1060,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 +1078,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 +1097,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 +1144,7 @@ object DownloadItemUtils {
downloadBtn: View?,
entrance: String,
location: String,
asVGame: Boolean,
isSubscribe: Boolean,
traceEvent: ExposureEvent?
) {
@ -1088,7 +1155,7 @@ object DownloadItemUtils {
DownloadManager.createDownload(
context,
gameEntity,
context.getString(R.string.download),
asVGame,
entrance,
location,
isSubscribe,
@ -1123,7 +1190,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 +1254,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,
@ -481,7 +478,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,10 +15,7 @@ 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
@ -37,7 +34,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 +43,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
}

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;
@ -516,7 +518,9 @@ 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);
@ -562,7 +566,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 +579,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 +728,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 +750,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;
};
}
/**
* 应用跳转
*/
@ -985,7 +1004,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

@ -65,9 +65,17 @@ class SplashScreenActivity : BaseActivity() {
private var mViewModel: SplashScreenViewModel? = null
private var mShouldPrefetchData = true
private val mPermissions = arrayOf(
PermissionHelper.PERMISSION_GET_INSTALLED_LIST
)
private val mPermissions by lazy {
if (isStoragePermissionsRequired) {
arrayOf(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
PermissionHelper.PERMISSION_GET_INSTALLED_LIST
)
} else {
arrayOf(PermissionHelper.PERMISSION_GET_INSTALLED_LIST)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
mViewModel = viewModelProvider()
@ -282,9 +290,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)
}
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
}
private fun getGitLogString(): String {
@ -489,6 +495,11 @@ class SplashScreenActivity : BaseActivity() {
companion object {
private const val REQUEST_PERMISSION_TAG = 30001
// 启动时的存储权限获取是否开启
val isStoragePermissionsRequired by lazy {
HaloApp.getInstance().channel != "GH_206" && HaloApp.getInstance().channel != "GH_110"
}
@JvmStatic
fun getSplashScreenIntent(context: Context?, bundle: Bundle?): Intent {
val intent = Intent(context, SplashScreenActivity::class.java)

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,79 @@
package com.gh.gamecenter.adapter
import android.util.SparseIntArray
import androidx.core.util.forEach
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
/***
* 支持替换Fragment的FragmentPagerAdapter
*/
class MainFragmentPagerAdapter(
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()
}

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,644 @@
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(
mViewHolder.context,
mGameEntity.id,
(if (mGameEntity.name != null) mGameEntity.name else "")!!,
mGameEntity.categoryChinese
) {
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
) {
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
) {
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)

View File

@ -51,16 +51,16 @@ class CategoryDirectoryFragment : LazyListFragment<CategoryEntity, CategoryDirec
onLoadRefresh()
if (arguments?.getBoolean(EntranceConsts.KEY_IS_HOME) == true) {
mListRv.setPadding(
mListRv?.setPadding(
0,
context?.resources?.getDimension(R.dimen.home_recyclerview_padding_top)?.toInt() ?: 0,
0,
0
)
mListRv.clipToPadding = false
mListRv?.clipToPadding = false
}
mListRv.setBackgroundColor(R.color.background_white.toColor(requireContext()))
mListRv?.setBackgroundColor(R.color.background_white.toColor(requireContext()))
mAdapter.recyclerView = mListRv
mListRefresh?.isEnabled = false
}
@ -95,9 +95,9 @@ class CategoryDirectoryFragment : LazyListFragment<CategoryEntity, CategoryDirec
override fun onDarkModeChanged() {
super.onDarkModeChanged()
mListRv.setBackgroundColor(R.color.background_white.toColor(requireContext()))
mListRv.adapter?.run {
mListRv.recycledViewPool.clear()
mListRv?.setBackgroundColor(R.color.background_white.toColor(requireContext()))
mListRv?.adapter?.run {
mListRv?.recycledViewPool?.clear()
notifyItemRangeChanged(0, itemCount)
}
}

View File

@ -143,7 +143,7 @@ class NewCategoryListAdapter(
event
)
DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding), true)
DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding))
} else if (holder is FooterViewHolder) {
holder.initItemPadding()
holder.initFooterViewHolder(mViewModel, mIsLoading, mIsNetworkError, mIsOver)

View File

@ -190,7 +190,6 @@ class CategoryV2ListAdapter(
mContext,
gameEntity,
CategoryGameViewHolder(holder.binding),
true,
"star&brief"
)
@ -242,8 +241,8 @@ class CategoryV2ListAdapter(
fun bindGameItem(gameEntity: GameEntity) {
binding.run {
gameIconView.displayGameIcon(gameEntity)
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
BindingAdapters.setGameName(gameName, gameEntity, false, null)
BindingAdapters.setTextSize(gameRating, if (gameEntity.commentCount > 3) 12 else 10)
BindingAdapters.setGameTags(labelList, gameEntity)
gameRating.setDrawableStart(if (gameEntity.commentCount > 3) R.drawable.game_horizontal_rating.toDrawable() else null)
gameRating.text = if (gameEntity.commentCount > 3) {

View File

@ -0,0 +1,84 @@
package com.gh.gamecenter.cloudarchive
import android.content.Context
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.R
import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.utils.toBinding
import com.gh.gamecenter.databinding.ItemArchiveLimitBinding
import com.gh.gamecenter.entity.ArchiveEntity
import java.text.SimpleDateFormat
import java.util.*
class ArchiveLimitAdapter(context: Context) : ListAdapter<ArchiveLimitAdapter.ArchiveItem>(context) {
private var currentSelectedPosition = 0
public override fun setListData(updateData: MutableList<ArchiveItem>?) {
// 默认定一个为选中状态
updateData?.firstOrNull()?.isChecked = true
super.setListData(updateData)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return ArchiveLimitViewHolder(parent.toBinding())
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is ArchiveLimitViewHolder) {
val item = mEntityList[position]
holder.binding.tvTitle.text = item.data.name
val timeLong = item.data.time.create
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA)
val date = Date(timeLong)
holder.binding.tvTime.text = sdf.format(date)
val resId = if (item.isChecked) R.drawable.ic_selector_selected else R.drawable.ic_selector_default
holder.binding.ivSelector.setImageResource(resId)
holder.itemView.setOnClickListener {
if (currentSelectedPosition == holder.bindingAdapterPosition) return@setOnClickListener
// 重置上一次选中状态
mEntityList[currentSelectedPosition].isChecked = false
notifyItemChanged(currentSelectedPosition, PAYLOAD_SELECTED_CHANGED)
// 设置新的选中状态
currentSelectedPosition = holder.bindingAdapterPosition
item.isChecked = true
notifyItemChanged(currentSelectedPosition, PAYLOAD_SELECTED_CHANGED)
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: MutableList<Any?>) {
if(holder is ArchiveLimitViewHolder){
if(payloads.isEmpty()){
onBindViewHolder(holder, position)
}else{
val item = mEntityList[position]
val resId = if (item.isChecked) R.drawable.ic_selector_selected else R.drawable.ic_selector_default
holder.binding.ivSelector.setImageResource(resId)
}
}
}
override fun getItemCount(): Int = mEntityList.size
fun getSelectedArchiveId() = mEntityList[currentSelectedPosition].data.id
companion object {
private const val PAYLOAD_SELECTED_CHANGED = "payload_selected_changed"
}
data class ArchiveItem(
val data: ArchiveEntity,
var isChecked: Boolean = false
)
private class ArchiveLimitViewHolder(
val binding: ItemArchiveLimitBinding
) : RecyclerView.ViewHolder(binding.root)
}

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