Compare commits

...

445 Commits

Author SHA1 Message Date
1ce04241f6 tinker base 4.2.0-202 2020-09-09 11:31:50 +08:00
f29b8da6d0 Version code 增至202 2020-09-08 14:28:03 +08:00
de968a4820 调整上报激活数据的时机 2020-09-08 14:26:42 +08:00
ddddda10a5 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-09-07 16:56:33 +08:00
30d6dabe4f 1.处理个人主页闪退问题 2.处理论坛帖子点赞数据同步 2020-09-07 16:56:27 +08:00
7655cc25be 捕抓通知栏闪退 2020-09-07 16:26:37 +08:00
52824e5baa 捕抓帖子详情列表动画异常 2020-09-07 16:11:00 +08:00
014c80cd18 激活信息添加 OAID https://gitlab.ghzs.com/pm/yunying/-/issues/1252 2020-09-07 16:05:56 +08:00
99eddec84a tinker_base 4.2.0-201 2020-09-07 14:12:00 +08:00
6b382ab080 暂时还原游戏库加载逻辑 2020-09-07 11:18:21 +08:00
d492cfdace Version code 升级到 201 2020-09-07 11:08:32 +08:00
256f0af0e9 修复一些闪退问题 2020-09-07 11:05:39 +08:00
58d2290e12 tinker_base 4.2.0-200 2020-09-04 18:27:59 +08:00
547e6da027 临时处理帖子详情状态栏颜色问题 2020-09-04 18:09:29 +08:00
c3e34ba644 应用内拦截光环url补充 m.ghzs666.com 2020-09-04 16:51:23 +08:00
077e17c5aa 捕抓分享异常,调整回答评论字数上限 2020-09-04 14:51:27 +08:00
f264875b7d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-09-04 09:24:28 +08:00
351b8a331c 处理上传视频封面错误问题 2020-09-04 09:24:24 +08:00
479f7c464b 调整游戏详情分享链接 2020-09-03 17:25:48 +08:00
e04a7fc4b9 修复资讯评论闪退问题 2020-09-03 17:19:54 +08:00
595f7747f4 调整帖子详情的评论楼层显示 2020-09-03 16:54:59 +08:00
8c1343fdba 优化帖子详情UI显示 2020-09-03 16:23:19 +08:00
c3717869bd 版规声明跳转至资讯文章详情 2020-09-03 15:34:03 +08:00
1e56dc533d 修改文案 2020-09-03 11:41:30 +08:00
1444531830 视频活动兼容老版本 2020-09-03 11:24:45 +08:00
4e759e446b 处理论坛详情全部列表筛选错误 2020-09-02 18:38:55 +08:00
ef6c09d27b 优化帖子评论的滚动效果 2020-09-02 16:12:46 +08:00
efc241429c 优化 gif 加载尺寸避免频繁内存回收 2020-09-02 15:51:27 +08:00
07be540ba1 补充错误码 2020-09-02 15:49:53 +08:00
50479d2e87 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-09-02 15:35:01 +08:00
2934c9dc38 处理ScrollView会自动滚动到焦点位置问题 2020-09-02 15:34:56 +08:00
30a60797e6 修复专题头图的曝光上报问题 2020-09-02 14:23:43 +08:00
53562297d5 修复启动时重复获取镜像地区配置数据的问题 2020-09-02 14:13:55 +08:00
144ee3ea8c 修改视频评论UI 2020-09-02 09:49:56 +08:00
e0c8697e75 延迟加载游戏库 2020-09-01 18:27:06 +08:00
6aba2906f6 完成论坛测试汇总的17~19 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/989 2020-09-01 17:14:28 +08:00
7bb468a1b1 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-09-01 16:22:05 +08:00
871be728bf 光环助手V4.2.0-论坛与视频测试汇总(正式环境)(8-10,12-16) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/989 2020-09-01 16:22:01 +08:00
bbac0c8d93 修复帖子详情骨架图变形的问题 2020-09-01 15:04:40 +08:00
6b361ed077 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-09-01 11:39:29 +08:00
1cfa54f8e8 分片检测下载进度数据增加 host 字段 2020-09-01 11:39:13 +08:00
5bd028cbe9 更新正式环境接口 2020-09-01 09:00:04 +08:00
b8f8711ba4 修复专题列表无筛项时曝光上报缺失数据的问题 2020-08-31 18:43:06 +08:00
c1f899f0d5 去掉视频详情游戏名称的点后缀 2020-08-31 17:32:27 +08:00
e4fd74da7d 修复APP由自动更新切换为手动更新时的进度跳跃问题 2020-08-31 17:31:38 +08:00
bf9cc93daa 补充方法供网页弹起版本不支持弹窗 2020-08-31 16:01:11 +08:00
3b974268a9 修复视频合集游戏标题的显示问题 2020-08-31 11:56:10 +08:00
822853a4be 完成光环助手V4.2.0-数据统计需求(游戏专题) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/984 2020-08-31 11:49:47 +08:00
f699841427 论坛首页双击回到顶部显示发帖子图标 2020-08-31 10:59:59 +08:00
c700910b15 调整首页卡片分割线高度 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/820 2020-08-31 10:31:57 +08:00
3c8d0cb3ec 补充礼仪考试弹窗MTA统计 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/945 2020-08-31 10:26:16 +08:00
8492c762b5 Merge remote-tracking branch 'origin/dev' into dev 2020-08-31 09:40:46 +08:00
b2d70392bb 补充进入游戏详情触发自动下载游戏的参数 2020-08-31 09:40:30 +08:00
eb9cb08624 更换启动引导图 2020-08-31 09:16:07 +08:00
a4ca2628dc 增加分片检测下载进度数据 https://gitlab.ghzs.com/stats/stats-issues/-/issues/188#note_66919 2020-08-28 18:44:21 +08:00
727d78d0e5 去掉获取地理位置权限 2020-08-28 17:14:44 +08:00
693d8c4385 Merge remote-tracking branch 'origin/dev' into dev 2020-08-27 23:48:38 +08:00
d46e3fac2d 补充跳转首页论坛的urlScheme 2020-08-27 23:48:30 +08:00
7f0ec7f128 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-27 23:24:38 +08:00
73eb2f6ecb 修改视频上传标签UI 2020-08-27 23:24:34 +08:00
6bd7ced28c 修复帖子详情UI测试0827PM https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/967 2020-08-27 23:15:38 +08:00
086c31a7d4 修复礼包页面重复跳转会复用第一个页面数据的问题 2020-08-27 23:09:00 +08:00
3a839f6770 修改系统消息点赞文案 2020-08-27 23:05:28 +08:00
b67c7e2803 修改论坛首页引导UI间距 2020-08-27 22:58:43 +08:00
b7dbf30845 修改论坛详情UI 2020-08-27 22:49:19 +08:00
lyr
ec86970cbe 登录界面顶部栏适配小米型号手机 2020-08-27 21:41:11 +08:00
956755b985 Merge remote-tracking branch 'origin/dev' into dev 2020-08-27 20:47:36 +08:00
fe2779196d 修复详情页点击tab偶尔失效的问题 2020-08-27 20:47:29 +08:00
9eeeba93d0 Merge branches 'dev' and 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-27 20:46:03 +08:00
d7df019d6d 调整论坛帖子底部按钮 2020-08-27 20:45:58 +08:00
lyr
68bfc26ddc 如果当前登录方式为手机号,在更换绑定手机号后,同步更新登录方式的值为已更换的手机号 2020-08-27 20:33:20 +08:00
94a1cfe4b2 修复帖子点赞通知的跳转问题 2020-08-27 20:13:13 +08:00
936c3b00bb 修改论坛UI问题 2020-08-27 20:04:49 +08:00
b34229e4c4 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-27 19:53:11 +08:00
b51322b473 视频上传交互优化(第二期)(5,6) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/969 2020-08-27 19:53:04 +08:00
e0657ccdcc 优化帖子详情请求出错时的显示 2020-08-27 19:49:21 +08:00
4b67d8b5aa 微调帖子详情页UI 2020-08-27 17:50:46 +08:00
5b8cc49349 完成更新强退时清空下载通知的功能 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/946 2020-08-27 16:58:01 +08:00
612f71e18c 原始回复显示作者标签 2020-08-27 16:55:37 +08:00
6239ccb8ab 删除多余代码 2020-08-27 16:47:12 +08:00
9680bea412 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-27 16:40:13 +08:00
a21d9096c8 处理论坛点赞错误问题 2020-08-27 16:40:09 +08:00
e6f3ad5cc2 视频上传交互优化(第二期)20200827ui反馈 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/969 2020-08-27 16:39:35 +08:00
c41e996add 修复更新进度跳跃问题 2020-08-27 16:32:29 +08:00
58f230038c 完成更新强退时清空下载通知的功能 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/946 2020-08-27 16:27:05 +08:00
bda41d8a26 修复更新推送0827测试问题 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/946 2020-08-27 15:49:44 +08:00
e3f41543a4 完成帖子详情测试内容 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/967 2020-08-27 15:09:45 +08:00
lyr
78c4d7acef 1.修改"注册方式"判断逻辑;2.优化"账号与安全"模块UI 2020-08-27 14:51:41 +08:00
8c884b6d23 修复礼仪考试20200826测试问题2 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/945 2020-08-27 14:33:32 +08:00
a5f9af2df2 适配活动视频流接口 2020-08-27 14:30:33 +08:00
e2fd6dbf97 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-27 14:08:46 +08:00
e430b4e2de 视频上传交互优化(第二期)20200827测试(3) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/969 2020-08-27 14:08:42 +08:00
caa3f46c5c 初始下载不填加 range 请求头 2020-08-27 11:00:50 +08:00
b2beba4d36 论坛详情UI测试 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/956 2020-08-27 10:52:51 +08:00
3a9c7fc71d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-27 08:38:41 +08:00
a5f8275f64 修改论坛帖子列表底部按钮错位问题 2020-08-27 08:38:36 +08:00
8fa3f3d832 调整更新推送逻辑 2020-08-26 19:52:38 +08:00
97472b8259 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-26 18:53:04 +08:00
ee07889b30 光环助手V4.2.0-引导设置“通知管理”(第3期)20200825UI测试 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/947 2020-08-26 18:52:59 +08:00
8582860116 光环助手V4.2.0-视频详情优化(第二期)20200825UI测试 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/970 2020-08-26 18:52:30 +08:00
b8903e7814 完成更新优化0826测试 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/946 2020-08-26 18:10:43 +08:00
b47bcfc2c3 Merge branches 'dev' and 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-26 17:56:55 +08:00
35a987a835 完成光环助手V4.2.0-问答首页优化UI测试 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/955 2020-08-26 17:56:49 +08:00
lyr
6f413b27d4 优化"账户与安全"模块代码 2020-08-26 16:09:53 +08:00
92173b4794 游戏详情优化汇总(9) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/975 2020-08-26 15:46:51 +08:00
89e79154aa Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-26 15:21:16 +08:00
de9145cd70 视频上传交互优化(第二期)(1-4,9)https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/969 2020-08-26 15:21:08 +08:00
8bf509ee2d 完成游戏类型优化 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/960 2020-08-26 15:00:42 +08:00
d7144265e1 完成更新推送功能优化0826补充及UI调整 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/946 2020-08-26 14:30:28 +08:00
cc6c759658 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-25 18:34:32 +08:00
8e5d482f9e 修改通知弹窗不显示问题 2020-08-25 18:34:26 +08:00
5ed8f2499a 完成活动分享数据即时反馈需求 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/982 2020-08-25 18:29:39 +08:00
a8c9bcc1b0 完成礼仪考试功能20200825测试的3 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/945 2020-08-25 18:10:17 +08:00
21aabcc561 完成更新推送优化20200825的1 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/946 2020-08-25 18:02:52 +08:00
a2b86a9e21 Merge remote-tracking branch 'origin/dev' into dev 2020-08-25 17:47:29 +08:00
74882f56ee 完成帖子详情20200825测试的(2, 4~10) 2020-08-25 17:47:19 +08:00
1eb9ec1dd3 光环助手V4.2.0-论坛详情功能20200825测试 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/956 2020-08-25 17:44:49 +08:00
9e95c0cc7e Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-25 17:00:34 +08:00
877238d2d5 光环助手V4.2.0-引导设置“通知管理”(第3期)20200825测试2 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/947 2020-08-25 17:00:30 +08:00
lyr
9c6f69b16a 修改绑定手机无法完成问题 2020-08-25 16:53:14 +08:00
64af456182 补充网页JS调用方法 2020-08-25 16:48:32 +08:00
1a84477700 修改视频评论作者标记显示问题 2020-08-25 16:20:29 +08:00
a0b6285596 修改文章标签详情列表不显示 2020-08-25 15:15:29 +08:00
951c139062 修改我的论坛我的帖子列表不显示 2020-08-25 14:23:00 +08:00
99efcd6bbf 光环助手V4.2.0-论坛详情功能20200824测试 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/956 2020-08-25 11:53:24 +08:00
3482f58b1b Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/entity/ForumEntity.kt
#	app/src/main/java/com/gh/gamecenter/entity/GameEntity.kt
2020-08-25 10:07:45 +08:00
6b4f751a16 光环助手V4.2.0-论坛详情功能(1,7,10) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/956 2020-08-25 10:03:26 +08:00
3be1308230 Merge remote-tracking branch 'origin/dev' into dev 2020-08-24 18:27:53 +08:00
b7710cffa3 微调帖子详情样式 2020-08-24 18:27:44 +08:00
lyr
dc4fe89521 账户与安全页底部增加联系客服文案和相应跳转 2020-08-24 18:20:47 +08:00
c33eb6829a 完成游戏详情优化(7,8) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/975 2020-08-24 17:59:21 +08:00
e1793d57eb Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-24 17:28:30 +08:00
cc4c48f718 修改取消论坛后论坛首页数据刷新问题 2020-08-24 17:28:25 +08:00
aa20ed9744 完成自定义栏目的镜像优化 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/963 2020-08-24 16:44:48 +08:00
b6d8688a40 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-24 16:32:58 +08:00
d1da2bb7fa 光环助手V4.2.0-问答首页优化20200824测试(2,5,6,7) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/955 2020-08-24 16:32:53 +08:00
lyr
7828bce732 新增上传抖音方式登录日志 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/951 2020-08-24 15:38:00 +08:00
026a8d7093 Merge branch 'feature-change-gdt-key' into 'dev'
更换广点通ID https://gitlab.ghzs.com/pm/yunying/-/issues/1249

See merge request halo/assistant-android!24
2020-08-24 14:15:57 +08:00
6a9a29c5ff 更换广点通ID https://gitlab.ghzs.com/pm/yunying/-/issues/1249 2020-08-24 14:14:33 +08:00
lyr
16b4b6cc81 修复专题排行榜滑动卡顿问题 2020-08-24 12:00:20 +08:00
863e570b61 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-24 11:53:47 +08:00
c9e8408804 修改视频评论作者标记显示错误 2020-08-24 11:53:42 +08:00
31984f1737 基本完成论坛帖子详情功能 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/967 2020-08-24 11:31:53 +08:00
ad2a0debdd 论坛列表数据同步 2020-08-24 09:56:30 +08:00
4c45657092 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-22 09:57:19 +08:00
5d7fc94d51 优化论坛首页 2020-08-22 09:57:14 +08:00
641b430fe5 优化帖子详情结构 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/967 2020-08-21 18:46:37 +08:00
lyr
e1bb02f4e0 绑定手机号点击"跳过"增加弹窗提示 2020-08-21 18:24:33 +08:00
36fd8cf408 双击论坛tab回到顶部 2020-08-21 15:04:42 +08:00
e48b47b315 处理个人主页论坛列表不显示问题 2020-08-21 14:17:09 +08:00
46935e4cad 补充网页游戏详情用的跳转规则 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/966 2020-08-21 11:45:14 +08:00
b8a6b4baea 处理游戏详情的闪退 2020-08-21 11:42:36 +08:00
8a8f0a95ed 光环助手V4.2.0-视频详情优化(第二期)20200820测试(4,6) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/970 2020-08-21 10:32:52 +08:00
cdbefd2d4f 完成部分帖子详情的功能 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/967 2020-08-20 21:01:40 +08:00
7e79b4e328 基本完成礼仪考试APP端功能 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/945 2020-08-20 19:53:10 +08:00
11dc9f9be0 游戏详情增加论坛Tab 2020-08-20 18:01:27 +08:00
ec255099eb 光环助手V4.2.0-论坛详情功能(9) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/956 2020-08-20 16:21:49 +08:00
64738dceaf 光环助手V4.2.0-论坛详情功能 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/956 2020-08-20 15:40:08 +08:00
7d518696f0 Merge branch 'dev_4.2.0' into dev
# Conflicts:
#	app/src/main/java/com/gh/common/util/EntranceUtils.java
2020-08-20 10:56:44 +08:00
fcd97b66df 光环助手V4.2.0-论坛详情功能 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/956 2020-08-20 10:53:26 +08:00
47f5c3b7c1 缩小保存测试路径的长按区域 2020-08-20 10:33:50 +08:00
b64fee9d25 Merge branch 'dev_4.2.0' into 'dev'
Dev 4.2.0

See merge request halo/assistant-android!23
2020-08-20 09:08:19 +08:00
498efdf5ea Merge branch 'dev' into 'dev_4.2.0'
# Conflicts:
#   dependencies.gradle
2020-08-20 09:08:12 +08:00
59d6450ded 更改论坛帖子详情的实现方式 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/967 2020-08-19 18:41:47 +08:00
7da206af7e 压缩部分原图过大的图片 2020-08-19 18:38:56 +08:00
8bd669e11a 正式环境维持 v4d1 接口 2020-08-19 17:49:12 +08:00
62570aed9e Merge remote-tracking branch 'origin/dev_lyr' into dev_4.2.0
# Conflicts:
#	app/src/main/java/com/gh/common/constant/Constants.java
#	dependencies.gradle
2020-08-19 17:45:17 +08:00
lyr
bfe9c04384 修改登录界面关闭按钮高度 2020-08-19 17:38:15 +08:00
lyr
b27d007d47 1.完成光环助手V4.2.0-优化登录功能 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/949;2.完成光环助手V4.2.0-新增账户安全功能 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/948#note_63972 2020-08-19 16:38:04 +08:00
7e50e6570d 光环助手V4.2.0-问答首页优化(15) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/955 2020-08-19 11:32:22 +08:00
336d449889 全局搜索将'文章'替换为'帖子' 2020-08-18 17:46:13 +08:00
3dfea1e6f9 Merge branch 'dev_4.2.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.2.0 2020-08-18 17:11:15 +08:00
3c1780d9b5 视频上传交互优化UI 2020-08-18 17:11:10 +08:00
35ee7cf03d 光环助手V4.2.0-论坛其他优化 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/968 2020-08-18 17:05:56 +08:00
lyr
72e8c18f9c 1.完成登录界面UI改版;2.增加第三方抖音登录;3.增加账号安全模块 2020-08-18 15:57:02 +08:00
f3f876d213 完成礼仪考试功能的APP UI https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/945 2020-08-18 14:37:45 +08:00
398907db90 完成游戏详情优化汇总(2~5) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/975 2020-08-18 10:18:25 +08:00
5dd251eaa8 完成游戏专题功能优化 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/965 2020-08-17 20:47:29 +08:00
2c73e55f43 调整通用列表的显示元素 2020-08-17 17:31:11 +08:00
f4406d7960 调整帖子评论布局 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/967 2020-08-17 17:22:10 +08:00
3e0a620ac5 更改帖子详情的实现方式 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/967 2020-08-14 18:38:57 +08:00
9ea8c32608 论坛首页优化 2020-08-14 17:51:15 +08:00
e2ea197f9e 光环助手V4.2.0-问答首页优化 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/955 2020-08-14 17:14:30 +08:00
f92038b5bf 光环助手V4.2.0-视频详情优化(第二期)(9,10) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/970 2020-08-13 18:00:58 +08:00
fa9eee2c4a 修改删除视频评论列表刷新错误 2020-08-13 16:52:58 +08:00
3e62fb61e1 Merge branch 'dev_4.2.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.2.0 2020-08-13 16:22:07 +08:00
5d71e0ccc1 光环助手V4.2.0-视频详情优化(第二期)(1-8) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/970 2020-08-13 16:22:02 +08:00
4699923058 清理测试内容 2020-08-13 16:03:55 +08:00
9206938938 更新版本号 2020-08-13 16:00:50 +08:00
46ac569f70 优化静默更新下载逻辑 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/946 2020-08-13 15:43:41 +08:00
b90d1b4f38 处理编译问题 2020-08-13 11:47:10 +08:00
592b7bbc5e 更新 gid 依赖 2020-08-13 11:31:11 +08:00
3ccb8b3772 基本完成更新推送功能优化 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/946 2020-08-12 22:02:54 +08:00
422abe1b87 基本完成更新推送功能优化 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/946 2020-08-12 21:57:46 +08:00
a14f35a4f0 完成启动跳转方法预留 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/966 2020-08-12 17:36:53 +08:00
3bebc92106 恢复误删的包引入 2020-08-12 16:19:24 +08:00
21413cf250 新增跳转 urlScheme https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/966 2020-08-12 15:33:31 +08:00
04a34af370 光环助手V4.2.0-引导设置“通知管理”(第3期)https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/947 2020-08-12 10:25:28 +08:00
e1e6924b6e tinker_base 4.1.0-191 2020-08-11 18:30:29 +08:00
fbd3a42e81 完成粗糙的帖子详情框架,细节待补充 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/967 2020-08-11 18:25:43 +08:00
80a2cbb8cd versionCode 改为191 2020-08-11 18:09:08 +08:00
96fc6cc183 论坛首页蒙层引导 2020-08-11 16:22:52 +08:00
b5ff891db1 修复动态页跳转礼包详情的游戏图标显示问题 2020-08-11 16:03:22 +08:00
d2171e7a3b 更换首页论坛tab图标和点击动画 2020-08-11 15:27:50 +08:00
c3a06f57b1 文章标签详情优化 2020-08-11 11:39:15 +08:00
18f41743bf Merge branch 'dev_4.2.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.2.0 2020-08-11 10:50:20 +08:00
fcc647a1f8 修改发帖子、提问页面 2020-08-11 10:50:15 +08:00
e80b198aa5 添加简单的页面快速跳转功能 2020-08-11 10:38:14 +08:00
52efa96e2c 修复游戏图标的列表复用问题 2020-08-11 10:10:56 +08:00
816dd60298 修复游戏图标角标的复用问题 2020-08-10 18:20:11 +08:00
a181292f80 修复游戏图标角标的复用问题 2020-08-10 18:09:55 +08:00
1b946c325c 光环助手V4.2.0-视频详情优化(第二期)8 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/970 2020-08-10 17:33:59 +08:00
befb323721 测试环境api版本升至v4d2d0 2020-08-10 17:33:20 +08:00
e62c0aaaad 论坛详情、板块成员UI 2020-08-10 17:08:36 +08:00
4ecc0c073b 补充GID获取异常的MTA统计 2020-08-10 11:36:47 +08:00
faa41248eb 修改获取Toast默认偏移量和位置闪退 2020-08-10 10:11:55 +08:00
6dca13e80b 论坛详情UI 2020-08-10 09:43:35 +08:00
f3fab1b3f6 tinker-base_4.1.0 2020-08-07 19:21:13 +08:00
5340a41298 fix bug 2020-08-07 14:24:31 +08:00
553ebc137b 选择论坛UI 2020-08-06 18:00:03 +08:00
caf2a379d9 修复xapk解压后安装包路径没有写入数据库的问题 2020-08-06 16:55:51 +08:00
c59b79427c 修复xapk解压后安装包路径没有写入数据库的问题 2020-08-06 16:42:32 +08:00
dd2338021e 论坛首页UI 2020-08-06 15:14:05 +08:00
e54fcca53e xapk解压失败增加MTA统计 2020-08-06 14:55:40 +08:00
ad416c6a5d xapk解压增加备用解决方案 2020-08-06 14:07:06 +08:00
4a65c1a5c8 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-05 15:53:00 +08:00
878529f646 fix 2020-08-05 15:52:47 +08:00
d01bc1e2d1 移除无用的ijkplayer依赖 2020-08-04 15:59:34 +08:00
d63f5f5ab2 调整广点通激活数据的发送时机 2020-08-04 10:01:00 +08:00
ad0fb7a55a 处理游戏图标类型不一致导致的闪退问题 2020-08-03 16:25:57 +08:00
b0258eef77 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-08-03 16:06:33 +08:00
86d4df8ad9 修复新增开服默认选择时间分钟不准问题 2020-08-03 16:06:20 +08:00
bb11d984f9 处理消息中心闪退问题 2020-08-03 14:56:34 +08:00
d3f3d2ca98 下载详细过程埋点更新 https://gitlab.ghzs.com/stats/stats-issues/-/issues/188 2020-07-31 18:19:52 +08:00
0c1e712c79 编辑封面禁止左右滑动(与图片缩放会有冲突)
修复xapk提示存储不足后没有把当前解压线程移除问题
2020-07-31 15:21:33 +08:00
e193a40651 修改预约弹窗号码提示动画的持续时间 2020-07-31 14:47:42 +08:00
03f36476cb Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-31 11:45:13 +08:00
a721637be3 预约弹窗增加号码提示弹出动画 2020-07-31 11:44:58 +08:00
722fb1ad64 调整视频数据UI间隔 2020-07-31 10:32:01 +08:00
52a05c3aa4 这是环境api版本改为v4d1d0 2020-07-31 10:31:30 +08:00
bcbdac6afc Merge remote-tracking branch 'origin/dev' into dev 2020-07-30 22:29:09 +08:00
a9507af3f4 修复镜像游戏的角标问题 2020-07-30 22:29:01 +08:00
68601ca8be 修改预约弹窗点击弹窗以外区域弹窗没有消失问题 2020-07-30 22:17:00 +08:00
a7adc27896 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-30 21:23:44 +08:00
d19d0eb571 修改预约弹窗的弹出位置 2020-07-30 21:23:30 +08:00
d8e365fe08 修改游戏评论显示异常 2020-07-30 21:12:17 +08:00
b34f61ce0d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-30 18:10:05 +08:00
1f24d16f95 h5游戏增加关闭按钮开关控制 2020-07-30 18:10:00 +08:00
738074ec00 光环助手V4.1.0-游戏评论功能强化20200730测试问题 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/925 2020-07-30 18:09:07 +08:00
c8eee33475 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-30 17:13:25 +08:00
badf9f9c20 修改编辑封面UI
防止手机登录连续点击获取验证码重复发送问题
2020-07-30 17:13:19 +08:00
0398cc4ffc 修改视频数据总览 2020-07-30 15:59:55 +08:00
b88abf6b9a link为空拦截跳转 2020-07-30 15:37:35 +08:00
a0d193bc52 web跳转视频流添加gameId参数 2020-07-30 15:24:33 +08:00
6ac635f8c6 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-30 14:38:11 +08:00
30c7d71114 外部跳转增加qq群 2020-07-30 14:38:05 +08:00
0223b3ab22 修复查看图片的bug(0730测试) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/940 2020-07-30 11:57:48 +08:00
c9663662d5 补充遗漏的游戏图标显示优化页面 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/939 2020-07-30 11:41:17 +08:00
12bed97638 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-30 11:11:25 +08:00
a857af970d 修复游戏评分一直显示加载中问题 2020-07-30 11:11:20 +08:00
7da621583f Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-30 11:08:38 +08:00
46a32b62c2 光环前端优化汇总(2020年7月第3周)20200729测试问题补充5 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/940 2020-07-30 11:08:33 +08:00
45bcc95e7d 游戏详情玩家评论数据同步 2020-07-30 11:07:44 +08:00
7d7bcfaa1d 补充遗漏的游戏图标显示优化页面 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/939 2020-07-30 10:45:23 +08:00
3a9a561c77 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2020-07-30 10:08:03 +08:00
e8d344256a 光环助手V4.1.0-视频上传支持剪辑封面(20200729测试) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/941 2020-07-30 10:07:34 +08:00
1a7c1119bf 微调UI 2020-07-29 17:44:24 +08:00
0b6a2503aa Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-29 17:32:01 +08:00
459b9f65a9 修改封面尝试修复截帧失败问题 2020-07-29 17:31:49 +08:00
6c1ebe531e 更改游戏图标圆角逻辑 2020-07-29 16:47:53 +08:00
604450292b Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-29 15:53:31 +08:00
e42361e84a 1.H5游戏跳转到指趣 2.修改web跳转到视频流闪退 2020-07-29 15:53:24 +08:00
a974652f7f 处理自动打包编译时间不对的问题 2020-07-29 14:40:51 +08:00
309ab54e90 微调UI 2020-07-29 14:40:07 +08:00
486d680c26 补充游戏图标显示优化的页面 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/939 2020-07-29 14:30:22 +08:00
61a5f3a275 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-29 14:22:08 +08:00
c865417a4b 光环助手V4.1.0-游戏评论功能强化20200729测试问题:4,6,7 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/925 2020-07-29 14:22:03 +08:00
b142feaaae 微调下载管理-游戏下载UI 2020-07-29 14:19:15 +08:00
7380854133 微调UI 2020-07-29 11:29:23 +08:00
8a0f185eda 修改视频上传UI 2020-07-29 10:59:17 +08:00
bd9604a53e 微调UI 2020-07-29 10:13:44 +08:00
1aeab51f94 修复上传视频后视频投稿页面无法及时刷新问题 2020-07-29 09:56:54 +08:00
b16a6fedc6 修改列表分页结束数量限制 2020-07-28 17:54:26 +08:00
b97c381ed4 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-28 17:43:04 +08:00
acb8c723a3 微调UI 2020-07-28 17:42:51 +08:00
4492307e23 处理刷新列表MarkerView会显示问题 2020-07-28 17:42:29 +08:00
e31224b332 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-28 17:13:22 +08:00
6933d6c590 修复预约弹窗键盘弹出延迟问题 2020-07-28 17:13:09 +08:00
3d58841ce5 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-28 16:59:45 +08:00
0654b0a25f 更改评论弹窗动画实现方式 2020-07-28 16:59:41 +08:00
44dde3f91b Merge branch 'video_poster' 2020-07-28 16:27:56 +08:00
abad30595f 光环助手V4.1.0-视频上传支持剪辑封面 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/941 2020-07-28 15:14:51 +08:00
c4df411560 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-28 11:36:14 +08:00
2974fa4562 修改视频数据图表自定义MarkerView 2020-07-28 11:36:10 +08:00
b086b1cb0c 完成接入腾讯企点会话接待组件(0727测试4) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/928 2020-07-28 11:24:12 +08:00
22cf026335 删除无用注释 2020-07-28 11:03:48 +08:00
90bd53fe61 修复选择游戏弹窗的闪退问题 2020-07-28 11:03:16 +08:00
9c580a356e 腾讯企点唤起改成应用内 2020-07-28 10:30:05 +08:00
7198c28e6f 补充遗漏的游戏图标角标位置 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/939 2020-07-28 10:29:33 +08:00
7bf074fddc 光环助手4.1.0-前端新增视频数据统计20200727测试1,4 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/936 2020-07-28 09:59:46 +08:00
bea1a336e9 视频编辑封面支持线上视频链接截取 2020-07-27 21:10:11 +08:00
97a9e03192 光环助手V4.1.0-视频上传支持剪辑封面(初步完成,后续细节尚需调整) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/941 2020-07-27 18:05:42 +08:00
244d57b6bc 更改判断应用前后台状态的实现逻辑 2020-07-27 17:44:57 +08:00
3cbd484147 更改判断应用前后台状态的实现逻辑 2020-07-27 17:43:56 +08:00
8b81819c30 修改大图触发下拉消失的滑动阈值为大于60度 2020-07-27 16:31:53 +08:00
1873ac5d4e 光环前端优化汇总(2020年7月第3周)0727测试12 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/940 2020-07-27 16:29:06 +08:00
cf70c1e7fe 光环助手4.1.0-前端新增视频数据统计20200727UI测试 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/936 2020-07-27 15:49:05 +08:00
6f6b26ea4d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-27 15:19:09 +08:00
e2708d9078 对接专区视频流接口 2020-07-27 15:19:05 +08:00
fb5a40c6e4 修复游戏图标的占位图显示问题 2020-07-27 12:03:03 +08:00
e2a10c1410 游戏评论显示折叠评论按钮 2020-07-27 12:01:08 +08:00
5461d3d548 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-27 11:45:26 +08:00
c47365e626 光环助手V4.1.0-游戏评论功能强化 20200725测试问题2,20200727UI测试 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/925 2020-07-27 11:45:22 +08:00
3476f8df3a 修复一些闪退问题 2020-07-27 11:14:48 +08:00
f812c1e5c8 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-27 09:24:51 +08:00
391f196005 修改游戏大事件时间转换错误 2020-07-27 09:24:46 +08:00
097dbca26e 修复客服消息列表页复制ID按钮不显示的问题 2020-07-24 18:34:29 +08:00
a147118381 完成游戏图标显示优化 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/939 2020-07-24 16:31:58 +08:00
e6bdde8273 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-24 15:27:27 +08:00
747757faa7 处理视频数据图标显示问题 2020-07-24 15:27:21 +08:00
6f21b9d0ae 腾讯企点改由内部 webview 跳转 2020-07-24 14:47:20 +08:00
e505554aac 修改视频数据图表配置 2020-07-24 11:18:18 +08:00
3323cce890 删除本地导入的videocache 2020-07-24 09:41:22 +08:00
ffd468db1e 格式化视频数据 2020-07-23 18:29:52 +08:00
e98e0d1522 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-23 17:12:07 +08:00
13a4f2014c 光环助手4.1.0-前端新增视频数据统计 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/936 2020-07-23 17:12:01 +08:00
8cbfe6450a Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-23 11:44:09 +08:00
bcc866888e 删除无用代码 2020-07-23 11:44:02 +08:00
60911d5dcb 移除无用的 glide 依赖 2020-07-23 11:15:35 +08:00
7e77d5749e 处理编译问题 2020-07-23 10:36:06 +08:00
6c3be5627d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-23 10:02:41 +08:00
f6a9585700 彻底移除用数据库存储登录信息的代码 2020-07-23 10:02:30 +08:00
06fddb7dcd 完成游戏管理apk包提供海外下载地址 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/930 2020-07-22 18:21:01 +08:00
3a3f9a625b 删除部分测试代码 2020-07-22 17:49:54 +08:00
3702b104fc 光环助手V4.1.0-安装游戏支持解压xapk文件(20200722测试) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/896 2020-07-22 17:39:46 +08:00
3e023089a1 Merge remote-tracking branch 'origin/dev' into dev 2020-07-22 16:24:37 +08:00
7455674f6b 完成7月第3周优化(3,11,14) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/940 2020-07-22 16:24:26 +08:00
c93c0f2fc6 修改列表分页结束数量限制 2020-07-22 16:23:56 +08:00
727f02e571 光环助手V4.1.0-预约游戏自动填写手机号(20200722测试) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/926 2020-07-22 15:15:25 +08:00
784fae1f5d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-22 14:54:56 +08:00
42ef075912 光环助手V4.1.0-游戏名称点号处理(20200722补充) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/921
修改dev api host
2020-07-22 14:54:44 +08:00
15307c5223 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-22 14:18:38 +08:00
aad3b48883 光环助手V4.1.0-视频详情功能优化20200722测试 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/935 2020-07-22 14:18:31 +08:00
d65d8f1c4c 删除多余刷新动画图片 2020-07-22 11:46:02 +08:00
c581496975 Merge branch 'refresh' into dev 2020-07-22 11:41:41 +08:00
d5481a8888 修改问答-推荐的下拉刷新动画 2020-07-22 11:24:08 +08:00
e0a61278fc fix import 2020-07-22 10:25:57 +08:00
2c36283833 Merge branch 'dev_4.1.0' into 'dev'
Dev 4.1.0

See merge request halo/assistant-android!21
2020-07-22 10:17:38 +08:00
1b5a8f3a7e Merge branch 'dev' into 'dev_4.1.0'
# Conflicts:
#   app/src/main/java/com/gh/common/DefaultUrlHandler.kt
#   app/src/main/java/com/gh/common/util/ShareUtils.java
#   dependencies.gradle
2020-07-22 10:17:19 +08:00
95c918b4e3 光环助手V4.1.0-游戏大事件功能优化 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/938 2020-07-22 09:47:57 +08:00
f32cc1673c 调整查看大图过渡动画 2020-07-21 18:32:32 +08:00
f0fc2f06da Merge branch 'dev_4.1.0' of gitlab.ghzhushou.com:halo/assistant-android into dev_4.1.0 2020-07-21 18:23:58 +08:00
b6c6abaa5b 调整大图动画 2020-07-21 18:23:33 +08:00
6ed67c911c Merge branch 'dev_4.1.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.1.0 2020-07-21 18:14:44 +08:00
1eda223a1e 光环助手V4.1.0-预约游戏自动填写手机号 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/926 2020-07-21 18:14:27 +08:00
316c0c28ab 扩大安利墙列表的部分点击区域 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/940 2020-07-21 17:27:18 +08:00
895d4d5cf1 tinker_base 4.0.3 2020-07-21 17:18:49 +08:00
877df95e02 添加安利墙列表的部分点击区域 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/940 2020-07-21 17:15:57 +08:00
801f0b95e7 版本改为4.0.3 2020-07-21 17:01:07 +08:00
9019f555b5 Merge branch 'dev_4.1.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.1.0 2020-07-21 16:52:00 +08:00
106b03a316 下载文件格式兼容xapk 2020-07-21 16:51:44 +08:00
d8faa554be 优化查看图片交互 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/940 2020-07-21 16:44:59 +08:00
93080a74a7 Merge branch 'dev_4.1.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.1.0 2020-07-21 15:54:08 +08:00
3ea2ede0cb 视频上传增加视频宽高字段 2020-07-21 15:53:59 +08:00
1242848b6f Merge branch 'dev_4.1.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.1.0 2020-07-21 15:35:50 +08:00
24d44a2c90 光环助手V4.1.0-游戏评论功能强化MTA数据统计 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/925 2020-07-21 15:35:45 +08:00
971779a529 Merge branch 'dev_4.1.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.1.0 2020-07-21 15:28:59 +08:00
14f561c237 扩大下载管理删除按钮的点击范围 2020-07-21 15:28:38 +08:00
3a38e746f6 Merge branch 'dev_4.1.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.1.0 2020-07-21 14:38:05 +08:00
dd3bc9d39d 光环助手V4.1.0-游戏评论功能强化1-5,6(1) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/925 2020-07-21 14:38:01 +08:00
39a8062aef 光环后台功能迁移测试汇总0717测试-1 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/923 2020-07-21 14:35:52 +08:00
55b6ccb760 merge xapk branch 2020-07-21 14:35:01 +08:00
a8a55eb9bd 修复首页游戏隐藏评论后还能显示评分问题 2020-07-21 14:30:15 +08:00
3eb73439aa 修改页面loading动画 2020-07-21 11:30:29 +08:00
466e118579 尝试替换SwipeRefreshLayout的下拉动画 2020-07-20 17:58:51 +08:00
b38032074b 按帧导入下拉刷新动画,SwipeRefreshLayout以源码的方式引入到主工程 2020-07-20 17:54:56 +08:00
9ee771e528 Merge branch 'dev_4.1.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.1.0 2020-07-20 17:04:11 +08:00
9253ed47e6 微信浏览器跳转到app 2020-07-20 17:04:03 +08:00
bc82263286 更改获取 bitmap 的实现 2020-07-20 16:41:46 +08:00
11979240ab Merge branch 'dev_4.0.1_bugfix' into dev
# Conflicts:
#	app/src/main/java/com/gh/common/DefaultUrlHandler.kt
#	dependencies.gradle
#	gradle.properties
2020-07-20 15:57:50 +08:00
255e6182a9 更改评论弹窗点击更多按钮交互方式 2020-07-20 15:41:39 +08:00
f170abb7ea 修复分享内容含 gif 图片时会分享失败的问题 2020-07-20 11:00:44 +08:00
eb80deb413 升级应用版本号为 4.1.0, 正式环境接口退回 4.0.2 (正式环境 4.1.0 API 暂未开启) 2020-07-20 10:58:15 +08:00
10ba5a9ba5 修改注释 2020-07-17 17:15:23 +08:00
94c49cba8b 修复裁剪控件图片过大显示异常问题 2020-07-17 17:13:54 +08:00
354dca8b04 非视频作者也可以删除自己的评论 2020-07-17 16:56:51 +08:00
034488ff34 非视频作者也可以删除自己的评论 2020-07-17 16:53:30 +08:00
59c70e23dd 光环前端优化汇总(2020年7月第3周)(5, 8, 12) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/940 2020-07-17 16:04:45 +08:00
7d98a842f1 完成接入腾讯企点会话接待组件 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/928 2020-07-17 14:37:15 +08:00
5f8006dc5a Merge branch 'dev_4.1.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.1.0 2020-07-17 11:24:10 +08:00
239bd69580 update LGLibrary version 2020-07-17 11:24:07 +08:00
bc96f102a1 光环前端优化汇总(2020年7月第3周)(2,4,6,7)https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/940 2020-07-17 11:19:13 +08:00
e2ef3f4d01 尝试解决登录失效后,无法打开登录界面问题 2020-07-17 10:47:07 +08:00
5c20bbf5e4 光环助手V4.1.0-视频详情功能优化 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/935 2020-07-16 18:09:54 +08:00
b07edd256a 增加登录异常MTA事件 2020-07-16 17:15:34 +08:00
1478d37889 Merge branch 'dev_4.1.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.1.0
# Conflicts:
#	app/src/main/res/values/colors.xml
2020-07-16 16:40:24 +08:00
7151b56de3 光环助手V4.1.0-预约游戏自动填写手机号 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/926 2020-07-16 16:37:55 +08:00
220fd9528b 去掉部分页面游戏图标右上角的礼包角标 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/939 2020-07-16 14:43:10 +08:00
1c26c35571 完成首页轮播图数据调整 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/933 2020-07-16 11:03:35 +08:00
78eb6b7b02 Merge branch 'dev_4.1.0' of gitlab.ghzs.com:halo/assistant-android into dev_4.1.0 2020-07-16 09:11:10 +08:00
9dc9add896 折叠评论UI 2020-07-16 09:11:05 +08:00
2d09f8c008 游戏专区外部跳转 2020-07-16 09:07:14 +08:00
166e1e77ec 完成首页弹窗数据统计 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/881 2020-07-15 18:32:07 +08:00
ea782d002b 光环助手V4.1.0-资讯文章配置的超链接跳转逻辑优化2(1,2,3) 3 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/927 2020-07-15 17:27:10 +08:00
f525a3c46d 接口版本改为v4d1d0 2020-07-15 17:23:22 +08:00
bef6cbb212 tinker_base 4.0.2-183 2020-07-15 17:00:17 +08:00
5e0af8654a 完成新首页轮播图数据上报调整 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/933 2020-07-15 16:56:04 +08:00
032a89e0cd versionCode 改为183 2020-07-15 16:48:28 +08:00
c9afb6df02 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-15 16:30:50 +08:00
b8092447ff 游戏列表默认不显示评分 2020-07-15 16:30:43 +08:00
bff20bea49 修复 7.1.1 系统上 toast 可能出现的闪退问题 2020-07-15 16:29:34 +08:00
87f2d9c85f Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2020-07-15 15:04:43 +08:00
154dfc8538 DsBridge原生Api支持无参方法 2020-07-15 15:03:56 +08:00
59c4176983 尝试根据视频帧数获取视频截图 2020-07-15 14:40:10 +08:00
fddcdfb3aa 更改今日头条SDK的初始化位置 2020-07-15 09:41:29 +08:00
cdbf7d39a5 光环助手V4.1.0-资讯文章配置的超链接跳转逻辑优化(1) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/927 2020-07-14 17:56:18 +08:00
6a55821d4d 完成一些todo 2020-07-14 10:16:45 +08:00
a305db7b13 tinker_base 4.0.2-182 2020-07-13 17:14:15 +08:00
58b1cd4b12 versionCode 改为182 2020-07-13 16:45:19 +08:00
5e7559e43f 修复一些闪退问题 2020-07-13 16:42:03 +08:00
2a74e35388 修复 7.1.1 系统上 toast 可能出现的闪退问题 2020-07-13 16:41:22 +08:00
5b9bef79da 修复一些闪退问题 2020-07-13 16:01:11 +08:00
e89750c364 光环助手V4.1.0-游戏名称点号处理 https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/921 2020-07-13 15:38:06 +08:00
9da6cbf097 修复 7.1.1 系统上 toast 可能出现的闪退问题 2020-07-13 15:23:08 +08:00
f83f719283 光环助手V4.1.0-安装游戏支持解压xapk文件(20200710补充) https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/896 2020-07-13 11:16:31 +08:00
4a1c81ffb4 预留方法供网页端确定是否已安装某应用 2020-07-13 09:49:51 +08:00
be26f5168b 增加视频上传urlscheme参数 2020-07-11 21:03:55 +08:00
4e6c75995c tinker_base 4.0.2-bugfix 2020-07-10 17:38:36 +08:00
df693ce0c2 versionCode 改为181 2020-07-10 17:00:55 +08:00
f0236d7ad5 sync submodule 2020-07-10 16:59:18 +08:00
1d3e2b5c16 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-10 16:00:25 +08:00
545d257135 修复一些闪退问题 2020-07-10 16:00:03 +08:00
f5164d2102 修复在模拟器上可能卡启动页的问题 2020-07-10 15:55:58 +08:00
9af83be9a7 修复 7.1.1 系统上 toast 可能出现的闪退问题 2020-07-10 15:40:38 +08:00
49b0b982f5 基本完成Xapk解压安装,还有部分细节可能要调整 2020-07-09 18:31:27 +08:00
ad7543e7bc Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-07-09 14:56:24 +08:00
1bd0db013b 处理Picasso获取Bitmap有时不显示问题 2020-07-09 14:56:18 +08:00
e63a374da1 重新整理Xapk解压部分以及增加取消操作 2020-07-09 09:28:57 +08:00
6564de8a72 整理安装/卸载相关代码,尽量做到统一处理 2020-07-07 14:57:06 +08:00
d57ac57f43 尝试将Xapk安装部分接入到原有的下载体系 2020-07-03 17:09:50 +08:00
942291d7c5 确定xapk的命名和存放路径问题 2020-07-02 16:59:57 +08:00
de597bdd36 初步完成Xapk解压部分 2020-07-01 16:06:03 +08:00
e1fc23a1bb tinker_base-4.0.1_bugfix 2020-06-17 17:51:22 +08:00
2d551a3f73 VersionCode 改为171 2020-06-17 17:42:37 +08:00
9b205366f7 1.修改视频流广告gif不播放 2.添加网页跳转支付宝微信支付 2020-06-16 18:29:20 +08:00
834 changed files with 25790 additions and 8168 deletions

View File

@ -67,6 +67,8 @@ android {
buildConfigField "String", "TD_APPID", "\"${TD_APPID}\""
buildConfigField "String", "LETO_APPID", "\"${LETO_APPID}\""
buildConfigField "String", "TTAD_APPID", "\"${TTAD_APPID}\""
buildConfigField "String", "DOUYIN_CLIENTKEY", "\"${DOUYIN_CLIENTKEY}\""
buildConfigField "String", "DOUYIN_CLIENTSECRET", "\"${DOUYIN_CLIENTSECRET}\""
buildConfigField "String", "MIPUSH_APPID", "\"${MIPUSH_APPID}\""
buildConfigField "String", "MIPUSH_APPKEY", "\"${MIPUSH_APPKEY}\""
@ -266,6 +268,7 @@ dependencies {
// for video streaming
implementation("com.shuyu:gsyVideoPlayer-java:$gsyVideo", {
exclude module: "gsyvideoplayer-androidvideocache"
exclude group: "tv.danmaku.ijk.media"
})
implementation "com.shuyu:GSYVideoPlayer-exo2:$gsyVideo"
@ -283,14 +286,21 @@ dependencies {
debugImplementation "com.github.nichbar.chucker:library:$chucker"
releaseImplementation "com.github.nichbar.chucker:library-no-op:$chucker"
implementation "com.bytedance.applog:RangersAppLog-Lite-cn:$bytedanceApplog"
implementation "com.bytedance.ies.ugc.aweme:opensdk-china-external:$bytedanceAweme"
implementation "com.bytedance.ies.ugc.aweme:opensdk-common:$bytedanceAweme"
implementation "com.aliyun.dpa:oss-android-sdk:${oss}"
implementation "com.airbnb.android:lottie:$lottie"
implementation "net.lingala.zip4j:zip4j:${zip4j}"
implementation("com.github.piasy:BigImageViewer:$bigImageViewer", {
exclude group: 'com.squareup.okhttp3'
exclude group: 'androidx.swiperefreshlayout'
exclude group: 'com.github.bumptech.glide'
})
implementation "com.github.PhilJay:MPAndroidChart:${chart}"
implementation project(':libraries:LGLibrary')
implementation project(':libraries:MTA')
@ -300,7 +310,6 @@ dependencies {
// implementation project(':libraries:WechatShare')
implementation project(':libraries:im')
implementation project(':libraries:Matisse')
implementation project(path: ':libraries:gsyVideoPlayer-proxy_cache')
}
File propFile = file('sign.properties')
if (propFile.exists()) {
@ -331,7 +340,7 @@ if (propFile.exists()) {
android.buildTypes.release.signingConfig = null
}
// 用于测试读取 META-INF 里的 JSON 的代码
// 用于测试读取 META-INF 里的文件
//task generateMetaJson {
// def resDir = new File(buildDir, 'generated/FILES_FOR_META_INF/')
// def destDir = new File(resDir, 'META-INF/')

Binary file not shown.

BIN
app/libs/gid-1.1.jar Normal file

Binary file not shown.

View File

@ -40,7 +40,7 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--可选,穿山甲提供“获取地理位置权限”和“不给予地理位置权限,开发者传入地理位置参数”两种方式上报用户位置,两种方式均可不选,添加位置权限或参数将帮助投放定位广告-->
<!--请注意:无论通过何种方式提供给穿山甲用户地理位置,均需向用户声明地理位置权限将应用于穿山甲广告投放,穿山甲不强制获取地理位置信息-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />-->
<!-- 如果有视频相关的广告且使用textureView播放请务必添加否则黑屏 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
@ -52,14 +52,8 @@
com.shuyu.gsy.base,
com.google.android.exoplayer2,
tv.danmaku.ijk.media.exo2,
shuyu.com.androidvideocache,
pl.droidsonroids.gif,
com.ledong.lib.minigame,
com.ledong.lib.leto,
com.leto.game.base.glide4,
com.leto.game.ad.gdt,
com.leto.game.fcm,
com.leto.game.ad.toutiao" />
com.donkingliang.consecutivescroller" />
<!-- 去掉 SDK 一些流氓权限 -->
<uses-permission
@ -113,7 +107,9 @@
android:screenOrientation="portrait" />
<!--android:theme = "@android:style/Theme.Black.NoTitleBar.Fullscreen" 退出时屏幕抖动 -->
<activity android:name="com.gh.gamecenter.ViewImageActivity" />
<activity
android:name="com.gh.gamecenter.ImageViewerActivity"
android:theme="@style/Theme.Transparent" />
<activity
android:name="com.gh.gamecenter.SearchActivity"
@ -168,6 +164,10 @@
android:name="com.gh.gamecenter.WebActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.FullScreenWebActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.ShareCardPicActivity"
android:screenOrientation="portrait" />
@ -177,9 +177,9 @@
android:screenOrientation="portrait" />
<activity
android:theme="@style/TransparentStatusBarAndNavigationBar"
android:name="com.gh.gamecenter.MessageDetailActivity"
android:screenOrientation="portrait" />
android:screenOrientation="portrait"
android:theme="@style/TransparentStatusBarAndNavigationBar" />
<activity
android:name="com.gh.gamecenter.LibaoActivity"
@ -207,10 +207,18 @@
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.CommentDetailActivity"
android:theme="@style/TransparentStatusBarAndNavigationBar"
android:name="com.gh.gamecenter.security.SecurityActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.security.BindPhoneActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.CommentDetailActivity"
android:screenOrientation="portrait"
android:theme="@style/TransparentStatusBarAndNavigationBar" />
<activity
android:name="com.gh.gamecenter.mygame.MyGameActivity"
android:screenOrientation="portrait" />
@ -389,6 +397,10 @@
android:name="com.gh.gamecenter.qa.article.detail.ArticleDetailActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.article.detail.comment.ArticleDetailCommentActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.draft.CommunityDraftWrapperActivity"
android:screenOrientation="portrait" />
@ -419,9 +431,9 @@
android:screenOrientation="portrait" />
<activity
android:theme="@style/TransparentStatusBarAndNavigationBar"
android:name="com.gh.gamecenter.gamedetail.rating.RatingReplyActivity"
android:screenOrientation="portrait" />
android:screenOrientation="portrait"
android:theme="@style/TransparentStatusBarAndNavigationBar" />
<activity
android:name="com.gh.gamecenter.history.HistoryActivity"
@ -449,7 +461,8 @@
<activity
android:name="com.gh.gamecenter.video.upload.view.UploadVideoActivity"
android:screenOrientation="portrait" />
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden"/>
<activity
android:name="com.gh.gamecenter.video.game.GameVideoActivity"
@ -514,6 +527,40 @@
<activity
android:name=".qa.answer.draft.AnswerDraftActivity"
android:screenOrientation="portrait" />
<activity
android:name=".gamedetail.rating.RatingFoldActivity"
android:screenOrientation="portrait" />
<activity
android:name=".video.data.VideoDataActivity"
android:screenOrientation="portrait" />
<activity
android:name=".video.poster.PosterEditActivity"
android:screenOrientation="portrait" />
<activity
android:name=".video.poster.PosterClipActivity"
android:screenOrientation="portrait" />
<activity
android:name=".forum.select.ForumSelectActivity"
android:screenOrientation="portrait" />
<activity
android:name=".forum.follow.ForumMyFollowActivity"
android:screenOrientation="portrait" />
<activity
android:name=".forum.detail.ForumDetailActivity"
android:screenOrientation="portrait" />
<activity
android:name=".forum.moderator.ModeratorListActivity"
android:screenOrientation="portrait" />
<activity
android:name=".video.label.VideoLabelActivity"
android:screenOrientation="portrait" />
<!-- 使用小米/华为推送弹窗功能提高推送成功率-->
<activity
@ -542,6 +589,12 @@
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
<activity
android:name="${applicationId}.douyinapi.DouYinEntryActivity"
android:launchMode="singleTask"
android:taskAffinity="${applicationId}"
android:exported="true" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}"
@ -607,7 +660,9 @@
</intent-filter>
</receiver>
<meta-data android:name="com.huawei.hms.client.appid" android:value="@string/huawei_push_appid"/>
<meta-data
android:name="com.huawei.hms.client.appid"
android:value="@string/huawei_push_appid" />
<service
android:name="com.gh.base.GHUmengNotificationService"

View File

@ -0,0 +1 @@
{"v":"5.6.9","fr":30,"ip":0,"op":20,"w":66,"h":66,"nm":"bottom bar tab/论坛/选中/E","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"矩形","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":4,"s":[80,80,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"t":13,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":1,"y":0},"t":0,"s":[{"i":[[-0.55,0],[0,0],[0,-0.55],[0,0],[1.38,0],[0,1.38],[0,0]],"o":[[0,0],[0.55,0],[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.55]],"v":[[-1.5,-2.5],[1.5,-2.5],[2.5,-1.5],[2.5,0],[0,2.5],[-2.5,0],[-2.5,-1.5]],"c":true}]},{"i":{"x":0,"y":1},"o":{"x":0.333,"y":0},"t":4,"s":[{"i":[[-0.55,0],[0,0],[0,-0.55],[0,0],[1.38,0],[0,1.38],[0,0]],"o":[[0,0],[0.55,0],[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.55]],"v":[[-1.5,-1.25],[1.5,-1.25],[2.5,-0.25],[2.5,0],[0,1.896],[-2.5,0],[-2.5,-0.25]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":1,"y":0},"t":9,"s":[{"i":[[-0.55,0],[0,0],[0,-0.55],[0,0],[1.38,0],[0,1.38],[0,0]],"o":[[0,0],[0.55,0],[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.55]],"v":[[-1.5,-2.938],[1.5,-2.938],[2.5,-1.938],[2.5,0],[0,2.833],[-2.5,0],[-2.5,-1.938]],"c":true}]},{"t":13,"s":[{"i":[[-0.55,0],[0,0],[0,-0.55],[0,0],[1.38,0],[0,1.38],[0,0]],"o":[[0,0],[0.55,0],[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.55]],"v":[[-1.5,-2.5],[1.5,-2.5],[2.5,-1.5],[2.5,0],[0,2.5],[-2.5,0],[-2.5,-1.5]],"c":true}]}],"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"路径 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,34.599,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.2,0],[2.19,-0.35],[0,-1.82],[0,0],[0,0],[-1.98,0],[0,0],[0,0],[0,0],[-0.72,0.53],[0,0],[0,0],[0,2.05],[0,0],[1.8,0.28]],"o":[[-2.19,0],[-1.8,0.28],[0,0],[0,0],[0.1,1.96],[0,0],[0,0],[0,0],[0.58,0.65],[0,0],[0,0],[2.05,0],[0,0],[0,-1.82],[-2.2,-0.35]],"v":[[-0.003,-9.745],[-6.583,-9.215],[-9.712,-5.555],[-9.712,3.465],[-9.702,3.665],[-6.003,7.175],[-3.383,7.175],[-2.122,9.065],[-2.023,9.185],[0.277,9.405],[3.238,7.175],[5.997,7.175],[9.717,3.465],[9.717,-5.555],[6.587,-9.215]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.266,0.638,1,0.5,0.242,0.595,1,1,0.217,0.552,1],"ix":9}},"s":{"a":0,"k":[-9.712,-9.745],"ix":5},"e":{"a":0,"k":[9.712,9.745],"ix":6},"t":1,"nm":"color","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"路径","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":150,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"预合成 1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33,0],"ix":2},"a":{"a":0,"k":[33,33,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":4,"s":[70,70,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":9,"s":[110,110,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":13,"s":[90,90,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"w":66,"h":66,"ip":0,"op":20,"st":0,"bm":0}],"markers":[]}

View File

@ -0,0 +1,132 @@
[
{
"login": {
"title": "开启消息通知",
"content": "新游上线、互动回复,重要推送不错过",
"image": "bg_notification_login_style_1",
"styleNo": "样式A",
"scenes": "场景1"
},
"question": {
"title": "开启消息通知",
"content": "及时查看大神回答",
"image": "bg_notification_question_style_1",
"styleNo": "样式A",
"scenes": "场景2"
},
"answer": {
"title": "开启消息通知",
"content": "及时查看点赞与评论",
"image": "bg_notification_answer_style_1",
"styleNo": "样式A",
"scenes": "场景3"
},
"article": {
"title": "开启消息通知",
"content": "及时查看点赞与评论",
"image": "bg_notification_article_style_1",
"styleNo": "样式A",
"scenes": "场景4"
},
"video": {
"title": "开启消息通知",
"content": "实时获取审核与推荐进度",
"image": "bg_notification_video_style_1",
"styleNo": "样式A",
"scenes": "场景5"
},
"rating": {
"title": "开启消息通知",
"content": "成功上墙立即知道",
"image": "bg_notification_rating_style_1",
"styleNo": "样式A",
"scenes": "场景6"
},
"gift": {
"title": "开启消息通知",
"content": "新上礼包不再错过",
"image": "bg_notification_gift_style_1",
"styleNo": "样式A",
"scenes": "场景7"
},
"reserveGame": {
"title": "开启消息通知",
"content": "新游上线即时体验",
"image": "bg_notification_reserve_game_style_1",
"styleNo": "样式A",
"scenes": "场景8"
},
"feedback": {
"title": "开启消息通知",
"content": "及时查看客服回复",
"image": "bg_notification_feedback_style_1",
"styleNo": "样式A",
"scenes": "场景9"
}
},
{
"login": {
"title": "咦!是新的小伙伴耶!",
"content": "打开<font color=\"#1383EB\">通知开关</font>,游戏、礼包、抽奖活动不错过",
"image": "bg_notification_login_style_2",
"styleNo": "样式B",
"scenes": "场景1"
},
"question": {
"title": "发布成功!答案马上来!",
"content": "为了第一时间通知您,需要打开<font color=\"#1383EB\">通知开关</font>",
"image": "bg_notification_question_style_2",
"styleNo": "样式B",
"scenes": "场景2"
},
"answer": {
"title": "精彩的回答!大佬牛啤!",
"content": "打开<font color=\"#1383EB\">通知开关</font>,可以第一时间收获赞美和感谢哟!",
"image": "bg_notification_answer_style_2",
"styleNo": "样式B",
"scenes": "场景3"
},
"article": {
"title": "发布成功!不愧是你!",
"content": "打开<font color=\"#1383EB\">通知开关</font>,可以第一时间收获赞美和互动哟!",
"image": "bg_notification_article_style_2",
"styleNo": "样式B",
"scenes": "场景4"
},
"video": {
"title": "“百万”播放预定!",
"content": "<font color=\"#1383EB\">打开通知!</font>第一时间知道审核结果和互动信息哟!",
"image": "bg_notification_video_style_2",
"styleNo": "样式B",
"scenes": "场景5"
},
"rating": {
"title": "这游戏超好玩,我说的!",
"content": "想知道有多少人吃下安利?<font color=\"#1383EB\">打开通知</font>,马上知道!",
"image": "bg_notification_rating_style_2",
"styleNo": "样式B",
"scenes": "场景6"
},
"gift": {
"title": "获得道具:神奇的游戏礼包!",
"content": "<font color=\"#1383EB\">打开通知!</font>礼包上线,马上知道!",
"image": "bg_notification_gift_style_2",
"styleNo": "样式B",
"scenes": "场景7"
},
"reserveGame": {
"title": "玩最新的游戏,做游戏圈最靓的仔",
"content": "<font color=\"#1383EB\">打开通知!</font>游戏上线,更快知道!",
"image": "bg_notification_reserve_game_style_2",
"styleNo": "样式B",
"scenes": "场景8"
},
"feedback": {
"title": "真是重要的反馈!",
"content": "感恩有你,光环更精彩!<font color=\"#1383EB\">打开通知</font>,客服回复,马上知道!",
"image": "bg_notification_feedback_style_2",
"styleNo": "样式B",
"scenes": "场景9"
}
}
]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,159 @@
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.swiperefreshlayout.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.view.View;
import android.view.animation.Animation;
import android.widget.ImageView;
import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
/**
* Private class created to work around issues with AnimationListeners being
* called before the animation is actually complete and support shadows on older
* platforms.
*/
class CircleImageView extends ImageView {
private static final int KEY_SHADOW_COLOR = 0x1E000000;
private static final int FILL_SHADOW_COLOR = 0x3D000000;
// PX
private static final float X_OFFSET = 0f;
private static final float Y_OFFSET = 1.75f;
private static final float SHADOW_RADIUS = 3.5f;
private static final int SHADOW_ELEVATION = 4;
private Animation.AnimationListener mListener;
int mShadowRadius;
CircleImageView(Context context, int color) {
super(context);
final float density = getContext().getResources().getDisplayMetrics().density;
final int shadowYOffset = (int) (density * Y_OFFSET);
final int shadowXOffset = (int) (density * X_OFFSET);
mShadowRadius = (int) (density * SHADOW_RADIUS);
ShapeDrawable circle;
if (elevationSupported()) {
circle = new ShapeDrawable(new OvalShape());
ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
} else {
OvalShape oval = new OvalShadow(mShadowRadius);
circle = new ShapeDrawable(oval);
setLayerType(View.LAYER_TYPE_SOFTWARE, circle.getPaint());
circle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset, shadowYOffset,
KEY_SHADOW_COLOR);
final int padding = mShadowRadius;
// set padding so the inner image sits correctly within the shadow.
setPadding(padding, padding, padding, padding);
}
circle.getPaint().setColor(color);
ViewCompat.setBackground(this, circle);
}
private boolean elevationSupported() {
return android.os.Build.VERSION.SDK_INT >= 21;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (!elevationSupported()) {
setMeasuredDimension(getMeasuredWidth() + mShadowRadius * 2, getMeasuredHeight()
+ mShadowRadius * 2);
}
}
public void setAnimationListener(Animation.AnimationListener listener) {
mListener = listener;
}
@Override
public void onAnimationStart() {
super.onAnimationStart();
if (mListener != null) {
mListener.onAnimationStart(getAnimation());
}
}
@Override
public void onAnimationEnd() {
super.onAnimationEnd();
if (mListener != null) {
mListener.onAnimationEnd(getAnimation());
}
}
/**
* Update the background color of the circle image view.
*
* @param colorRes Id of a color resource.
*/
public void setBackgroundColorRes(int colorRes) {
setBackgroundColor(ContextCompat.getColor(getContext(), colorRes));
}
@Override
public void setBackgroundColor(int color) {
if (getBackground() instanceof ShapeDrawable) {
((ShapeDrawable) getBackground()).getPaint().setColor(color);
}
}
private class OvalShadow extends OvalShape {
private RadialGradient mRadialGradient;
private Paint mShadowPaint;
OvalShadow(int shadowRadius) {
super();
mShadowPaint = new Paint();
mShadowRadius = shadowRadius;
updateRadialGradient((int) rect().width());
}
@Override
protected void onResize(float width, float height) {
super.onResize(width, height);
updateRadialGradient((int) width);
}
@Override
public void draw(Canvas canvas, Paint paint) {
final int viewWidth = CircleImageView.this.getWidth();
final int viewHeight = CircleImageView.this.getHeight();
canvas.drawCircle(viewWidth / 2, viewHeight / 2, viewWidth / 2, mShadowPaint);
canvas.drawCircle(viewWidth / 2, viewHeight / 2, viewWidth / 2 - mShadowRadius, paint);
}
private void updateRadialGradient(int diameter) {
mRadialGradient = new RadialGradient(diameter / 2, diameter / 2,
mShadowRadius, new int[] { FILL_SHADOW_COLOR, Color.TRANSPARENT },
null, Shader.TileMode.CLAMP);
mShadowPaint.setShader(mRadialGradient);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -18,12 +18,19 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle;
import com.gh.base.fragment.BaseFragment;
import com.gh.common.constant.Constants;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.ExtensionsKt;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.PackageInstaller;
import com.gh.common.util.RunningUtils;
import com.gh.common.util.ShareUtils;
import com.gh.common.util.StringUtils;
@ -44,10 +51,6 @@ import org.json.JSONObject;
import java.lang.ref.WeakReference;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle;
import butterknife.ButterKnife;
import pub.devrel.easypermissions.EasyPermissions;
@ -97,10 +100,13 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == com.tencent.connect.common.Constants.REQUEST_QQ_SHARE
|| requestCode == com.tencent.connect.common.Constants.REQUEST_QZONE_SHARE) {
Tencent.onActivityResultData(requestCode, resultCode, data, ShareUtils.getInstance(this).QqShareListener);
}
ExtensionsKt.tryCatchInRelease(() -> {
if (requestCode == com.tencent.connect.common.Constants.REQUEST_QQ_SHARE
|| requestCode == com.tencent.connect.common.Constants.REQUEST_QZONE_SHARE) {
Tencent.onActivityResultData(requestCode, resultCode, data, ShareUtils.getInstance(this).QqShareListener);
}
return null;
});
}
@Override
@ -168,14 +174,15 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
LinearLayout ll = new LinearLayout(this);
TextView tv = new TextView(this);
String envText = "正式环境";
tv.setBackground(ContextCompat.getDrawable(this, R.color.theme));
if (BuildConfig.FLAVOR.equals("internal")) {
envText = "测试环境";
tv.setBackground(ContextCompat.getDrawable(this, R.color.red));
}
tv.setText(envText);
tv.setGravity(Gravity.CENTER);
tv.setTextColor(Color.WHITE);
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
tv.setBackground(ContextCompat.getDrawable(this, R.color.red));
tv.measure(0, 0);
tv.setAlpha(0.15F);
int height = tv.getMeasuredHeight();
@ -186,6 +193,13 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
ll.addView(tv);
ll.setPadding(0, (width - height) / 2, 0, (width - height) / 2);
if (BuildConfig.DEBUG) {
tv.setOnLongClickListener(v -> {
EntranceUtils.saveShortcut(this.getClass().getName(), getIntent().getExtras());
return true;
});
}
screenRootView.addView(view);
screenRootView.addView(ll);
@ -206,7 +220,7 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
if (FileUtils.isEmptyFile(showDialog.getPath())) {
toast(R.string.install_failure_hint);
} else {
startActivity(PackageUtils.getUninstallIntent(BaseActivity.this, showDialog.getPath()));
PackageInstaller.uninstall(BaseActivity.this, showDialog.getPath());
}
});
} else if (LOGIN_EXCEPTION.equals(showDialog.getType())) {

View File

@ -95,7 +95,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
mDraftBtn.text = if (this is AnswerEditActivity) {
"回答草稿"
} else "文章草稿"
} else "帖子草稿"
}
@OnClick(R.id.editor_image, R.id.editor_font, R.id.editor_link, R.id.editor_paragraph,

View File

@ -14,6 +14,13 @@ import android.view.Window;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;
import com.gh.common.util.DisplayUtils;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.DownloadManagerActivity;
@ -31,13 +38,6 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;
/**
* 需要用到工具栏的页面使用
* <p>
@ -49,7 +49,7 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
@Nullable
private PackageViewModel mPackageViewModel;
protected RelativeLayout mToolbarContainer;
protected View mToolbarContainer;
protected Toolbar mToolbar;

View File

@ -5,6 +5,7 @@ import android.os.Looper
import com.gh.common.AppExecutor.ioExecutor
import com.gh.common.AppExecutor.lightWeightIoExecutor
import com.gh.common.AppExecutor.uiExecutor
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.Executor
import java.util.concurrent.Executors
@ -25,6 +26,8 @@ object AppExecutor {
@JvmStatic
val ioExecutor = Executors.newCachedThreadPool() // 用 by lazy 可能影响初始化速度
val cachedScheduler by lazy { Schedulers.from(ioExecutor) }
class MainThreadExecutor : Executor {
private val mainThreadHandler = Handler(Looper.getMainLooper())

View File

@ -1,21 +1,24 @@
package com.gh.common
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.webkit.JavascriptInterface
import androidx.annotation.Keep
import androidx.appcompat.app.AppCompatActivity
import com.gh.base.CurrentActivityHolder
import com.gh.common.constant.Constants
import com.gh.common.util.*
import com.gh.common.view.dsbridge.CompletionHandler
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.ImageViewerActivity
import com.gh.gamecenter.LoginActivity
import com.gh.gamecenter.ViewImageActivity
import com.gh.gamecenter.entity.Badge
import com.gh.gamecenter.entity.MtaEvent
import com.gh.gamecenter.entity.NotificationUgc
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.room.AppDatabase
import com.gh.gamecenter.user.LoginTag
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
@ -24,6 +27,8 @@ import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
import java.util.*
import kotlin.collections.ArrayList
class DefaultJsApi(var context: Context) {
@ -46,7 +51,7 @@ class DefaultJsApi(var context: Context) {
@JavascriptInterface
fun getUserInfo(msg: Any): String {
return UserManager.getInstance().userInfoEntity.toJson()
return UserManager.getInstance().userInfoEntity?.toJson() ?: ""
}
@JavascriptInterface
@ -65,12 +70,11 @@ class DefaultJsApi(var context: Context) {
val userInfoEntity = UserManager.getInstance().userInfoEntity
if (msg.toString().isNotEmpty()) {
val badge = msg.toString().toObject() ?: Badge()
userInfoEntity.badge = badge
userInfoEntity?.badge = badge
} else {
userInfoEntity.badge = null
userInfoEntity?.badge = null
}
UserManager.getInstance().userInfoEntity = userInfoEntity
AppDatabase.getInstance(context).userInfoDao().updateUserInfo(userInfoEntity)
}
@JavascriptInterface
@ -83,6 +87,11 @@ class DefaultJsApi(var context: Context) {
return BuildConfig.VERSION_NAME
}
@JavascriptInterface
fun getAppVersionCode(msg: Any): Int {
return PackageUtils.getVersionCode()
}
@JavascriptInterface
fun bindWechat(msg: Any, handler: CompletionHandler<Any>) {
context.ifLogin("浏览器") {
@ -139,7 +148,21 @@ class DefaultJsApi(var context: Context) {
val context = CurrentActivityHolder.getCurrentActivity()
context?.startActivity(ViewImageActivity.getViewImageIntent(context, imageEvent.imageList, imageEvent.position, "浏览器"))
context?.startActivity(ImageViewerActivity.getIntent(context, imageEvent.imageList, imageEvent.position, "浏览器"))
}
@JavascriptInterface
fun isInstalled(event: Any): String {
val localInstalledPackageList = PackageUtils.getAllPackageName(HaloApp.getInstance().application)
val packageNameList: ArrayList<String> = event.toString().toObject() ?: ArrayList()
for (packageName in packageNameList) {
if (!localInstalledPackageList.contains(packageName)) {
return "false"
}
}
return "true"
}
@JavascriptInterface
@ -148,7 +171,48 @@ class DefaultJsApi(var context: Context) {
Base64ImageHolder.image = event.toString()
context?.startActivity(ViewImageActivity.getBase64ViewImageIntent(context, true))
context?.startActivity(ImageViewerActivity.getBase64Intent(context, true))
}
@JavascriptInterface
fun openNotificationSetting(msg: Any) {
NotificationHelper.show(context as AppCompatActivity, NotificationUgc.LOGIN)
}
@JavascriptInterface
fun useDarkStatusBarText(msg: Any) {
runOnUiThread {
DisplayUtils.transparentStatusBar(context as AppCompatActivity)
DisplayUtils.setLightStatusBar(context as AppCompatActivity, msg.toString() == "true")
}
}
@JavascriptInterface
fun exitWebView(msg: Any) {
runOnUiThread { (context as Activity).finish() }
}
@JavascriptInterface
fun updateRegulationTestStatus(msg: Any) {
if (msg.toString().toLowerCase(Locale.getDefault()) == "pass") {
SPUtils.setString(Constants.SP_REGULATION_TEST_PASS_STATUS, "pass")
}
}
@JavascriptInterface
fun getStatusBarHeight(msg: Any): String {
val statusBarHeight = DisplayUtils.getStatusBarHeight(context.resources)
return "$statusBarHeight"
}
@JavascriptInterface
fun getGid(msg: Any): String {
return HaloApp.getInstance().gid
}
@JavascriptInterface
fun showIncompatibleVersionDialog(msg: Any) {
DialogUtils.showLowVersionDialog(context)
}
@Keep

View File

@ -4,20 +4,23 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.text.TextUtils
import com.gh.common.util.CheckLoginUtils
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
import android.util.Base64
import com.gh.common.util.*
import com.gh.common.util.DirectUtils.directToGameDetailVideoStreaming
import com.gh.common.util.DirectUtils.directToGameServerCalendar
import com.gh.common.util.DirectUtils.directToGameVideo
import com.gh.common.util.DirectUtils.directToLinkPage
import com.gh.common.util.DirectUtils.directToVideoDetail
import com.gh.common.util.EntranceUtils
import com.gh.gamecenter.*
import com.gh.gamecenter.entity.CommunityEntity
import com.gh.gamecenter.entity.SubjectRecommendEntity
import com.gh.gamecenter.entity.VideoLinkEntity
import com.gh.common.util.GsonUtils.gson
import com.gh.gamecenter.LibaoDetailActivity
import com.gh.gamecenter.MainActivity
import com.gh.gamecenter.NewsDetailActivity
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.subject.SubjectActivity
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
import com.lightgame.utils.Utils
import java.nio.charset.Charset
object DefaultUrlHandler {
@ -37,7 +40,7 @@ object DefaultUrlHandler {
when (host) {
"article" -> context.startActivity(NewsDetailActivity.getIntentById(context, id, entrance))
"game" -> GameDetailActivity.startGameDetailActivity(context, id, "libao" == uri.getQueryParameter("to"), entrance)
"game" -> DirectUtils.directToGameDetail(context, id = id, tab = uri.getQueryParameter("to"), autoDownload = uri.getQueryParameter("auto_download") == "true", entrance = entrance)
"column" -> SubjectActivity.startSubjectActivity(context, id, uri.getQueryParameter("name"), false, entrance)
@ -50,7 +53,7 @@ object DefaultUrlHandler {
e.printStackTrace()
}
"qqqun" -> {
EntranceUtils.HOST_QQ_QUN -> {
val key = uri.getQueryParameter("key")
if (!DirectUtils.directToQqGroup(context, key)) {
Utils.toast(context, "请检查是否已经安装手机QQ")
@ -124,12 +127,14 @@ object DefaultUrlHandler {
val title = if (titleParameter.isNullOrEmpty()) "" else "#$titleParameter#"
val categoryId = uri.getQueryParameter("category_id") ?: ""
val link = uri.getQueryParameter("link") ?: ""
val linkEntity = VideoLinkEntity(title, categoryId, link)
// if (!CheckLoginUtils.isLogin()) {
// HaloApp.put(EntranceUtils.HOST_UPLOAD_VIDEO, linkEntity)
// }
val gameId = uri.getQueryParameter("gameId") ?: ""
val gameName = uri.getQueryParameter("gameName") ?: ""
val tagActivityId = uri.getQueryParameter("tagActivityId") ?: ""
val tagActivityName = uri.getQueryParameter("tagActivityName") ?: ""
val linkEntity = VideoLinkEntity(title, categoryId, link, tagActivityId, tagActivityName)
val simpleGameEntity = SimpleGameEntity(gameId, gameName)
CheckLoginUtils.checkLogin(context, null, true, EntranceUtils.ENTRANCE_BROWSER) {
DirectUtils.directToVideoManager(context, linkEntity, EntranceUtils.ENTRANCE_BROWSER, "")
DirectUtils.directToVideoManager(context, linkEntity, simpleGameEntity, EntranceUtils.ENTRANCE_BROWSER, "")
}
}
EntranceUtils.HOST_USERHOME -> {
@ -140,8 +145,19 @@ object DefaultUrlHandler {
val referer = uri.getQueryParameter("referer") ?: ""
val type = uri.getQueryParameter("type") ?: ""
val act = uri.getQueryParameter("act") ?: ""
val loaction = if (TextUtils.isEmpty(act)) id else VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.value
directToVideoDetail(context, id, loaction, false, "", entrance, "", referer, type, act)
val gameId = uri.getQueryParameter("gameId") ?: ""
val fieldId = uri.getQueryParameter("fieldId") ?: ""
val sectionName = uri.getQueryParameter("sectionName") ?: ""
val paginationType = uri.getQueryParameter("paginationType")
?: "page"//活动分页方式 page filter
val location = if (!TextUtils.isEmpty(act)) {
VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.value
} else if (!TextUtils.isEmpty(fieldId)) {
VideoDetailContainerViewModel.Location.GAME_ZONE.value
} else {
id
}
directToVideoDetail(context, id, location, false, gameId, entrance, "", referer, type, act, paginationType, fieldId, sectionName)
}
EntranceUtils.HOST_VIDEO_SINGLE -> {
val referer = uri.getQueryParameter("referer") ?: ""
@ -191,7 +207,7 @@ object DefaultUrlHandler {
val name = uri.getQueryParameter("name")
?: ""
val entity = SubjectRecommendEntity(link = id, name = name, text = name)
DirectUtils.directToBlock(context, entity)
DirectUtils.directToBlock(context, entity, entrance)
}
EntranceUtils.HOST_SERVER_BLOCK -> {
@ -215,14 +231,161 @@ object DefaultUrlHandler {
}
EntranceUtils.HOST_GAME_UPLOAD -> {
DirectUtils.directGameUpload(context,entrance = entrance, path = "")
DirectUtils.directGameUpload(context, entrance = entrance, path = "")
}
EntranceUtils.HOST_GAME_ZONE -> {
val zoneUrl = uri.getQueryParameter("url") ?: ""
DirectUtils.directGameZone(context, id, zoneUrl, entrance)
}
EntranceUtils.HOST_LINK -> {
try {
val dataString = uri.getQueryParameter("data")
if (!TextUtils.isEmpty(dataString)) {
val linkData = Base64.decode(dataString, Base64.DEFAULT)
val linkDataString = String(linkData, Charset.defaultCharset())
val le = gson.fromJson(linkDataString, LinkEntity::class.java)
directToLinkPage(context, le, entrance, "")
}
} catch (e: Exception) {
e.printStackTrace()
}
}
EntranceUtils.HOST_GAME_NEWS -> {
DirectUtils.directToGameNews(
context,
uri.getQueryParameter(EntranceUtils.KEY_GAME_ID),
uri.getQueryParameter(EntranceUtils.KEY_GAME_NAME),
entrance);
}
EntranceUtils.HOST_GAME_CALENDAR -> {
directToGameServerCalendar(context, uri.getQueryParameter(EntranceUtils.KEY_GAME_ID))
}
EntranceUtils.HOST_HISTORY_APK -> {
DirectUtils.directToHistoryApk(context, uri.getQueryParameter(EntranceUtils.KEY_GAME_ID))
}
EntranceUtils.HOST_FORUM_DETAIL -> {
DirectUtils.directForumDetail(context, id, entrance)
}
EntranceUtils.HOST_GAME_RATING_DETAIL -> {
DirectUtils.directToGameRatingDetail(context, uri.getQueryParameter(EntranceUtils.KEY_GAME_ID), uri.getQueryParameter(EntranceUtils.KEY_COMMENT_ID), EntranceUtils.ENTRANCE_BROWSER)
}
EntranceUtils.HOST_FORUM -> {
DirectUtils.directToForum(context);
}
else -> DialogUtils.showLowVersionDialog(context)
}
return true
} else if ("zhiqu" == uri.scheme) {
if (PackageUtils.isInstalled(context, "com.beieryouxi.zqyxh")) {
val intent = Intent()
intent.data = Uri.parse(url)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(intent)
} else {
Utils.toast(context, "请安装指趣游戏盒")
}
}
if (url.startsWith("alipays:") || url.startsWith("alipay")) {
try {
context.startActivity(Intent("android.intent.action.VIEW", Uri.parse(url)))
} catch (e: Exception) {
ToastUtils.showToast("请安装支付宝客户端")
}
return true
} else if (url.startsWith("weixin")) {
try {
context.startActivity(Intent("android.intent.action.VIEW", Uri.parse(url)))
} catch (e: Exception) {
ToastUtils.showToast("请安装微信客户端")
}
return true
} else if (url.startsWith("mqqwpa")) {
try {
context.startActivity(Intent("android.intent.action.VIEW", Uri.parse(url)))
} catch (e: Exception) {
ToastUtils.showToast("请安装QQ客户端")
}
return true
}
if ("http" != uri.scheme && "https" != uri.scheme) return true
return false
}
@JvmStatic
fun transformNormalScheme(context: Context, url: String, entrance: String): Boolean {
val uri = Uri.parse(url)
if (uri.host == "www.ghzs666.com"
|| uri.host == "www.ghzs.com"
|| uri.host == "ask.ghzs.com"
|| uri.host == "m.ghzs.com"
|| uri.host == "m.ghzs666.com") {
Utils.log(uri.path)
uri.path?.apply {
when {
contains("game") -> {
val gameId = uri.getQueryParameter("gameId") ?: ""
DirectUtils.directToGameDetail(context, gameId, entrance, autoDownload = false, traceEvent = null)
}
contains("question") -> {
val questionId = split("/")[2]
val answerId = uri.getQueryParameter("answer")
if (answerId.isNullOrEmpty()) {
DirectUtils.directToQuestionDetail(context, questionId, entrance, "")
} else {
DirectUtils.directToAnswerDetail(context, answerId, entrance, "")
}
}
contains("communities") && contains("article") -> {
var communityId = ""
var type = ""
var typeId = ""
val split = replace("/communities", "").replace(".html", "").split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
for (text in split) {
if (TextUtils.isEmpty(communityId)) {
communityId = text
continue
}
if (TextUtils.isEmpty(type)) {
type = text
continue
}
if (TextUtils.isEmpty(typeId)) {
typeId = text
}
}
if ("articles" == type) {
DirectUtils.directToCommunityArticle(
context, typeId, communityId,
entrance, "文章链接")
}
}
contains("article") -> {
val articleId = split("/")[2].replace(".html", "")
DirectUtils.directToArticle(context, articleId, entrance)
}
contains("columns") -> {
val columnsId = split("/")[3]
val id = uri.getQueryParameter("communityId") ?: ""
val name = uri.getQueryParameter("communityName") ?: ""
DirectUtils.directToCommunityColumn(context, CommunityEntity(id, name), columnsId, entrance, "")
}
contains("zone") -> {
val gameId = split("/")[2]
DirectUtils.directGameZone(context, gameId, url, entrance)
}
}
}
return true
}
return false
}
}

View File

@ -4,22 +4,26 @@ import com.gh.common.exposure.ExposureManager
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.loghub.LoghubUtils
import com.gh.common.util.doOnMainProcessOnly
import com.gh.common.util.tryCatchInRelease
import com.gh.common.videolog.VideoRecordUtils
import com.gh.download.DownloadDataHelper
import com.gh.gamecenter.entity.TimeEntity
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
import kotlin.concurrent.fixedRateTimer
object FixedRateJobHelper {
private const val CHECKER_PERIOD: Long = 60 * 1000L
private const val CHECKER_PERIOD: Long = 15 * 1000L
private const val TIME_PERIOD: Long = 600 * 1000L
private const val LOGHUB_PERIOD: Long = 120 * 1000L
private const val EXPOSURE_PERIOD: Long = 300 * 1000L
private const val REGION_SETTING_PERIOD: Long = 300 * 1000L
private const val VIDEO_RECORD_PERIOD: Long = 60 * 1000L
private const val DOWNLOAD_HEARTBEAT_PERIOD: Long = 60 * 1000L
private const val DOWNLOAD_HEARTBEAT_SHEET_PERIOD: Long = 15 * 1000L
private var mExecuteCount: Int = 0
var timeDeltaBetweenServerAndClient: Long = 0
@ -31,7 +35,7 @@ object FixedRateJobHelper {
// 时间校对10分钟一次
if ((mExecuteCount * CHECKER_PERIOD) % TIME_PERIOD == 0L) {
RetrofitManager.getInstance(HaloApp.getInstance().application).api.time
.subscribeOn(Schedulers.io())
.subscribeOn(AppExecutor.cachedScheduler)
.subscribe(object : Response<TimeEntity>() {
override fun onResponse(response: TimeEntity?) {
val serverTime = response?.time
@ -45,6 +49,14 @@ object FixedRateJobHelper {
ExposureManager.commitSavedExposureEvents(true)
}
// 分片检测下载进度
if ((mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_SHEET_PERIOD == 0L) {
tryCatchInRelease {
val upload = (mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_PERIOD == 0L
DownloadDataHelper.uploadDownloadHeartbeat(upload)
}
}
// 提交普通 loghub 数据
if ((mExecuteCount * CHECKER_PERIOD) % LOGHUB_PERIOD == 0L) {
LoghubUtils.commitSavedLoghubEvents()

View File

@ -95,6 +95,7 @@ object PushManager {
jsonObject.put("os", meta.os)
jsonObject.put("os_version", meta.android_version)
jsonObject.put("mac", meta.mac)
jsonObject.put("gid", meta.gid)
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())

View File

@ -51,6 +51,8 @@ public class Config {
public static final String BUGLY_APPID = BuildConfig.BUGLY_APPID;
public static final String LETO_APPID = BuildConfig.LETO_APPID;
public static final String TTAD_APPID = BuildConfig.TTAD_APPID;
public static final String DOUYIN_CLIENTKEY = BuildConfig.DOUYIN_CLIENTKEY;
public static final String DOUYIN_CLIENTSECRET = BuildConfig.DOUYIN_CLIENTSECRET;
// http://www.ghzs666.com/article/${articleId}.html
public static final String URL_ARTICLE = "http://www.ghzs666.com/article/"; // ghzs/ghzs666 统一
public static final String PATCHES = "patches";

View File

@ -1,6 +1,7 @@
package com.gh.common.constant;
import com.gh.common.util.PackageUtils;
import com.halo.assistant.HaloApp;
public class Constants {
@ -12,11 +13,12 @@ public class Constants {
public final static int NOT_NETWORK_CODE = 504; // 没有网络的状态码(应该是这个吧!)
public static final String LOGIN_TOKEN_ID = "userToken_id"; // 用户ID 与服务器无关
public static final String USER_TOKEN_KEY = "userTokenKey";
public static final String USER_INFO_KEY = "userInfoKey";
public static final String WELCOME_DIALOG_ID = "welcome_dialog_id";
public static final String WELCOME_DIALOG_LINK_TITLE = "welcome_dialog_link_title";
public static final String DEVICE_KEY = "deviceKey";
public static final String HAS_REQUESTED_NOTIFICATION_PERMISSIONS = "has_requested_notification_permissions";
@ -28,12 +30,12 @@ public class Constants {
public static final String XPOSED_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
public static final String EB_QUIT_LOGIN = "quit_login";
// 用于避免历史下载掺和到普通下载状态的 ID 修饰符
public static final String GAME_ID_DIVIDER = ":";
// 用于避免历史下载影响到部分依赖名字作为数据更新条件的修饰符
public static final String GAME_NAME_DECORATOR = " ";
// 游戏详情进入时的自定义栏目标签是否已经默认展开过一次的标记
public static final String SP_HAS_EXPANDED_GAME_DETAIL_TAGS = "has_expanded_game_detail_tags";
// 游戏详情进入时的自定义栏目标签是否已经显示过一次展开更多的浮窗提示
@ -42,7 +44,15 @@ public class Constants {
// 最近显示的弹窗信息
public static final String SP_LAST_OPENING_ID = "last_opening_dialog_id";
public static final String SP_LAST_OPENING_TIME = "last_opening_dialog_time";
// 游戏图标和图标角标
public static final String RAW_GAME_ICON = "raw_game_icon";
public static final String GAME_ICON_SUBSCRIPT = "game_icon_subscript";
public static final String EXTRA_DOWNLOAD_TYPE = "extra_download_type";
public static final String SILENT_UPDATE = "静默更新";
public static final String LAST_GHZS_UPDATE_FILE_SIZE = "last_ghzs_update_file_size";
// 新用户首次启动光环的时间
public static final String SP_INITIAL_USAGE_TIME = "initial_usage_time";
@ -53,6 +63,9 @@ public class Constants {
public static final String SP_SHOWED_NOTIFICATION_ARTICLE = "show_notification_article_hint";
public static final String SP_SHOWED_NOTIFICATION_VIDEO = "show_notification_video_hint";
public static final String SP_SHOWED_NOTIFICATION_RATING = "show_notification_rating_hint";
public static final String SP_SHOWED_NOTIFICATION_GIFT = "show_notification_gift_hint";
public static final String SP_SHOWED_NOTIFICATION_RESERVE_GAME = "show_notification_reserve_game_hint";
public static final String SP_SHOWED_NOTIFICATION_FEEDBACK = "show_notification_feedback_hint";
// 新版本 也要触发一次“通知管理” 引导弹窗
public static final String SP_SHOWED_NOTIFICATION_NEW_VERSION = "show_notification_new_version";
// 今天是否已经触发了 “通知管理” 引导弹窗
@ -91,6 +104,17 @@ public class Constants {
public static final String SP_TOP_VIDEO_SCHEDULE = "top_video_schedule";
//我的光环小红点提示
public static final String SP_GH_RED_POINT_REMIND = "gh_red_point_remind";
//论坛首页引导
public static final String SP_FORUM_GUIDE = "forum_guide";
//礼仪考试开启状态
public static final String SP_REGULATION_TEST_LAST_REMIND_TIME = "regulation_test_last_remind_time";
public static final String SP_REGULATION_TEST_STATUS = "regulation_test_status";
public static final String SP_REGULATION_TEST_PASS_STATUS = "regulation_test_pass_status";
//相同设备号,每一种第三方登录方式登录后弹出绑定手机页面的次数
public static final String SP_QQ_SHOW_BIND_PHONE_TIME = "qq_show_bind_phone_time" + HaloApp.getInstance().getGid();
public static final String SP_WECHAT_SHOW_BIND_PHONE_TIME = "wechat_show_bind_phone_time" + HaloApp.getInstance().getGid();
public static final String SP_WEIBO_SHOW_BIND_PHONE_TIME = "weibo_show_bind_phone_time" + HaloApp.getInstance().getGid();
public static final String SP_DOUYIN_SHOW_BIND_PHONE_TIME = "douyin_show_bind_phone_time" + HaloApp.getInstance().getGid();
//手机号码匹配规则
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
@ -100,14 +124,24 @@ public class Constants {
//输入规则
public static final String INPUT_RULE = "0123456789abcdefghijklnmopqrstuvwxyzABCDEFGHIJKLNMOPQRSTUVWXYZ_";
// 微信绑定地址地址
// 微信绑定地址
public static final String WECHAT_BIND_ADDRESS_DEV = "https://resource.ghzs.com/page/wechat_dev/index.html#/";
public static final String WECHAT_BIND_ADDRESS = "https://resource.ghzs.com/page/wechat_pro/index.html#/";
// 礼仪考试地址
public static final String REGULATION_TEST_ADDRESS_DEV = "https://static-web.ghzs.com/etiquette-dev/index.html#/";
public static final String REGULATION_TEST_ADDRESS = "https://static-web.ghzs.com/etiquette/index.html#/";
// 徽章
public static final String BADGE_ADDRESS_DEV = "http://resource.ghzs.com/page/badge_dev/index.html#/";
public static final String BADGE_ADDRESS = "http://resource.ghzs.com/page/badge_pro/index.html#/";
// 腾讯企点地址
public static final String TENCENT_QIDIAN_ADDRESS = "https://url.cn/D80iyMVV?_type=wpa&qidian=true";
//版规声明
public static final String FORUM_REGULATIONS_NEWS_ID = "5f4db9cc34d44d01b92fd670";
//最少需要多少数据才能上传
public static final int DATA_AMOUNT = 20;

View File

@ -40,12 +40,14 @@ import com.gh.common.util.LogUtils;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.NewsUtils;
import com.gh.common.util.NumberUtils;
import com.gh.common.util.PackageInstaller;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.PermissionHelper;
import com.gh.common.util.PlatformUtils;
import com.gh.common.util.ReservationHelper;
import com.gh.common.view.DownloadProgressBar;
import com.gh.common.view.DrawableView;
import com.gh.common.view.GameIconView;
import com.gh.download.DownloadManager;
import com.gh.download.dialog.DownloadDialog;
import com.gh.gamecenter.DownloadManagerActivity;
@ -313,6 +315,13 @@ public class BindingAdapters {
}
}
@BindingAdapter("game")
public static void setGame(View view, GameEntity gameEntity) {
if (gameEntity != null && view instanceof GameIconView) {
((GameIconView) view).displayGameIcon(gameEntity);
}
}
@BindingAdapter("articleType")
public static void setArticleType(TextView view, String articleType) {
NewsUtils.setNewsType(view, articleType, 0, 0);
@ -427,15 +436,16 @@ public class BindingAdapters {
case PLUGIN:
if (gameEntity.getApk().size() == 1) {
ApkEntity apk = gameEntity.getApk().get(0);
DownloadDialogHelper.findAvailableDialogAndShow(v.getContext(), gameEntity, apk,
() -> {
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
});
DownloadDialogHelper.findAvailableDialogAndShow(v.getContext(), gameEntity, apk, () -> {
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
DialogUtils.showOverseaDownloadDialog(v.getContext(), gameEntity, () -> {
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
});
});
});
});
} else {
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
@ -467,7 +477,7 @@ public class BindingAdapters {
if (gameEntity.getApk().size() == 1) {
DownloadEntity downloadEntity = DownloadManager.getInstance(progressBar.getContext()).getDownloadEntityByUrl(gameEntity.getApk().get(0).getUrl());
if (downloadEntity != null) {
PackageUtils.launchSetup(v.getContext(), downloadEntity);
PackageInstaller.install(v.getContext(), downloadEntity);
}
}
break;
@ -506,7 +516,7 @@ public class BindingAdapters {
HistoryHelper.insertGameEntity(gameEntity);
}
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), isPlay));
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), isPlay,linkEntity.getCloseButton()));
progressBar.getContext().startActivity(i);
break;
}
@ -775,4 +785,17 @@ public class BindingAdapters {
}
view.setText(span);
}
@BindingAdapter({"setVideoData"})
public static void setVideoData(TextView view, int count) {
if (count > 0) {
view.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(view.getContext(), R.drawable.ic_video_data_up), null, null, null);
view.setTextColor(ContextCompat.getColor(view.getContext(), R.color.text_EA3333));
view.setText(count + "");
} else {
view.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
view.setTextColor(ContextCompat.getColor(view.getContext(), R.color.text_999999));
view.setText("-");
}
}
}

View File

@ -2,28 +2,34 @@ package com.gh.common.dialog
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import android.content.res.AssetManager
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import com.gh.common.util.DisplayUtils
import androidx.core.content.ContextCompat
import com.gh.common.util.GsonUtils
import com.gh.common.util.MtaHelper
import com.gh.common.util.PermissionHelper
import com.gh.common.util.fromHtml
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.NotificationHint
import com.gh.gamecenter.entity.NotificationStyleEntity
import com.gh.gamecenter.entity.NotificationUgc
import com.lightgame.utils.Utils
import kotlinx.android.synthetic.main.dialog_notification_hint.*
import org.json.JSONArray
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import kotlin.random.Random
// 通知权限弹窗
class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
private var mNotificationHint: NotificationHint? = null
private var mNotificationUgc: NotificationUgc? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.dialog_notification_hint, null)
@ -34,23 +40,34 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
titleTv.text = mNotificationHint?.title
contentContainer.removeAllViews()
for (item in mNotificationHint?.content ?: arrayListOf()) {
val tv = TextView(context)
tv.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
topMargin = if (contentContainer.childCount == 0) 0 else DisplayUtils.dip2px(12f)
}
tv.text = item
tv.setTextColor(Color.parseColor("#1383EB"))
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
contentContainer.addView(tv)
val jsonString = getJsonFromAssets()
if (jsonString.isNullOrEmpty()) {
Utils.log("Failed to obtain configuration file")
return
}
val index = Random.nextInt(2)
val jsonArray = JSONArray(jsonString)
val jsonObj = jsonArray.getJSONObject(index)
if (!jsonObj.has(mNotificationUgc?.value)) {
Utils.log("ugc type error")
return
}
val styleEntityJson = jsonObj.getJSONObject(mNotificationUgc!!.value)
val styleEntity = GsonUtils.fromJson(styleEntityJson.toString(), NotificationStyleEntity::class.java)
val drawableId = resources.getIdentifier(styleEntity.image, "drawable", requireContext().packageName)
notificationIv.setImageDrawable(ContextCompat.getDrawable(requireContext(), drawableId))
notificationTitle.text = styleEntity.title
notificationContent.text = styleEntity.content.fromHtml()
if (index == 0) {
closeIv.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_notification_close_1))
} else {
activateTv.background = ContextCompat.getDrawable(requireContext(), R.drawable.bg_notification_open_btn_style_1)
activateTv.text = "优雅的开启"
}
activateTv.setOnClickListener {
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击立即开启")
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击立即开启")
dismiss()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//这种方案适用于 API 26, 即8.0含8.0)以上可以用
@ -63,9 +80,10 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
}
}
laterTv.setOnClickListener {
closeIv.setOnClickListener {
dismiss()
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击以后再说")
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击关闭")
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击关闭")
}
dialog?.setCanceledOnTouchOutside(true)
@ -81,10 +99,30 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
override fun trackWithBasicDeviceInfo() = true
private fun getJsonFromAssets(): String? {
val stringBuilder = StringBuilder()
var bufferedReader: BufferedReader? = null
var inputStreamReader: InputStreamReader? = null
try {
inputStreamReader = InputStreamReader(requireContext().assets.open("notification_style.json"))
bufferedReader = BufferedReader(inputStreamReader)
var line: String?
while (bufferedReader.readLine().also { line = it } != null) {
stringBuilder.append(line)
}
} catch (e: IOException) {
e.printStackTrace()
} finally {
inputStreamReader?.close()
bufferedReader?.close()
}
return stringBuilder.toString()
}
companion object {
@JvmStatic
fun getInstance(hint: NotificationHint) = NotificationHintDialogFragment().apply {
mNotificationHint = hint
fun getInstance(ugc: NotificationUgc) = NotificationHintDialogFragment().apply {
mNotificationUgc = ugc
}
}
}

View File

@ -4,51 +4,80 @@ import android.annotation.SuppressLint
import android.app.Application
import android.os.Bundle
import android.text.Html
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.*
import android.view.animation.AnimationUtils
import android.widget.EditText
import android.widget.TextView
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import butterknife.BindView
import butterknife.ButterKnife
import butterknife.OnClick
import com.gh.base.fragment.BaseDialogFragment
import com.gh.common.AppExecutor
import com.gh.common.constant.Config
import com.gh.common.history.HistoryHelper
import com.gh.common.repository.ReservationRepository
import com.gh.common.util.*
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.NotificationUgc
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import org.json.JSONArray
import org.json.JSONObject
// 预约弹窗
class ReserveDialogFragment
: BaseDialogFragment() {
: BaseDialogFragment(), KeyboardHeightObserver {
// : BaseTrackableDialogFragment() {
@BindView(R.id.reserve_hint_tv)
lateinit var reserveHintTv: TextView
@BindView(R.id.reserve_content_tv)
lateinit var reserveContentTv: TextView
@BindView(R.id.reserve_completed_content_tv)
lateinit var reserveCompletedContentTv: TextView
@BindView(R.id.mobile_et)
lateinit var mobileEt: EditText
@BindView(R.id.reserve_container)
lateinit var reserveContainer: View
@BindView(R.id.reserve_completed_container)
lateinit var reserveCompletedContainer: View
@BindView(R.id.customizable_btn)
lateinit var customizableBtn: TextView
@BindView(R.id.content_container)
lateinit var contentContainer: View
@BindView(R.id.mobile_index_container)
lateinit var mobileIndexContainer: View
@BindView(R.id.mobile_index_reserve)
lateinit var mobileIndexReserve: TextView
@BindView(R.id.mobile_index_user)
lateinit var mobileIndexUser: TextView
@BindView(R.id.mobile_et_delete)
lateinit var mobileEtDelete: View
@BindView(R.id.layout_container)
lateinit var layoutContainer: View
private lateinit var mViewModel: ReserveViewModel
private var mSuccessCallback: SuccessCallback? = null
@ -57,10 +86,19 @@ class ReserveDialogFragment
private var mGameId: String = ""
private var mGameName: String = ""
private var mKeyboardHeightProvider: KeyboardHeightProvider? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mViewModel = viewModelProvider()
mKeyboardHeightProvider = KeyboardHeightProvider(activity)
mKeyboardHeightProvider?.start()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -81,11 +119,14 @@ class ReserveDialogFragment
super.onViewCreated(view, savedInstanceState)
ButterKnife.bind(this, view)
val reserveContent = "游戏上线,您将<font color='#ff4147'>免费</font>收到短信提醒"
val reserveContent = "游戏上线,您将收到<font color='#1383EB'>免费短信</font>提醒"
reserveContentTv.text = Html.fromHtml(reserveContent)
mobileEt.setText(UserManager.getInstance().userInfoEntity.mobile)
mobileEt.setSelection(mobileEt.text.length)
mobileEt.setTextChangedListener { s, _, _, _ ->
mobileIndexContainer.visibility = View.GONE
mobileEtDelete.goneIf(s.trim().isEmpty())
}
mViewModel.reservation.observeNonNull(this) {
if (it.success) {
@ -94,6 +135,11 @@ class ReserveDialogFragment
HistoryHelper.insertGameEntity(mGame!!)
}
}
mViewModel.reserveMobile.observe(viewLifecycleOwner, Observer {
setMobileIndexHint(it)
})
dialog?.setCanceledOnTouchOutside(true)
}
@ -123,18 +169,57 @@ class ReserveDialogFragment
}
}
private fun setMobileIndexHint(reserveMobile: String?) {
var userMobile = UserManager.getInstance().userInfoEntity?.mobile
if (reserveMobile == userMobile) userMobile = null
if (!reserveMobile.isNullOrEmpty()) {
mobileIndexReserve.visibility = View.VISIBLE
mobileIndexReserve.text = reserveMobile
} else {
mobileIndexReserve.visibility = View.GONE
}
if (!userMobile.isNullOrEmpty()) {
mobileIndexUser.visibility = View.VISIBLE
mobileIndexUser.text = userMobile
} else {
mobileIndexUser.visibility = View.GONE
}
mobileIndexContainer.goneIf(mobileIndexUser.visibility == View.GONE && mobileIndexReserve.visibility == View.GONE)
if (mobileIndexContainer.visibility ==View.VISIBLE) {
mobileIndexContainer.animation = AnimationUtils.loadAnimation(requireContext(), R.anim.reserve_dialog_index_anim)
}
}
@OnClick(R.id.reserve_with_mobile_btn,
R.id.reserve_without_mobile_btn,
R.id.content_container,
R.id.close_btn,
R.id.customizable_btn)
R.id.customizable_btn,
R.id.mobile_index_reserve,
R.id.mobile_index_user,
R.id.mobile_et_delete,
R.id.mobile_et,
R.id.layout_container)
fun onClick(view: View) {
when (view.id) {
R.id.reserve_without_mobile_btn -> {
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击无手机号预约")
if (mobileIndexContainer.visibility == View.VISIBLE) {
mobileIndexContainer.visibility = View.GONE
return
}
mViewModel.reserve(gameId = mGameId, gameName = mGameName)
}
R.id.reserve_with_mobile_btn -> {
if (mobileIndexContainer.visibility == View.VISIBLE) {
mobileIndexContainer.visibility = View.GONE
return
}
val mobile = mobileEt.text.toString()
if (mobile.length < 11 || !mobile.startsWith("1")) {
Utils.toast(context, "手机号格式错误,请检查并重新输入")
@ -148,7 +233,65 @@ class ReserveDialogFragment
R.id.close_btn -> {
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击关闭")
dismissAllowingStateLoss()
AppExecutor.uiExecutor.executeWithDelay(Runnable {
NotificationHelper.showNotificationHintDialog(NotificationUgc.RESERVE_GAME)
}, 1000)
}
R.id.content_container -> {
mobileIndexContainer.visibility = View.GONE
}
R.id.mobile_index_reserve -> {
mobileEt.setText(mobileIndexReserve.text.toString())
mobileEt.setSelection(mobileEt.text.length)
mobileIndexContainer.visibility = View.GONE
}
R.id.mobile_index_user -> {
mobileEt.setText(mobileIndexUser.text.toString())
mobileEt.setSelection(mobileEt.text.length)
mobileIndexContainer.visibility = View.GONE
}
R.id.mobile_et_delete -> {
mobileEt.setText("")
}
R.id.mobile_et -> {
mobileIndexContainer.visibility = View.GONE
}
R.id.layout_container -> {
dismissAllowingStateLoss()
}
}
}
override fun onResume() {
super.onResume()
if (HaloApp.getInstance().mCacheKeyboardHeight > 0) {
val attributes = dialog?.window?.attributes
val heightPixels = requireContext().resources.displayMetrics.heightPixels
val mCacheKeyboardHeight = HaloApp.getInstance().mCacheKeyboardHeight
val statusBarHeight = DisplayUtils.getStatusBarHeight(requireContext().resources)
dialog?.window?.attributes?.height = heightPixels - mCacheKeyboardHeight - statusBarHeight
attributes?.gravity = Gravity.TOP
dialog?.window?.attributes = attributes
}
mKeyboardHeightProvider?.setKeyboardHeightObserver(this)
}
override fun onPause() {
super.onPause()
mKeyboardHeightProvider?.setKeyboardHeightObserver(null)
}
override fun onDestroy() {
super.onDestroy()
mKeyboardHeightProvider?.close()
}
override fun onKeyboardHeightChanged(height: Int, orientation: Int) {
if (height > 0) {
val attributes = dialog?.window?.attributes
attributes?.gravity = Gravity.CENTER
dialog?.window?.attributes = attributes
HaloApp.getInstance().mCacheKeyboardHeight = height
}
}
@ -170,6 +313,12 @@ class ReserveDialogFragment
class ReserveViewModel(application: Application) : AndroidViewModel(application) {
val reservation = MutableLiveData<Reservation>()
val reserveMobile = MutableLiveData<String>()
init {
getAppointmentMobile()
}
@SuppressLint("CheckResult")
fun reserve(gameId: String, gameName: String, mobile: String = "") {
@ -201,5 +350,30 @@ class ReserveViewModel(application: Application) : AndroidViewModel(application)
})
}
@SuppressLint("CheckResult")
private fun getAppointmentMobile() {
RetrofitManager.getInstance(getApplication()).api
.getAppointmentMobile(UserManager.getInstance().userId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
var mobile: String? = null
tryCatchInRelease {
val jsonArray = JSONArray(data.string())
if (jsonArray.length() > 0) {
mobile = jsonArray.get(0).toString()
}
}
reserveMobile.postValue(mobile)
}
override fun onFailure(exception: Exception) {
reserveMobile.postValue(null)
}
})
}
class Reservation(var success: Boolean = false, var withMobile: Boolean = false, var boundWechat: Boolean = false)
}

View File

@ -15,5 +15,11 @@ data class ExposureEntity(
val sequence: Int? = 0,
val platform: String? = "",
val downloadType: String? = "",
val downloadCompleteType: String? = ""
val downloadCompleteType: String? = "",
// 统计启动弹窗相关数据用的 (ugly)
@SerializedName("dialog_id")
var welcomeDialogId: String? = "",
@SerializedName("link_title")
var welcomeDialogLinkTitle: String? = ""
) : Parcelable

View File

@ -39,7 +39,10 @@ data class ExposureEvent(
sequence = gameEntity?.sequence,
platform = gameEntity?.platform,
downloadType = gameEntity?.downloadType,
downloadCompleteType = gameEntity?.downloadCompleteType),
downloadCompleteType = gameEntity?.downloadCompleteType,
// ugly
welcomeDialogId = gameEntity?.welcomeDialogId ?: eTrace?.firstOrNull()?.payload?.welcomeDialogId,
welcomeDialogLinkTitle = gameEntity?.welcomeDialogTitle ?: eTrace?.firstOrNull()?.payload?.welcomeDialogLinkTitle),
source = source,
eTrace = eTrace,
event = event).apply { gameEntity?.exposureEvent = this }

View File

@ -1,17 +1,19 @@
package com.gh.common.filter
import android.annotation.SuppressLint
import com.gh.common.AppExecutor
import com.gh.common.constant.Constants
import com.gh.common.util.SPUtils
import com.gh.common.util.debounceActionWithInterval
import com.gh.common.util.toJson
import com.gh.common.util.toObject
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Function
import io.reactivex.schedulers.Schedulers
object RegionSettingHelper {
@ -49,7 +51,7 @@ object RegionSettingHelper {
list
}
fun shouldGameOfThisCategoryUseMirrorInfo(category: String) : Boolean {
fun shouldGameOfThisCategoryUseMirrorInfo(category: String): Boolean {
return if (mChannelControl == null || mChannelControl?.effect == false || !isUserUsedLessThan24Hours()) {
false
} else {
@ -60,23 +62,26 @@ object RegionSettingHelper {
@SuppressLint("CheckResult")
@JvmStatic
fun getRegionSetting() {
RetrofitManager.getInstance(HaloApp.getInstance().application)
.sensitiveApi
.getRegionSetting(HaloApp.getInstance().channel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<RegionSetting>() {
override fun onSuccess(data: RegionSetting) {
updateSettingsInMemory(data)
SPUtils.setString(SP_SETTING, data.toJson())
}
override fun onFailure(exception: Exception) {
SPUtils.getString(SP_SETTING).toObject<RegionSetting>()?.let {
updateSettingsInMemory(it)
debounceActionWithInterval(R.string.name, 3000) {
// 使用默认的 Schdulers.io() 可能会触发 OOM
RetrofitManager.getInstance(HaloApp.getInstance().application)
.sensitiveApi
.getRegionSetting(HaloApp.getInstance().channel)
.subscribeOn(AppExecutor.cachedScheduler)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<RegionSetting>() {
override fun onSuccess(data: RegionSetting) {
updateSettingsInMemory(data)
SPUtils.setString(SP_SETTING, data.toJson())
}
}
})
override fun onFailure(exception: Exception) {
SPUtils.getString(SP_SETTING).toObject<RegionSetting>()?.let {
updateSettingsInMemory(it)
}
}
})
}
}
private fun updateSettingsInMemory(data: RegionSetting) {

View File

@ -15,7 +15,7 @@ import com.gh.gamecenter.room.converter.*
import com.gh.gamecenter.room.dao.*
import com.halo.assistant.HaloApp
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 6, exportSchema = false)
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 7, exportSchema = false)
@TypeConverters(CountConverter::class,
CommunityConverter::class,
TimeConverter::class,
@ -63,12 +63,19 @@ abstract class HistoryDatabase : RoomDatabase() {
}
}
val MIGRATION_6_7: Migration = object : Migration(6, 7) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("Alter TABLE HistoryGameEntity add iconSubscript TEXT DEFAULT ''")
}
}
val instance by lazy {
Room.databaseBuilder(HaloApp.getInstance().application, HistoryDatabase::class.java, "USER_TRACK_HISTORY_DATABASE")
.addMigrations(MIGRATION_2_3)
.addMigrations(MIGRATION_3_4)
.addMigrations(MIGRATION_4_5)
.addMigrations(MIGRATION_5_6)
.addMigrations(MIGRATION_6_7)
.build()
}
}

View File

@ -41,7 +41,8 @@ object HistoryHelper {
historyGame.id = updateEntity.id
historyGame.brief = updateEntity.brief
historyGame.des = ""
historyGame.icon = updateEntity.icon
historyGame.icon = updateEntity.rawIcon ?: updateEntity.icon
historyGame.iconSubscript = historyGame.iconSubscript
historyGame.name = updateEntity.name
historyGame.tagStyle = updateEntity.tagStyle
historyGame.tag = updateEntity.tag
@ -55,11 +56,11 @@ object HistoryHelper {
historyGame.id = gameEntity.id
historyGame.brief = gameEntity.brief
historyGame.des = gameEntity.des
historyGame.icon = gameEntity.icon
historyGame.icon = gameEntity.rawIcon ?: gameEntity.icon
historyGame.iconSubscript = gameEntity.iconSubscript
historyGame.name = gameEntity.name
historyGame.tagStyle = gameEntity.tagStyle
historyGame.tag = gameEntity.getTag()
historyGame.isLibaoExist = gameEntity.isLibaoExists
return historyGame
}
@ -109,6 +110,7 @@ object HistoryHelper {
clearHtmlFormatCompletely().
replace(" +".toRegex()," ")
articleEntity.count = articleDetailEntity.count
articleDetailEntity.community.id = articleDetailEntity.communityId
articleEntity.community = articleDetailEntity.community
articleEntity.time = articleDetailEntity.time
articleEntity.title = articleDetailEntity.title

View File

@ -0,0 +1,5 @@
package com.gh.common.iinterface
interface IScrollable {
fun scrollToTop()
}

View File

@ -45,7 +45,7 @@ object ImManager {
HaloApp.getInstance().application,
ImReceiver.UNIQUE_BROADCAST_ACTION,
IM_KEY,
UserManager.getInstance().userInfoEntity.name + "(" + UserManager.getInstance().userId + ")",
UserManager.getInstance().userInfoEntity?.name + "(" + UserManager.getInstance().userId + ")",
UserManager.getInstance().userId)
shouldShowFloatingWindow = SPUtils.getBoolean(SP_FLOATING_WINDOW_KEY + UserManager.getInstance().userId)
@ -75,11 +75,11 @@ object ImManager {
try {
SPUtils.setBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId, false)
shouldShowFloatingWindowDot = false
val chatHelper = KfStartHelper(activity, UserManager.getInstance().userInfoEntity.icon, inputContent, requestCode)
val chatHelper = KfStartHelper(activity, UserManager.getInstance().userInfoEntity?.icon, inputContent, requestCode)
chatHelper.initSdkChat(
ImReceiver.UNIQUE_BROADCAST_ACTION,
IM_KEY,
UserManager.getInstance().userInfoEntity.name + "(" + UserManager.getInstance().userId + ")"
UserManager.getInstance().userInfoEntity?.name + "(" + UserManager.getInstance().userId + ")"
+ "[" + BuildConfig.VERSION_NAME + "]",
UserManager.getInstance().userId)
} catch (e: Exception) {

View File

@ -1,8 +1,11 @@
package com.gh.common.loghub
import android.app.Application
import androidx.annotation.Keep
import com.aliyun.sls.android.sdk.model.Log
import com.aliyun.sls.android.sdk.model.LogGroup
import com.gh.common.exposure.ExposureEntity
import com.gh.common.exposure.meta.Meta
import com.gh.loghub.LoghubHelper
import org.json.JSONObject
import java.util.concurrent.Executors
@ -43,6 +46,23 @@ object LoghubUtils {
}
}
@JvmStatic
fun log(jsonString: String, logStore: String, forcedUpload: Boolean) {
loghubEventExecutor.execute {
try {
val event = LoghubEvent(time = (System.currentTimeMillis() / 1000L).toString(), content = jsonString, logStore = logStore)
loghubEventSet.add(event)
loghubEventDao.insert(event)
} catch (e: Exception) {
e.printStackTrace()
}
if (forcedUpload || loghubEventSet.size >= STORE_SIZE) {
commitSavedLoghubEvents()
}
}
}
private fun uploadLogGroup(logGroup: LogGroup, logStore: String) {
LoghubHelper.getInstance().uploadLogGroup(logGroup, logStore)
}
@ -86,4 +106,12 @@ object LoghubUtils {
}
}
}
}
@Keep
data class SimpleLogContainerEntity(
var event: String? = null,
var action: String? = null,
var meta: Meta? = null,
var payload: ExposureEntity? = null,
var timestamp: Long? = 0)

View File

@ -5,14 +5,17 @@ object SyncFieldConstants {
// 是否点赞
const val ANSWER_VOTE = "ANSWER_VOTE"
const val ARTICLE_VOTE = "ARTICLE_VOTE"
const val ARTICLE_COMMENT_VOTE = "ARTICLE_COMMENT_VOTE"
// 赞同数量
const val ANSWER_VOTE_COUNT = "ANSWER_VOTE_COUNT"
const val ARTICLE_VOTE_COUNT = "ARTICLE_VOTE_COUNT"
const val ARTICLE_COMMENT_VOTE_COUNT = "ARTICLE_COMMENT_VOTE_COUNT"
// 评论数量
const val ANSWER_COMMENT_COUNT = "ANSWER_COMMENT_COUNT"
const val ARTICLE_COMMENT_COUNT = "ARTICLE_COMMENT_COUNT"
const val ARTICLE_COMMENT_REPLY_COUNT = "ARTICLE_COMMENT_REPLY_COUNT"
// 回答数量
const val ANSWER_COUNT = "ANSWER_COUNT"

View File

@ -21,9 +21,7 @@ object ActivationHelper {
*/
@JvmStatic
fun sendActivationInfo() {
// 能获取到 IMEI 并且之前没发送过激活信息才发
if (!mHasSentActivatedInfo
&& Util_System_Phone_State.canGetImei(HaloApp.getInstance().application)) {
if (!mHasSentActivatedInfo) {
RetrofitManager.getInstance(HaloApp.getInstance().application)
.api.postActivationInfo()
.subscribeOn(Schedulers.io())

View File

@ -0,0 +1,6 @@
package com.gh.common.util
interface BiCallback<FIRST, SECOND> {
fun onFirst(first: FIRST)
fun onSecond(second: SECOND)
}

View File

@ -0,0 +1,9 @@
package com.gh.common.util
import com.gh.gamecenter.room.AppDatabase
import com.gh.gamecenter.room.dao.CommentDraftDao
import com.halo.assistant.HaloApp
object CommentDraftContainer {
val commentDraftDao: CommentDraftDao by lazy { AppDatabase.getInstance(HaloApp.getInstance().application).commentDraftDao() }
}

View File

@ -1,14 +1,19 @@
package com.gh.common.util
import android.content.Context
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import com.gh.common.util.CommentUtils.copyText
import com.gh.common.view.BugFixedPopupWindow
import com.gh.gamecenter.CommentDetailActivity
import com.gh.gamecenter.MessageDetailActivity
import com.gh.gamecenter.adapter.OnCommentCallBackListener
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.CommentEntity
import com.gh.gamecenter.entity.MeEntity
import com.gh.gamecenter.entity.Permissions
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.qa.comment.OnCommentOptionClickListener
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.lightgame.utils.Utils
@ -23,27 +28,29 @@ import retrofit2.HttpException
object CommentHelper {
@JvmStatic
fun showCommunityArticleCommentOptions(context: Context,
fun showCommunityArticleCommentOptions(view: View,
commentEntity: CommentEntity,
showConversation: Boolean,
articleId: String,
communityId: String,
listener: OnCommentCallBackListener?) {
showCommentOptions(context = context,
ignoreModerator: Boolean = false,
listener: OnCommentOptionClickListener?) {
showCommentOptions(view = view,
commentEntity = commentEntity,
showConversation = showConversation,
articleId = articleId,
communityId = communityId,
ignoreModerator = ignoreModerator,
listener = listener)
}
@JvmStatic
fun showAnswerCommentOptions(context: Context,
fun showAnswerCommentOptions(view: View,
commentEntity: CommentEntity,
showConversation: Boolean,
answerId: String,
listener: OnCommentCallBackListener?) {
showCommentOptions(context = context,
listener: OnCommentOptionClickListener?) {
showCommentOptions(view = view,
commentEntity = commentEntity,
showConversation = showConversation,
answerId = answerId,
@ -51,31 +58,41 @@ object CommentHelper {
}
@JvmStatic
fun showVideoCommentOptions(context: Context,
fun showVideoCommentOptions(view: View,
commentEntity: CommentEntity,
showConversation: Boolean,
videoId: String,
listener: OnCommentCallBackListener?) {
showCommentOptions(context = context,
isVideoAuthor: Boolean,
listener: OnCommentOptionClickListener?) {
showCommentOptions(view = view,
commentEntity = commentEntity,
showConversation = showConversation,
videoId = videoId,
isVideoAuthor = isVideoAuthor,
listener = listener)
}
private fun showCommentOptions(context: Context,
private fun showCommentOptions(view: View,
commentEntity: CommentEntity,
showConversation: Boolean,
articleId: String? = null,
communityId: String? = null,
answerId: String? = null,
videoId: String? = null,
listener: OnCommentCallBackListener? = null) {
ignoreModerator: Boolean = false,
isVideoAuthor: Boolean = false,
listener: OnCommentOptionClickListener? = null) {
val context = view.context
val dialogOptions = ArrayList<String>()
if (isVideoAuthor || (videoId != null && commentEntity.user.id == UserManager.getInstance().userId)) {
dialogOptions.add("删除评论")
}
dialogOptions.add("复制")
dialogOptions.add("投诉")
commentEntity.me?.let {
if (ignoreModerator) return@let
if (it.isModerator || (it.moderatorPermissions.hideAnswerComment > Permissions.GUEST
|| it.moderatorPermissions.topAnswerComment > Permissions.GUEST
|| it.moderatorPermissions.hideCommunityArticleComment > Permissions.GUEST
@ -88,55 +105,75 @@ object CommentHelper {
dialogOptions.add("查看对话")
}
DialogUtils.showListDialog(context, dialogOptions, null) {
when (it) {
"管理" -> showControlDialog(context, answerId, articleId, communityId, commentEntity, commentEntity.me!!)
val inflater = LayoutInflater.from(context)
val layout = inflater.inflate(R.layout.comment_more_option, null)
val popupWindow = BugFixedPopupWindow(layout,
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
val container = layout.findViewById<LinearLayout>(R.id.container)
for (text in dialogOptions) {
val item = inflater.inflate(R.layout.comment_more_option_item, container, false)
container.addView(item)
"复制" -> copyText(commentEntity.content, context)
val hitText = item.findViewById<TextView>(R.id.hint_text)
hitText.text = text
"投诉" -> {
context.ifLogin("回答详情-评论-投诉") {
showReportTypeDialog(context) { reportType ->
item.setOnClickListener {
popupWindow.dismiss()
listener?.onCommentOptionClick(commentEntity, text)
when (text) {
"管理" -> showControlDialog(context, answerId, articleId, communityId, commentEntity, commentEntity.me!!)
val commentListener = object : PostCommentUtils.PostCommentListener {
override fun postSuccess(response: JSONObject?) {
Utils.toast(context, "感谢您的投诉")
}
"复制" -> copyText(commentEntity.content, context)
override fun postFailed(error: Throwable?) {
if (error == null) {
Utils.toast(context, "投诉失败,请稍后重试")
} else {
Utils.toast(context, "投诉失败,${error.message}")
"投诉" -> {
context.ifLogin("回答详情-评论-投诉") {
showReportTypeDialog(context) { reportType ->
val commentListener = object : PostCommentUtils.PostCommentListener {
override fun postSuccess(response: JSONObject?) {
Utils.toast(context, "感谢您的投诉")
}
override fun postFailed(error: Throwable?) {
if (error == null) {
Utils.toast(context, "投诉失败,请稍后重试")
} else {
Utils.toast(context, "投诉失败,${error.message}")
}
}
}
}
if (answerId != null) {
PostCommentUtils.postAnswerReportData(context, commentEntity.id, answerId, reportType, commentListener)
} else if (articleId != null) {
PostCommentUtils.reportCommunityArticleComment(context, communityId, articleId, commentEntity.id, reportType, commentListener)
} else {
PostCommentUtils.reportVideoComment(context, videoId, commentEntity.id, reportType, commentListener)
if (answerId != null) {
PostCommentUtils.postAnswerReportData(context, commentEntity.id, answerId, reportType, commentListener)
} else if (articleId != null) {
PostCommentUtils.reportCommunityArticleComment(context, communityId, articleId, commentEntity.id, reportType, commentListener)
} else {
PostCommentUtils.reportVideoComment(context, videoId, commentEntity.id, reportType, commentListener)
}
}
}
}
}
"查看对话" -> {
if (answerId != null) {
context.startActivity(CommentDetailActivity
.getAnswerCommentIntent(context, commentEntity.id, answerId, null))
} else if (articleId != null) {
context.startActivity(CommentDetailActivity
.getCommunityArticleCommentIntent(context, articleId, commentEntity.id, communityId, null))
} else {
context.startActivity(CommentDetailActivity
.getVideoCommentIntent(context, commentEntity.id, videoId, null))
"查看对话" -> {
if (answerId != null) {
context.startActivity(CommentDetailActivity
.getAnswerCommentIntent(context, commentEntity.id, answerId, null))
} else if (articleId != null) {
context.startActivity(CommentDetailActivity
.getCommunityArticleCommentIntent(context, articleId, commentEntity.id, communityId, null))
} else {
context.startActivity(CommentDetailActivity
.getVideoCommentIntent(context, commentEntity.id, videoId, isVideoAuthor, null))
}
}
}
}
}
popupWindow.isTouchable = true
popupWindow.isFocusable = true
popupWindow.showAutoOrientation(view)
}
private fun showControlDialog(context: Context,

View File

@ -12,6 +12,8 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import com.gh.gamecenter.CommentDetailActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.viewholder.CommentViewHolder;
@ -38,7 +40,6 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import androidx.core.content.ContextCompat;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
@ -50,9 +51,13 @@ import retrofit2.HttpException;
public class CommentUtils {
public static void setCommentTime(TextView textView, long time) {
textView.setText(getCommentTime(time));
}
public static String getCommentTime(long timestamp) {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
try {
long day = time * 1000;
long day = timestamp * 1000;
String year = String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
format.applyPattern("yyyy");
String currentYear = format.format(day);
@ -63,35 +68,34 @@ public class CommentUtils {
int hour = (int) (min / (60 * 60));
if (hour == 0) {
if (min < 60) {
textView.setText("刚刚");
return "刚刚";
} else {
textView.setText(String.format(Locale.getDefault(), "%d分钟前", (int) (min / 60)));
return String.format(Locale.getDefault(), "%d分钟前", (int) (min / 60));
}
} else {
textView.setText(String.format(Locale.getDefault(), "%d小时前", hour));
return String.format(Locale.getDefault(), "%d小时前", hour);
}
} else if (day >= today - 86400 * 1000 && day < today) {
format.applyPattern("HH:mm");
textView.setText("昨天 ");
return "昨天 ";
} else if (day >= today - 86400 * 1000 * 7 && day < today - 86400 * 1000) {
format.applyPattern("HH:mm");
long days = (today - day) / 86400000 + 1;
textView.setText(String.format(Locale.getDefault(), "%d天前 ", days));
return String.format(Locale.getDefault(), "%d天前 ", days);
} else if (day < today - 86400 * 1000 * 7 && year.equals(currentYear)) {
format.applyPattern("MM-dd");
textView.setText(format.format(day));
return format.format(day);
} else {
format.applyPattern("yyyy-MM-dd");
textView.setText(format.format(day));
return format.format(day);
}
} catch (ParseException e) {
e.printStackTrace();
format.applyPattern("yyyy-MM-dd");
textView.setText(format.format(time * 1000));
return format.format(timestamp * 1000);
}
}
public static void showReportDialog(final CommentEntity commentEntity,
final Context context,
final boolean showConversation,

View File

@ -6,7 +6,7 @@ import android.widget.LinearLayout;
import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.gamecenter.ViewImageActivity;
import com.gh.gamecenter.ImageViewerActivity;
import java.util.ArrayList;
import java.util.List;
@ -93,7 +93,7 @@ public class ConcernContentUtils {
break;
}
imageView.setOnClickListener(v -> {
Intent checkIntent = ViewImageActivity.getViewImageIntent(context, (ArrayList<String>) list, position, entrance);
Intent checkIntent = ImageViewerActivity.getIntent(context, (ArrayList<String>) list, position, entrance);
context.startActivity(checkIntent);
});
return imageView;

View File

@ -20,12 +20,13 @@ import java.util.Map;
public class DataLogUtils {
// 轮播图
public static void uploadLunbotuLog(Context context, String type, String text, String index, String source) {
public static void uploadLunbotuLog(Context context, String type, String text, String title, String index, String source) {
Map<String, Object> map = new HashMap<>();
map.put("index", index);
map.put("type", type);
map.put("text", text);
map.put("source", source);
map.put("slide_title", title);
uploadLog(context, "slide", map);
}

View File

@ -141,7 +141,7 @@ public class DataUtils {
@Override
public void onFailure(String s) {
Utils.log(s);
MtaHelper.onEventWithBasicDeviceInfo("开发辅助", "GID 获取异常", s);
}
});
}

View File

@ -6,6 +6,8 @@ import android.view.View;
import com.gh.common.constant.Config;
import com.gh.common.repository.ReservationRepository;
import com.gh.common.view.DownloadProgressBar;
import com.gh.common.xapk.XapkInstaller;
import com.gh.common.xapk.XapkUnzipStatus;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.viewholder.DetailViewHolder;
@ -13,7 +15,6 @@ import com.gh.gamecenter.entity.LinkEntity;
import com.gh.gamecenter.entity.PluginLocation;
import com.gh.gamecenter.manager.PackagesManager;
import com.lightgame.download.DownloadEntity;
import com.lightgame.utils.Utils;
/**
* Created by khy on 27/06/17.
@ -112,8 +113,18 @@ public class DetailDownloadUtils {
}
public static void detailInvalidate(DetailViewHolder viewHolder) {
viewHolder.mDownloadPb.setProgress((int) (viewHolder.downloadEntity.getPercent() * 10));
DownloadEntity downloadEntity = viewHolder.downloadEntity;
String xapkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
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.setDownloadType(DownloadProgressBar.DownloadType.XAPK_UNZIPPING);
return;
}
viewHolder.mDownloadPb.setProgress((int) (viewHolder.downloadEntity.getPercent() * 10));
switch (downloadEntity.getStatus()) {
case downloading:
case pause:

View File

@ -11,6 +11,8 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.Nullable;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.Util_System_Phone_State;
import com.tencent.stat.StatConfig;
@ -222,8 +224,7 @@ public class DeviceUtils {
// get sim
public static String getSim(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String imsi = tm.getSubscriberId();
String imsi = getTelephonySubscriberId(context);
if (imsi == null) {
return "";
}
@ -239,6 +240,12 @@ public class DeviceUtils {
return "";
}
@Nullable
public static String getTelephonySubscriberId(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getSubscriberId();
}
// ping domain
public static String ping(String domain) {
try {

View File

@ -29,6 +29,12 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.gh.common.AppExecutor;
import com.gh.common.constant.Config;
@ -39,8 +45,10 @@ import com.gh.common.view.LimitHeightLinearLayout;
import com.gh.common.view.MaxHeightNestedScrollView;
import com.gh.gamecenter.AboutActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.SuggestionActivity;
import com.gh.gamecenter.WebActivity;
import com.gh.gamecenter.adapter.viewholder.PrivacyPolicyItemViewHolder;
import com.gh.gamecenter.databinding.DialogOverseaConfirmationBinding;
import com.gh.gamecenter.databinding.ImprintContentItemBinding;
import com.gh.gamecenter.databinding.PrivacyItemBinding;
import com.gh.gamecenter.entity.ApkEntity;
@ -48,22 +56,19 @@ import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
import com.gh.gamecenter.entity.SettingsEntity;
import com.gh.gamecenter.entity.TrackableEntity;
import com.gh.gamecenter.suggest.SuggestType;
import com.halo.assistant.HaloApp;
import com.halo.assistant.fragment.SettingsFragment;
import com.lightgame.adapter.BaseRecyclerAdapter;
import com.lightgame.download.DownloadEntity;
import com.lightgame.utils.AppManager;
import com.lightgame.utils.Util_System_Keyboard;
import com.lightgame.utils.Utils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
public class DialogUtils {
public static Dialog showWaitDialog(Context context, String msg) {
@ -80,7 +85,6 @@ public class DialogUtils {
return dialog;
}
public static void showInstallHintDialog(Context context, final ConfirmListener cmListener) {
context = checkDialogContext(context);
@ -539,8 +543,6 @@ public class DialogUtils {
clListener.onCancel();
});
dialog.show();
}
@ -584,7 +586,6 @@ public class DialogUtils {
dialog.setContentView(contentView);
dialog.setCancelable(false);
dialog.show();
}
/**
@ -665,7 +666,6 @@ public class DialogUtils {
TextPaint tp = mesage.getPaint();
tp.setFakeBoldText(true);
}
}
public static void showSignDialog(Context context, String title, CharSequence message, CharSequence message2
@ -1099,6 +1099,21 @@ public class DialogUtils {
final ConfirmListener cmListener,
final CancelListener clListener,
TrackableEntity trackableEntity) {
return showTrackableDialog(context, false, title, message, positive, negative, cmListener, clListener, trackableEntity);
}
/**
* @param useRoundedCornerStyle 使用圆角样式
*/
public static Dialog showTrackableDialog(Context context,
boolean useRoundedCornerStyle,
String title,
CharSequence message,
String positive,
String negative,
final ConfirmListener cmListener,
final CancelListener clListener,
TrackableEntity trackableEntity) {
context = checkDialogContext(context);
final TrackableDialog dialog = new TrackableDialog(context,
@ -1110,7 +1125,17 @@ public class DialogUtils {
trackableEntity.getKeyBackValue(),
trackableEntity.getLogShowEvent());
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_alert, null);
View contentView;
if (useRoundedCornerStyle) {
contentView = LayoutInflater.from(context).inflate(R.layout.dialog_alert_with_rounded_corner, null);
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
} else {
contentView = LayoutInflater.from(context).inflate(R.layout.dialog_alert, null);
}
TextView contentTv = contentView.findViewById(R.id.dialog_content);
TextView titleTv = contentView.findViewById(R.id.dialog_title);
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
@ -1265,6 +1290,45 @@ public class DialogUtils {
}
}
// 海外下载地址弹窗
public static void showOverseaDownloadDialog(Context context, GameEntity gameEntity, @NonNull ConfirmListener listener) {
context = checkDialogContext(context);
if (gameEntity.getOverseasAddressDialog() == null
|| gameEntity.getApk().size() == 0
|| !gameEntity.getOverseasAddressDialog().isEnable()) {
listener.onConfirm();
} else {
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
DialogOverseaConfirmationBinding binding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.dialog_oversea_confirmation, null, false);
View contentView = binding.getRoot();
binding.setGame(gameEntity);
binding.urlTv.setText(gameEntity.getOverseasAddressDialog().getLink());
binding.closeIv.setOnClickListener(v -> dialog.dismiss());
binding.downloadBtn.setText("下载(" + gameEntity.getApk().get(0).getSize() + "");
binding.downloadBtn.setOnClickListener(v -> {
listener.onConfirm();
dialog.dismiss();
});
if ("show&download".equals(gameEntity.getOverseasAddressDialog().getStatus())) {
gameEntity.getApk().get(0).setUrl(gameEntity.getOverseasAddressDialog().getLink());
}
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
}
public static void showImprintDialog(Context context, GameEntity gameEntity, String titleName) {
context = checkDialogContext(context);
Dialog dialog = new Dialog(context, R.style.full_dialog);
@ -1341,6 +1405,41 @@ public class DialogUtils {
dialog.show();
}
public static void showStopServerExplanationDialog(Context context, String content, String gameName) {
context = checkDialogContext(context);
final Dialog dialog = new TrackableDialog(context, R.style.GhAlertDialog, "评论说明弹窗", "弹窗", gameName, null, null, true);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_stop_service_explanation, null);
TextView contentTv = contentView.findViewById(R.id.contentTv);
MaxHeightNestedScrollView scrollView = contentView.findViewById(R.id.scrollView);
if (TextUtils.isEmpty(content)) {
content = context.getString(R.string.rating_protection);
}
contentTv.setText(content);
TextView ok = contentView.findViewById(R.id.dialog_ok);
scrollView.setScrollChangedListener((l, t, oldl, oldt) -> {
MtaHelper.onEvent("评论说明弹窗", "滑动内容", gameName);
});
ok.setOnClickListener(v -> {
MtaHelper.onEvent("评论说明弹窗", "弹窗", "点击我知道了");
MtaHelper.onEvent("评论说明弹窗", "点击我知道了", gameName);
dialog.dismiss();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
WindowManager.LayoutParams params = window.getAttributes();
params.width = context.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(60f);
window.setAttributes(params);
}
}
public static void showPluggableNeverRemindDialog(Context context, String nameAndPlatform, @NonNull ConfirmListener listener) {
context = checkDialogContext(context);
@ -1368,6 +1467,142 @@ public class DialogUtils {
dialog.show();
}
public static void showRegulationTestDialog(Context context, @NonNull ConfirmListener confirmListener, @NonNull CancelListener cancelListener) {
context = checkDialogContext(context);
final Dialog dialog = new TrackableDialog(
context,
R.style.GhAlertDialog,
"礼仪考试",
"礼仪考试弹窗",
null, null, null,
true);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_regulation_test, null);
View cancelBtn = contentView.findViewById(R.id.cancel);
View confirmBtn = contentView.findViewById(R.id.confirm);
View linkTv = contentView.findViewById(R.id.link);
Context finalContext = context;
linkTv.setOnClickListener(v -> {
MtaHelper.onEvent("礼仪考试", "礼仪考试弹窗", "了解更多");
DirectUtils.directToArticle(finalContext, "5f4477be25e07e19be4e2a22", "(礼仪测试弹窗)");
});
cancelBtn.setOnClickListener(v -> {
cancelListener.onCancel();
MtaHelper.onEvent("礼仪考试", "礼仪考试弹窗", "跳过");
dialog.dismiss();
});
Context finalContext1 = context;
confirmBtn.setOnClickListener(v -> {
Util_System_Keyboard.hideSoftKeyboard((Activity) finalContext1);
MtaHelper.onEvent("礼仪考试", "礼仪考试弹窗", "确定");
confirmListener.onConfirm();
dialog.dismiss();
});
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
public static void showUnzipFailureDialog(Context context, DownloadEntity downloadEntity) {
final Context activityContext = checkDialogContext(context);
final Dialog dialog = new Dialog(activityContext, R.style.GhAlertDialog);
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawableResource(android.R.color.transparent);
}
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_unzip_failure, null);
View cancelBtn = contentView.findViewById(R.id.cancel);
View confirmBtn = contentView.findViewById(R.id.confirm);
cancelBtn.setOnClickListener(v -> {
dialog.dismiss();
});
confirmBtn.setOnClickListener(v -> {
dialog.dismiss();
String hint = "" + downloadEntity.getName() + "》游戏安装包解压失败,问题反馈:";
SuggestionActivity.startSuggestionActivity(activityContext, SuggestType.normal, null, hint);
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
public static void showNoticeDialog(Context context, String title, String content, @NonNull ConfirmListener listener) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_notice, null);
TextView titleTv = contentView.findViewById(R.id.dialog_title);
TextView contentTv = contentView.findViewById(R.id.dialog_content);
if (title == null) {
titleTv.setVisibility(View.GONE);
} else {
titleTv.setVisibility(View.VISIBLE);
titleTv.setText(title);
}
contentTv.setText(content);
contentView.findViewById(R.id.dialog_ok).setOnClickListener(v -> {
listener.onConfirm();
dialog.dismiss();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
public static void showUploadVideoChangeLabelDialog(Context context, @NonNull ConfirmListener confirmListener) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_upload_video_change_label, null);
View cancelBtn = contentView.findViewById(R.id.cancel);
View confirmBtn = contentView.findViewById(R.id.confirm);
cancelBtn.setOnClickListener(v -> {
dialog.dismiss();
});
confirmBtn.setOnClickListener(v -> {
confirmListener.onConfirm();
dialog.dismiss();
});
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
/**
* @param context may be is application context
* @return activity context

View File

@ -12,6 +12,7 @@ import com.gh.base.ToolBarActivity
import com.gh.base.fragment.BaseFragment_TabLayout
import com.gh.common.AppExecutor
import com.gh.common.constant.Config
import com.gh.common.constant.Constants
import com.gh.common.exposure.ExposureEvent
import com.gh.common.exposure.ExposureEvent.Companion.createEvent
import com.gh.common.exposure.ExposureManager.log
@ -25,10 +26,14 @@ import com.gh.gamecenter.download.DownloadFragment.Companion.INDEX_UPDATE
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.eventbus.EBReuse
import com.gh.gamecenter.eventbus.EBSkip
import com.gh.gamecenter.forum.detail.ForumDetailActivity
import com.gh.gamecenter.fragment.MainWrapperFragment
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity
import com.gh.gamecenter.game.upload.GameSubmissionActivity
import com.gh.gamecenter.gamedetail.GameDetailFragment
import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity
import com.gh.gamecenter.gamedetail.history.HistoryApkListActivity
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.mygame.PlayedGameActivity
import com.gh.gamecenter.personalhome.UserHomeActivity
@ -39,17 +44,24 @@ import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
import com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
import com.gh.gamecenter.qa.subject.CommunitySubjectActivity
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.servers.GameServersActivity
import com.gh.gamecenter.subject.SubjectActivity
import com.gh.gamecenter.suggest.SuggestType
import com.gh.gamecenter.tag.TagsActivity
import com.gh.gamecenter.video.data.VideoDataActivity
import com.gh.gamecenter.video.detail.VideoDetailActivity
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
import com.gh.gamecenter.video.game.GameVideoActivity
import com.gh.gamecenter.video.videomanager.VideoManagerActivity
import com.halo.assistant.HaloApp
import com.lightgame.utils.Util_System_ClipboardManager
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import org.greenrobot.eventbus.EventBus
import retrofit2.HttpException
/**
* 跳转用的方法
@ -86,9 +98,6 @@ object DirectUtils {
}
}
/**
* 跳转到特定页面,只支持App内部跳转
*/
@JvmStatic
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String) {
directToLinkPage(context, linkEntity, entrance, path, null)
@ -153,7 +162,10 @@ object DirectUtils {
"answer", "社区回答" -> directToAnswerDetail(context, linkEntity.link ?: "", entrance, path)
"community", "问答社区" -> directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
"community", "问答社区" -> {
if (linkEntity.link.isNullOrEmpty()) return
directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
}
"community_article", "社区文章" -> directToCommunityArticle(context, linkEntity.community!!, linkEntity.link!!, entrance, path)
@ -185,11 +197,14 @@ object DirectUtils {
"category", "分类" -> directCategoryDirectory(context, linkEntity.link!!, linkEntity.text!!)
"block", "版块" -> {
directToBlock(context, SubjectRecommendEntity(
link = linkEntity.link,
text = linkEntity.text,
name = linkEntity.name,
display = linkEntity.display ?: Display()))
if (linkEntity.link.isNullOrEmpty()) return
directToBlock(context,
SubjectRecommendEntity(
link = linkEntity.link,
text = linkEntity.text,
name = linkEntity.name,
display = linkEntity.display ?: Display()),
entrance)
}
"column_collection", "专题合集" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
@ -224,6 +239,8 @@ object DirectUtils {
"game_upload", "游戏投稿" -> directGameUpload(context, entrance, path)
"bbs_detail" -> directForumDetail(context, linkEntity.link ?: "", entrance)
//"h5_game_center" -> directLetoGameCenter(context)
"" -> {
@ -244,7 +261,7 @@ object DirectUtils {
*/
@JvmStatic
fun directToQa(context: Context, text: String, id: String) {
// context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaId = id))
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_TO, QaActivity::class.java.simpleName)
bundle.putString(KEY_NAVIGATION_TITLE, text)
@ -257,7 +274,7 @@ object DirectUtils {
*/
@JvmStatic
fun directToQaCollection(context: Context, text: String, id: String) {
// context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaCollectionId = id))
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_TO, QaActivity::class.java.simpleName)
bundle.putString(KEY_NAVIGATION_TITLE, text)
@ -270,13 +287,52 @@ object DirectUtils {
*/
@JvmStatic
fun directToColumnCollection(context: Context, id: String, position: Int = -1, entrance: String, columnName: String = "") {
// context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance, columnName))
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_TO, ColumnCollectionDetailActivity::class.java.name)
bundle.putString(KEY_ENTRANCE, entrance)
bundle.putString(KEY_COLLECTION_ID,id)
bundle.putString(KEY_COLUMNNAME,columnName)
bundle.putInt(KEY_POSITION,position)
bundle.putString(KEY_COLLECTION_ID, id)
bundle.putString(KEY_COLUMNNAME, columnName)
bundle.putInt(KEY_POSITION, position)
jumpActivity(context, bundle)
}
/**
* 跳转至资讯文章列表
*/
@JvmStatic
fun directToGameNews(context: Context, gameId: String?, gameName: String?, entrance: String?) {
val bundle = Bundle()
bundle.putString(KEY_TO, GameNewsActivity::class.java.name)
bundle.putString(KEY_ENTRANCE, entrance)
bundle.putString(KEY_GAMEID, gameId)
bundle.putString(KEY_GAMENAME, gameName)
jumpActivity(context, bundle)
}
/**
* 跳转至游戏日历表
*/
@JvmStatic
fun directToGameServerCalendar(context: Context, gameId: String?) {
val bundle = Bundle()
bundle.putString(KEY_TO, ServersCalendarActivity::class.java.name)
bundle.putParcelable(GameEntity::class.java.simpleName, GameEntity().apply {
id = gameId ?: ""
})
bundle.putParcelable(GameDetailServer::class.java.simpleName, GameDetailServer())
bundle.putParcelable(MeEntity::class.java.simpleName, MeEntity())
jumpActivity(context, bundle)
}
/**
* 跳转至游戏历史版本页面
*/
@JvmStatic
fun directToHistoryApk(context: Context, gameId: String?) {
val bundle = Bundle()
bundle.putString(KEY_TO, HistoryApkListActivity::class.java.name)
bundle.putString(KEY_GAMEID, gameId)
jumpActivity(context, bundle)
}
@ -285,6 +341,7 @@ object DirectUtils {
*/
@JvmStatic
fun directToArticle(context: Context, id: String, entrance: String? = null) {
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, NewsDetailActivity::class.java.simpleName)
@ -327,14 +384,19 @@ object DirectUtils {
* 跳转到游戏详情
*/
@JvmStatic
fun directToGameDetail(context: Context, id: String, entrance: String? = null, autoDownload: Boolean? = null, scrollToLibao: Boolean = false, traceEvent: ExposureEvent? = null) {
fun directToGameDetail(context: Context, id: String, entrance: String? = null, autoDownload: Boolean? = null, tab: String? = "", traceEvent: ExposureEvent? = null) {
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, GameDetailActivity::class.java.simpleName)
bundle.putString(KEY_GAMEID, id)
if (scrollToLibao) {
bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_TRENDES)
bundle.putBoolean(KEY_SCROLL_TO_LIBAO, scrollToLibao)
if (!TextUtils.isEmpty(tab)) {
when (tab) {
"comment" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_RATING)
"desc" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_DESC)
"forum" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_BBS)
"zone" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_TRENDES)
}
}
if (traceEvent != null) {
val clickEvent = createEvent(GameEntity(id), traceEvent.source, appendTrace(traceEvent), ExposureType.CLICK)
@ -345,6 +407,19 @@ object DirectUtils {
jumpActivity(context, bundle)
}
/**
* 跳转到游戏评分详情
*/
@JvmStatic
fun directToGameRatingDetail(context: Context, gameId: String? = "", commentId: String? = "", entrance: String? = null) {
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_GAMEID, gameId)
bundle.putString(KEY_COMMENTID, commentId)
bundle.putString(KEY_TO, RatingReplyActivity::class.java.name)
jumpActivity(context, bundle)
}
/**
* 跳转视频流-游戏介绍进入
*/
@ -356,7 +431,16 @@ object DirectUtils {
bundle.putString(KEY_GAMEID, id)
bundle.putBoolean(KEY_OPEN_VIDEO_STREAMING, true)
bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_DESC)
// GameDetailActivity.startGameDetailToVideoStreaming(context, id, entrance)
jumpActivity(context, bundle)
}
@JvmStatic
fun directToGameDetail(context: Context, id: String, defaultTab: Int = GameDetailFragment.INDEX_DESC, entrance: String? = null) {
val bundle = Bundle()
bundle.putString(KEY_TO, GameDetailActivity::class.java.name)
bundle.putString(KEY_ENTRANCE, entrance)
bundle.putString(KEY_GAMEID, id)
bundle.putInt(KEY_TARGET, defaultTab)
jumpActivity(context, bundle)
}
@ -368,6 +452,7 @@ object DirectUtils {
// 专栏
@JvmStatic
fun directToSubject(context: Context, id: String, subjectName: String? = "", entrance: String? = null) {
if (id.isEmpty()) return
val bundle = Bundle()
val subjectData = SubjectData(subjectId = id, subjectName = subjectName, isOrder = false)
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
@ -444,6 +529,7 @@ object DirectUtils {
@JvmStatic
fun directToAnswerDetail(context: Context, id: String, entrance: String? = null, path: String? = null) {
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, AnswerDetailActivity::class.java.name)
@ -454,6 +540,7 @@ object DirectUtils {
@JvmStatic
fun directToQuestionDetail(context: Context, id: String, entrance: String? = null, path: String? = null) {
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, QuestionsDetailActivity::class.java.name)
@ -464,6 +551,7 @@ object DirectUtils {
@JvmStatic
fun directToWebView(context: Context, url: String, entrance: String? = null) {
if (url.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, WebActivity::class.java.simpleName)
@ -482,8 +570,9 @@ object DirectUtils {
@JvmStatic
fun directToExternalBrowser(context: Context, url: String) {
if (url.isEmpty()) return
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
if (context !is AppCompatActivity){
if (context !is AppCompatActivity) {
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(browserIntent)
@ -507,7 +596,7 @@ object DirectUtils {
}
val str = "mqqwpa://im/chat?chat_type=$chatType&uin=$qq&version=1&src_type=web"
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(str))
if (context !is AppCompatActivity){
if (context !is AppCompatActivity) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(intent)
@ -521,12 +610,13 @@ object DirectUtils {
// 跳转 QQ 群
@JvmStatic
fun directToQqGroup(context: Context, groupNumber: String? = null): Boolean {
if (groupNumber.isNullOrEmpty()) return false
if (ShareUtils.isQQClientAvailable(context)) {
val intent = Intent()
intent.data = Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D$groupNumber")
// 此Flag可根据具体产品需要自定义如设置则在加群界面按返回返回手Q主界面不设置按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
return try {
if (context !is AppCompatActivity){
if (context !is AppCompatActivity) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(intent)
@ -534,7 +624,7 @@ object DirectUtils {
} catch (e: Exception) {
false
}
}else{
} else {
Utils.toast(context, "请安装QQ客户端")
return false
}
@ -546,10 +636,12 @@ object DirectUtils {
*/
@JvmStatic
fun directToGiftDetail(context: Context, giftId: String, entrance: String? = null) {
if (giftId.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, LibaoDetailActivity::class.java.simpleName)
bundle.putString(EntranceUtils.KEY_ID, giftId)
HaloApp.put(LibaoEntity.TAG, null)
jumpActivity(context, bundle)
}
@ -600,6 +692,7 @@ object DirectUtils {
@JvmStatic
fun directToCommunityArticle(context: Context, community: CommunityEntity?, articleId: String?, entrance: String?, path: String?) {
if (articleId.isNullOrEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_PATH, path)
@ -614,6 +707,7 @@ object DirectUtils {
*/
@JvmStatic
fun directToCommunityColumn(context: Context, community: CommunityEntity?, subjectId: String, entrance: String?, path: String?) {
if (subjectId.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_PATH, path)
bundle.putString(KEY_TO, CommunitySubjectActivity::class.java.name)
@ -627,7 +721,8 @@ object DirectUtils {
* @param fromLocation 可见 [VideoDetailContainerViewModel.Location]
*/
@JvmStatic
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null, path: String? = "", referer: String = "", type: String = "", act: String = "") {
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null,
path: String? = "", referer: String = "", type: String = "", act: String = "", paginationType: String = "", fieldId: String = "", sectionName: String = "") {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
@ -640,6 +735,9 @@ object DirectUtils {
bundle.putString(KEY_REFERER, referer)
bundle.putString(KEY_TYPE, type)
bundle.putString(KEY_ACTIVITY_NAME, act)
bundle.putString(KEY_PAGINATION_TYPE, paginationType)
bundle.putString(KEY_FIELD_ID, fieldId)
bundle.putString(KEY_SECTION_NAME, sectionName)
jumpActivity(context, bundle)
} else {
DialogUtils.showLowSystemVersionDialog(context)
@ -677,20 +775,37 @@ object DirectUtils {
* 跳转至上传视频
*/
@JvmStatic
fun directToVideoManager(context: Context, linkEntity: VideoLinkEntity, entrance: String? = null, path: String? = "") {
fun directToVideoManager(context: Context, linkEntity: VideoLinkEntity, simpleGameEntity: SimpleGameEntity, entrance: String? = null, path: String? = "") {
val bundle = Bundle()
bundle.putString(KEY_PATH, path)
bundle.putParcelable(VideoLinkEntity::class.java.simpleName, linkEntity)
bundle.putParcelable(SimpleGameEntity::class.java.simpleName, simpleGameEntity)
bundle.putString(KEY_TO, VideoManagerActivity::class.java.name)
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
jumpActivity(context, bundle)
}
@JvmStatic
fun directToFullScreenWebPage(context: Context, url: String, webViewHandleBackPressed: Boolean = false) {
context.startActivity(FullScreenWebActivity.getIntent(context, url, webViewHandleBackPressed))
}
@JvmStatic
fun directToRegulationTestPage(context: Context) {
val url = if ("internal" == BuildConfig.FLAVOR) {
Constants.REGULATION_TEST_ADDRESS_DEV
} else {
Constants.REGULATION_TEST_ADDRESS
}
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转视频合集
*/
@JvmStatic
fun directToGameVideo(context: Context, gameId: String, entrance: String? = null, path: String? = "") {
if (gameId.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_PATH, path)
bundle.putString(KEY_TO, GameVideoActivity::class.java.name)
@ -738,6 +853,7 @@ object DirectUtils {
*/
@JvmStatic
fun directCategoryDirectory(context: Context, categoryId: String, categoryTitle: String, entrance: String? = null, path: String? = "") {
if (categoryId.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_TO, CategoryDirectoryActivity::class.java.name)
bundle.putString(KEY_CATEGORY_ID, categoryId)
@ -766,6 +882,7 @@ object DirectUtils {
*/
@JvmStatic
fun directAskColumnDetail(context: Context, columnId: String, community: CommunityEntity, entrance: String? = null, path: String? = "") {
if (columnId.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_TO, AskColumnDetailActivity::class.java.name)
bundle.putString(KEY_COLUMN_ID, columnId)
@ -779,10 +896,11 @@ object DirectUtils {
* 跳转到板块
*/
@JvmStatic
fun directToBlock(context: Context, blockData: SubjectRecommendEntity) {
fun directToBlock(context: Context, blockData: SubjectRecommendEntity, entrance: String) {
val bundle = Bundle()
bundle.putString(KEY_TO, BlockActivity::class.java.name)
bundle.putParcelable(KEY_BLOCK_DATA, blockData)
bundle.putString(KEY_ENTRANCE, entrance)
jumpActivity(context, bundle)
}
@ -814,6 +932,7 @@ object DirectUtils {
*/
@JvmStatic
fun directSimpleArticleList(context: Context, sortType: String, entrance: String? = null, path: String? = "") {
if (sortType.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_TO, SimpleArticleListActivity::class.java.name)
bundle.putString(KEY_TYPE, sortType)
@ -821,4 +940,69 @@ object DirectUtils {
bundle.putString(KEY_PATH, path)
jumpActivity(context, bundle)
}
@JvmStatic
fun directGameZone(context: Context, gameId: String, url: String, entrance: String? = null) {
RetrofitManager.getInstance(HaloApp.getInstance().application)
.sensitiveApi
.getGameDigest(gameId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<GameEntity>() {
override fun onResponse(response: GameEntity?) {
response?.apply {
if (zone.status == "on") {
if (zone.style == "link") {
directToGameDetail(context, gameId, GameDetailFragment.INDEX_TRENDES, entrance)
} else {
directToWebView(context, url, entrance)
}
} else {
directToWebView(context, url, entrance)
}
}
}
override fun onFailure(e: HttpException?) {
}
})
}
@JvmStatic
fun directVideoData(context: Context, entrance: String? = null) {
val bundle = Bundle()
bundle.putString(KEY_TO, VideoDataActivity::class.java.name)
bundle.putString(KEY_ENTRANCE, entrance)
jumpActivity(context, bundle)
}
@JvmStatic
fun directForumDetail(context: Context, bbsId: String? = "", entrance: String? = null) {
val bundle = Bundle()
bundle.putString(KEY_TO, ForumDetailActivity::class.java.name)
bundle.putString(KEY_BBS_ID, bbsId)
bundle.putString(KEY_ENTRANCE, entrance)
jumpActivity(context, bundle)
}
/**
* 到首页论坛 tab
*/
@JvmStatic
fun directToForum(context: Context) {
if (RunningUtils.isRunning(context)
&& MainActivity::class.java.name == RunningUtils.getBaseActivity(context)) {
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
context.startActivity(intent)
// 这里换个线程操作是为了做一点延时
AppExecutor.ioExecutor.execute {
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_ASK))
}
} else {
jumpActivity(context, Bundle().apply { putInt(KEY_POSITION, MainWrapperFragment.INDEX_ASK) })
}
}
}

View File

@ -9,6 +9,7 @@ import android.os.Build;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
@ -272,13 +273,23 @@ public class DisplayUtils {
}
public static int getToastOffset() {
int i = Resources.getSystem().getIdentifier("toast_y_offset", "dimen", "android");
return HaloApp.getInstance().getApplication().getResources().getDimensionPixelSize(i);
try {
int i = Resources.getSystem().getIdentifier("toast_y_offset", "dimen", "android");
return HaloApp.getInstance().getApplication().getResources().getDimensionPixelSize(i);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
return dip2px(24);
}
}
public static int getToastDefaultGravity() {
int i = Resources.getSystem().getIdentifier("config_toastDefaultGravity", "integer", "android");
return HaloApp.getInstance().getApplication().getResources().getInteger(i);
try {
int i = Resources.getSystem().getIdentifier("config_toastDefaultGravity", "integer", "android");
return HaloApp.getInstance().getApplication().getResources().getInteger(i);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
return Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
}
}
public static boolean hasSoftKeys(Context context) {

View File

@ -8,12 +8,6 @@ import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.collection.ArrayMap;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.gh.common.constant.Config;
import com.gh.common.dialog.CertificationDialog;
import com.gh.common.dialog.DeviceRemindDialog;
@ -21,6 +15,8 @@ import com.gh.common.dialog.ReserveDialogFragment;
import com.gh.common.exposure.ExposureEvent;
import com.gh.common.history.HistoryHelper;
import com.gh.common.repository.ReservationRepository;
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;
@ -40,6 +36,12 @@ import com.lightgame.utils.Utils;
import java.util.concurrent.LinkedBlockingQueue;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.collection.ArrayMap;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
/**
* todo 下载判断不能以按钮文案为判断条件,否则按钮文案修改时又要修改判断逻辑
*/
@ -261,6 +263,7 @@ public class DownloadItemUtils {
boolean isShowPlatform, boolean isNormal) {
updateItemViewStatus(holder, true, null);
holder.gameProgressbar.setProgressDrawable(context.getResources().getDrawable(R.drawable.progressbar_bg_style));
String platform = PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
@ -321,6 +324,17 @@ public class DownloadItemUtils {
holder.gameDownloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
}
} else if (status.equals(DownloadStatus.done)) {
String xapkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
if (XapkUnzipStatus.UNZIPPING.name().equals(xapkStatus)) {
String percent = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_PERCENT);
holder.gameProgressbar.setProgressDrawable(context.getResources().getDrawable(R.drawable.progressbar_xapk_style));
holder.gameDownloadSpeed.setText(R.string.unzipping);
holder.gameProgressbar.setProgress((int) (Float.valueOf(percent) * 10));
holder.gameDownloadPercentage.setText(percent + "%");
holder.gameDownloadBtn.setText(R.string.unzipping);
return;
}
holder.gameProgressbar.setProgress(1000);
if (isShowPlatform && platform != null) {
holder.gameDownloadSpeed.setText(String.format("%s - 下载完成", platform));
@ -454,7 +468,7 @@ public class DownloadItemUtils {
HistoryHelper.insertGameEntity(gameEntity);
}
Intent i = WebActivity.getIntentForWebGame(context, gameEntity.getH5Link().getLink(), gameEntity.getName(), isPlay);
Intent i = WebActivity.getIntentForWebGame(context, gameEntity.getH5Link().getLink(), gameEntity.getName(), isPlay,linkEntity.getCloseButton());
context.startActivity(i);
});
} else if (gameEntity.getApk().size() == 1) {
@ -520,8 +534,10 @@ public class DownloadItemUtils {
// 先弹下载弹窗(如果需要的话)
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
DialogUtils.checkDownload(context, apk.getSize(),
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
DialogUtils.checkDownload(context, apk.getSize(),
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
});
});
});
@ -530,8 +546,10 @@ public class DownloadItemUtils {
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
DialogUtils.checkDownload(context, apk.getSize(),
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
DialogUtils.checkDownload(context, apk.getSize(),
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
});
});
});
});
@ -559,10 +577,6 @@ public class DownloadItemUtils {
}
DataUtils.onGameLaunchEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), location);
PackageUtils.launchApplicationByPackageName(context, gameEntity.getApk().get(0).getPackageName());
} else if (str.equals(context.getString(R.string.waiting))
|| str.equals(context.getString(R.string.downloading))) {
context.startActivity(DownloadManagerActivity.getDownloadMangerIntent(context,
apk.getUrl(), entrance + "+(" + location.split(":")[0] + ")"));
} else if (str.equals(context.getString(R.string.update))) {
if (entrance.contains("我的游戏")) {
MtaHelper.onEvent("我的游戏_启动", "更新", gameEntity.getName());
@ -571,6 +585,9 @@ public class DownloadItemUtils {
DialogUtils.checkDownload(context, apk.getSize(),
isSubscribe -> update(context, gameEntity, entrance, location, isSubscribe, traceEvent));
});
} else {
context.startActivity(DownloadManagerActivity.getDownloadMangerIntent(context,
apk.getUrl(), entrance + "+(" + location.split(":")[0] + ")"));
}
}
@ -631,9 +648,9 @@ public class DownloadItemUtils {
}
adapter.notifyItemChanged(position);
} else if (PackageUtils.isCanPluggable(apkEntity)) {
DialogUtils.showPluginDialog(context, () -> context.startActivity(PackageUtils.getUninstallIntent(context, path)));
DialogUtils.showPluginDialog(context, () -> PackageInstaller.uninstall(context, path));
} else {
PackageUtils.launchSetup(context, downloadEntity);
PackageInstaller.install(context, downloadEntity);
}
}
}

View File

@ -10,6 +10,8 @@ import android.os.Build
import androidx.core.app.NotificationCompat
import com.gh.common.AppExecutor
import com.gh.common.constant.Constants
import com.gh.common.xapk.XapkInstaller
import com.gh.common.xapk.XapkUnzipStatus
import com.gh.gamecenter.R
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
@ -38,9 +40,12 @@ object DownloadNotificationHelper {
var requireUpdateNotificationGroupDelay = false
val notificationManager = getNotificationManager()
val downloadNotificationId = (entity.gameId + entity.packageName).hashCode()
val xapkStatus = entity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
if (entity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.SILENT_UPDATE) return
val intent = Intent()
if (entity.status == DownloadStatus.done) {
if (entity.status == DownloadStatus.done && xapkStatus != XapkUnzipStatus.FAILURE.name) {
intent.putExtra(EntranceUtils.KEY_DATA, entity.toJson())
intent.putExtra(EntranceUtils.KEY_PATH, entity.path)
intent.action = ACTION_INSTALL
@ -53,7 +58,6 @@ object DownloadNotificationHelper {
PendingIntent.FLAG_UPDATE_CURRENT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// importance == IMPORTANCE_DEFAULT 时每次更新都会触发震动
val channel = NotificationChannel(DOWNLOAD_CHANNEL_ID, DOWNLOAD_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
notificationManager.createNotificationChannel(channel)
}
@ -65,18 +69,22 @@ object DownloadNotificationHelper {
.setContentIntent(pendingIntent)
.setGroup(DOWNLOAD_GROUP_KEY)
.setWhen(whenTime)
.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
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.neterror -> builder.setContentText("已暂停连接WiFi自动下载")
else -> builder.setContentText("暂停中")
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.neterror -> builder.setContentText("已暂停连接WiFi自动下载")
else -> builder.setContentText("暂停中")
}
builder.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
}
when {
@ -91,6 +99,11 @@ object DownloadNotificationHelper {
tryCatchInRelease {
val notification = builder.build() // 可能会抛出异常
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
if (xapkStatus == XapkUnzipStatus.FAILURE.name) {
notification.flags = notification.flags or Notification.FLAG_AUTO_CANCEL
} else {
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
}
if (entity.status == DownloadStatus.delete
|| entity.status == DownloadStatus.cancel
@ -98,7 +111,8 @@ object DownloadNotificationHelper {
|| entity.status == DownloadStatus.notfound
|| entity.status == DownloadStatus.overflow
|| (entity.status == DownloadStatus.done // 触发安装事件以后也 cancel 掉通知
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty())) {
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty()
&& xapkStatus != XapkUnzipStatus.FAILURE.name)) {
requireUpdateNotificationGroupDelay = true
notificationManager.cancel(entity.path, DOWNLOAD_NOTIFICATION_ID)
} else {
@ -125,32 +139,35 @@ object DownloadNotificationHelper {
}
private fun updateNotificationGroup() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val notificationManager = getNotificationManager()
val activeNotifications = notificationManager.activeNotifications
var downloadNotificationSize = 0
var downloadGroupNotificationSize = 0
for (activeNotification in activeNotifications) {
if (activeNotification.id == DOWNLOAD_NOTIFICATION_ID) {
downloadNotificationSize++
// 部分华为设备调用 getActiveNotifications() 方法时会触发方法内的空指针,这里整体包裹处理了
tryCatchInRelease {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val notificationManager = getNotificationManager()
val activeNotifications = notificationManager.activeNotifications
var downloadNotificationSize = 0
var downloadGroupNotificationSize = 0
for (activeNotification in activeNotifications) {
if (activeNotification.id == DOWNLOAD_NOTIFICATION_ID) {
downloadNotificationSize++
}
if (activeNotification.id == DOWNLOAD_NOTIFICATION_FOLD_ID) {
downloadGroupNotificationSize++
}
}
if (activeNotification.id == DOWNLOAD_NOTIFICATION_FOLD_ID) {
downloadGroupNotificationSize++
}
}
if (downloadNotificationSize == 0 && downloadGroupNotificationSize != 0) {
// 删除组可能会把组内所有通知一并删除
notificationManager.cancel(DOWNLOAD_NOTIFICATION_FOLD_ID)
} else if (downloadNotificationSize != 0 && downloadGroupNotificationSize == 0) {
val groupBuilder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
.setSmallIcon(R.mipmap.logo)
.setGroup(DOWNLOAD_GROUP_KEY)
.setGroupSummary(true)
.setStyle(NotificationCompat.BigTextStyle().bigText("下载任务"))
val groupNotification = groupBuilder.build()
groupNotification.flags = groupNotification.flags or Notification.FLAG_NO_CLEAR
notificationManager.notify(DOWNLOAD_NOTIFICATION_FOLD_ID, groupNotification)
if (downloadNotificationSize == 0 && downloadGroupNotificationSize != 0) {
// 删除组可能会把组内所有通知一并删除
notificationManager.cancel(DOWNLOAD_NOTIFICATION_FOLD_ID)
} else if (downloadNotificationSize != 0 && downloadGroupNotificationSize == 0) {
val groupBuilder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
.setSmallIcon(R.mipmap.logo)
.setGroup(DOWNLOAD_GROUP_KEY)
.setGroupSummary(true)
.setStyle(NotificationCompat.BigTextStyle().bigText("下载任务"))
val groupNotification = groupBuilder.build()
groupNotification.flags = groupNotification.flags or Notification.FLAG_NO_CLEAR
notificationManager.notify(DOWNLOAD_NOTIFICATION_FOLD_ID, groupNotification)
}
}
}
}

View File

@ -6,6 +6,8 @@ import android.preference.PreferenceManager
import com.gh.base.BaseActivity
import com.gh.common.constant.Constants
import com.gh.common.exposure.ExposureUtils
import com.gh.common.xapk.XapkInstaller
import com.gh.download.DownloadDataHelper
import com.gh.download.DownloadManager
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.R
@ -43,11 +45,15 @@ object DownloadObserver {
fun initObserver() {
val dataWatcher = object : DataWatcher() {
override fun onDataChanged(downloadEntity: DownloadEntity) {
// todo 如何处理xapk安装问题
val xapkStatus = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
if (!xapkStatus.isNullOrEmpty()) return
val gameId = downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER)
val downloadManager = DownloadManager.getInstance(HaloApp.getInstance().application)
if (downloadEntity.status != DownloadStatus.downloading) {
LogUtils.uploadDownloadEvent(downloadEntity)
tryCatchInRelease {
DownloadDataHelper.uploadDownloadEvent(downloadEntity)
}
if (DownloadStatus.hijack == downloadEntity.status) {
@ -101,11 +107,13 @@ object DownloadObserver {
if (DownloadStatus.done == downloadEntity.status) {
if (downloadEntity.name.contains(mApplication.getString(R.string.app_name))) {
MtaHelper.onEvent("软件更新", "下载完成")
// 会有 ActivityNotFoundException 异常catch 掉不管了
tryWithDefaultCatch {
// 会有 ActivityNotFoundException 异常catch 掉不管了
mApplication.startActivity(PackageUtils.getInstallIntent(mApplication, downloadEntity.path, true))
if (Constants.SILENT_UPDATE != downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE)) {
PackageInstaller.install(mApplication, downloadEntity)
DataLogUtils.uploadUpgradeLog(mApplication, "install") //上传更新安装数据
}
}
DataLogUtils.uploadUpgradeLog(mApplication, "install") //上传更新安装数据
} else {
statDoneEvent(downloadEntity)
@ -131,7 +139,7 @@ object DownloadObserver {
if (PackageUtils.isCanLaunchSetup(mApplication, downloadEntity.path)) {
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
tryWithDefaultCatch {
mApplication.startActivity(PackageUtils.getInstallIntent(mApplication, downloadEntity.path))
PackageInstaller.install(mApplication, downloadEntity, false)
}
} else {
// 弹出卸载提示框

View File

@ -1,18 +1,32 @@
package com.gh.common.util;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextUtils;
import com.gh.common.avoidcallback.AvoidOnResultManager;
import com.gh.common.avoidcallback.Callback;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.MainActivity;
import com.gh.gamecenter.NormalActivity;
import com.gh.gamecenter.SplashScreenActivity;
import com.gh.gamecenter.normal.NormalFragment;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.Utils;
import org.json.JSONObject;
import java.util.Iterator;
import java.util.Set;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
/**
* @author CsHeng
* @Date 2017/4/25
@ -25,8 +39,10 @@ public class EntranceUtils {
public static final String KEY_NEXT_TO = "next_to";
public static final String KEY_NEWSID = "newsId";
public static final String KEY_GAMEID = "gameId";
public static final String KEY_GAME_ID = "game_id";
public static final String KEY_ID = "id";
public static final String KEY_URL = "url";
public static final String KEY_BUNDLE = "bundle";
public static final String KEY_GAMENAME = "gameName";
public static final String KEY_PACKAGE_MD5 = "package_md5";
public static final String HOST_ARTICLE = "article";
@ -38,6 +54,7 @@ public class EntranceUtils {
public static final String HOST_VIDEO_COLLECTION = "video_collection";//视频合集
public static final String HOST_USERHOME = "userhome";//个人主页
public static final String HOST_VIDEO = "video";
public static final String HOST_FORUM = "forum";
public static final String HOST_CATEGORY = "category";//分类
public static final String HOST_COLUMN_COLLECTION = "column_collection";//专题合集
public static final String HOST_COMMUNITY_QUESTION_LABEL_DETAIL = "community_question_label_detail";//问题标签详情
@ -45,25 +62,33 @@ public class EntranceUtils {
public static final String HOST_BLOCK = "block";//板块
public static final String HOST_SERVER_BLOCK = "server";//开服表板块
public static final String HOST_AMWAY_BLOCK = "amway";//安利墙板块
public static final String HOST_GAME_CALENDAR = "game_calendar";// 指定游戏的开服表页面
public static final String HOST_HISTORY_APK = "history_apk"; // 历史版本页面
public static final String HOST_HELP = "help";//Q&A
public static final String HOST_HELP_COLLECTION = "help_collection";//Q&A合集
public static final String HOST_GAME_UPLOAD = "game_upload";//游戏上传
public static final String HOST_GAME_ZONE = "game_zone";//游戏专区
public static final String HOST_COMMUNITY_ARTICLE = "community_article";
public static final String HOST_COMMUNITY_COLUMN = "community_column";
public static final String HOST_GAME = "game";
public static final String HOST_GAME_DOWNLOAD = "game_download";
public static final String HOST_GAME_NEWS = "game_news";
public static final String HOST_COLUMN = "column";
public static final String HOST_WEB = "web";
public static final String HOST_QQ = "qq";
public static final String HOST_QQ_GROUP = "qqgroup";
public static final String HOST_QQ_QUN = "qqqun";
public static final String HOST_DOWNLOAD = "download";
public static final String HOST_UPDATE = "update";
public static final String HOST_LINK = "link";
public static final String HOST_LIBAO = "libao";
public static final String HOST_COMMUNITY = "community";
public static final String HOST_SUGGESTION = "suggestion";
public static final String HOST_ANSWER = "answer";
public static final String HOST_QUESTION = "question";
public static final String HOST_TOOLBOX = "toolbox";
public static final String HOST_FORUM_DETAIL = "forum_detail";
public static final String HOST_GAME_RATING_DETAIL = "game_rating_detail";
public static final String KEY_DATA = "data";
public static final String KEY_MESSAGE = "message";
public static final String KEY_MESSAGE_ID = "message_id";
@ -81,6 +106,7 @@ public class EntranceUtils {
public static final String ENTRANCE_DOWNLOAD = "(下载跳转)";
public static final String ENTRANCE_RECOMMEND = "(落地页)";
public static final String ENTRANCE_BLOCK_RECOMMEND = "(推荐入口)";
public static final String ENTRANCE_AMWAY = "(安利墙)";
public static final String KEY_SUGGEST_HINT_TYPE = "suggestHintType";
public static final String KEY_PACKAGENAME = "packageName";
public static final String KEY_PLATFORM = "platform";
@ -91,6 +117,7 @@ public class EntranceUtils {
public static final String KEY_LOCATION = "location";
public static final String KEY_CURRENTITEM = "currentItem";
public static final String KEY_COMMENTID = "commentId";
public static final String KEY_COMMENT_ID = "comment_id";
public static final String KEY_SHOW_KEYBOARD_IF_NEEDED = "show_key_board_if_needed";
public static final String KEY_PATH = "path";
public static final String KEY_OUTER_INFO = "outerInfo";
@ -140,6 +167,7 @@ public class EntranceUtils {
public static final String KEY_COMMUNITY_ARTICLE_ID = "communityArticleId";
public static final String KEY_ARTICLE_COMMENT_ID = "articleCommentId";
public static final String KEY_SHOW_ARTICLE_COMMENT = "showArticleComment";
public static final String KEY_SCROLL_TO_COMMENT_AREA = "scroll_to_comment_area";
public static final String KEY_RATING_STAR_COUNT = "ratingStarCount";
public static final String KEY_QUESTION_MODERATOR_PATCH = "questionModeratorPatch";
public static final String KEY_SKIP_GAME_COMMENT = "skipGameComment";
@ -161,7 +189,10 @@ public class EntranceUtils {
public static final String KEY_IS_HOME = "isHome";
public static final String KEY_WEB_SHARE = "webShare";
public static final String KEY_ACTIVITY_NAME = "activityName";//活动名称
public static final String KEY_PAGINATION_TYPE = "paginationType";//活动分页方式
public static final String KEY_REQUIRE_REDIRECT = "require_redirect"; // 标记需要再跳转
public static final String KEY_FIELD_ID = "field_id"; // 专区板块id
public static final String KEY_SECTION_NAME = "section_name"; // 专区专题名
public static final String KEY_COLUMNNAME = "columnName";
public static final String KEY_QA_ID = "qaId";
public static final String KEY_QA_COLLECTION_ID = "qaCollectionId";
@ -169,6 +200,13 @@ public class EntranceUtils {
public static final String KEY_ARTICLE_OPEN_IN_NEW_PAGE = "openArticleInNewPage";
public static final String KEY_ONLY_CREATE_DRAFT = "onlyCreateDraft";
public static final String KEY_KAIFU_SELECT_TIME = "kaifuSelectTime";
public static final String KEY_POSTER_PATH = "posterPath";
public static final String KEY_BLACK_THEME = "blackTheme";
public static final String KEY_FROM_LOGIN = "fromLogin";
public static final String KEY_CHANGE_PHONE = "changePhone";
public static final String KEY_CONFLICT_PHONE = "conflictPhone";
public static final String KEY_CONFLICT_USER = "conflictUser";
public static final String KEY_BBS_ID = "bbs_id";
public static void jumpActivity(Context context, Bundle bundle) {
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
@ -224,4 +262,82 @@ public class EntranceUtils {
context.startActivity(SplashScreenActivity.getSplashScreenIntent(context, bundle));
}
}
public static void saveShortcut(String activityName, @Nullable Bundle bundle) {
if (BuildConfig.DEBUG) {
JSONObject json = new JSONObject();
if (activityName.contains("MainActivity")) {
SPUtils.setString(EntranceUtils.KEY_BUNDLE, "");
return;
}
if (bundle == null) bundle = new Bundle();
try {
Set<String> keys = bundle.keySet();
json.put(KEY_TO, activityName);
for (String key : keys) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Object object = bundle.get(key);
if (object instanceof Parcelable) {
if (object.toString().toLowerCase().contains("gameentity")) {
Utils.toast(HaloApp.getInstance().getApplication(), "暂不支持带游戏实体的页面保存捷径");
return;
}
String parcelableName = key + ":parcelable";
String parcelableType = object.getClass().getName();
String objectJsonString = GsonUtils.toJson(object);
JSONObject jObject = new JSONObject(objectJsonString);
json.put(parcelableName, parcelableType);
json.put(key, jObject);
} else {
json.put(key, JSONObject.wrap(bundle.get(key)));
}
}
}
Utils.toast(HaloApp.getInstance().getApplication(), "保存捷径成功");
SPUtils.setString(EntranceUtils.KEY_BUNDLE, json.toString());
} catch (Exception e) {
e.printStackTrace();
SPUtils.setString(EntranceUtils.KEY_BUNDLE, "");
}
}
}
public static void jumpShortcut(Activity activity) {
if (BuildConfig.DEBUG) {
if (!hasShortcut()) return;
Bundle bundle = new Bundle();
try {
JSONObject jsonObject = new JSONObject(SPUtils.getString(EntranceUtils.KEY_BUNDLE));
Iterator iter = jsonObject.keys();
String parcelableName = "";
while (iter.hasNext()) {
String key = (String) iter.next();
String value = jsonObject.getString(key);
if (key.contains(":parcelable")) {
parcelableName = value;
} else {
if (!TextUtils.isEmpty(parcelableName)) {
Class<?> gClass = Class.forName(parcelableName);
bundle.putParcelable(key, ((Parcelable) GsonUtils.fromJson(value, gClass)));
} else {
bundle.putString(key, value);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
jumpActivity(activity, bundle);
}
}
public static boolean hasShortcut() {
return !TextUtils.isEmpty(SPUtils.getString(EntranceUtils.KEY_BUNDLE));
}
}

View File

@ -116,6 +116,8 @@ object ErrorHelper {
403078 -> Utils.toast(context, "已点赞")
403072 -> Utils.toast(context, R.string.comment_failed_userblocked)
403082 -> Utils.toast(context, "作者已关闭评论")
403022 -> Utils.toast(context, "不能回复自己")
403056 -> Utils.toast(context, "发布失败,字数已达上限")
403020 -> if (showHighPriorityHint) {
DialogUtils.showAlertDialog(context,

View File

@ -3,6 +3,7 @@ package com.gh.common.util
import android.animation.Animator
import android.content.ClipboardManager
import android.content.Context
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.text.*
import android.text.style.ClickableSpan
@ -11,6 +12,8 @@ import android.text.style.URLSpan
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.PopupWindow
import android.widget.TextView
import androidx.annotation.ColorRes
@ -19,6 +22,7 @@ import androidx.core.text.HtmlCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.*
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
import com.airbnb.lottie.LottieAnimationView
@ -32,8 +36,10 @@ import com.gh.common.view.ExpandTextView
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.manager.UserManager
import com.google.gson.reflect.TypeToken
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.utils.Utils
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
@ -41,6 +47,7 @@ import io.reactivex.disposables.Disposable
import okhttp3.MediaType
import okhttp3.RequestBody
import java.net.URI
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern
import kotlin.math.abs
@ -61,6 +68,14 @@ inline fun <reified VM : ViewModel> Fragment.viewModelProviderFromParent(
) =
ViewModelProviders.of(requireActivity(), provider).get(VM::class.java)
/**
* 创建以 activity 为观察者上下文的 viewModel
*/
inline fun <reified VM : ViewModel> FragmentActivity.viewModelProviderFromParent(
provider: ViewModelProvider.Factory? = null
) =
ViewModelProviders.of(this, provider).get(VM::class.java)
/**
* 创建以 fragment 为观察者上下文的 viewModel
*/
@ -159,6 +174,17 @@ fun View.removeSelectableItemBackground() {
background = null
}
fun View.setRoundedColorBackground(@ColorRes color: Int, radius: Float) {
val shape = GradientDrawable()
shape.cornerRadius = radius.dip2px().toFloat()
shape.setColor(ContextCompat.getColor(context, color))
background = shape
}
fun View.setDebouncedClickListener(action: () -> Unit) {
setOnClickListener { debounceActionWithInterval(interval = 300L) { action.invoke() } }
}
/**
* LiveData Extensions
*/
@ -220,6 +246,28 @@ fun String.containHtmlTag(): Boolean {
return matcher.find()
}
/**
* 用户行为相关
*/
fun Fragment.showRegulationTestDialogIfNeeded(action: (() -> Unit)) {
if (UserManager.getInstance().userShouldTakeRegulationBaseOnLastRemind()) {
DialogUtils.showRegulationTestDialog(requireContext(),
{ DirectUtils.directToRegulationTestPage(requireContext()) },
{ action.invoke() })
} else {
action()
}
}
fun Context.showRegulationTestDialogIfNeeded(action: (() -> Unit)) {
if (UserManager.getInstance().userShouldTakeRegulationBaseOnLastRemind()) {
DialogUtils.showRegulationTestDialog(this,
{ DirectUtils.directToRegulationTestPage(this) },
{ action.invoke() })
} else {
action()
}
}
/**
* 在限定 interval 里只触发一次 action
*/
@ -275,6 +323,15 @@ fun throwExceptionInDebug(message: String = "", predicate: Boolean = true) {
}
}
/**
* 主动抛出异常
*/
fun throwException(message: String = "", predicate: Boolean = true) {
if (predicate) {
throw RuntimeException(message)
}
}
/**
* String related
*/
@ -314,6 +371,10 @@ fun String.subStringIfPossible(length: Int): String {
}
}
fun String.countOccurrences(char: String): Int {
return StringTokenizer(" $this ", char).countTokens() - 1
}
fun String.getFirstElementDividedByDivider(divider: String): String {
if (this.contains(divider)) {
return this.split(divider.toRegex()).toTypedArray()[0]
@ -364,6 +425,11 @@ fun Float.px2dip(): Int {
return (this / scale + 0.5f).toInt()
}
fun Float.sp2px():Int{
val scale: Float = HaloApp.getInstance().application.resources.displayMetrics.scaledDensity
return (this * scale + 0.5f).toInt()
}
/**
* PopupWindow 自动适配方向
* 弹出与锚点右对齐
@ -444,6 +510,15 @@ fun FragmentActivity.checkStoragePermissionBeforeAction(action: (() -> Unit)) {
})
}
/**
* List related.
*/
// Returns the second element, or `null` if the list is empty.
fun <T> List<T>.secondOrNull(): T? {
return if (isEmpty() || size == 1) null else this[1]
}
/**
* TextView related.
*/
@ -566,6 +641,21 @@ fun SimpleDraweeView.display(url: String) {
ImageUtils.display(this, url)
}
/**
* DownloadEntity extension
*/
fun DownloadEntity.addMetaExtra(key: String, value: String?) {
value?.let { meta[key] = value }
}
fun DownloadEntity.getMetaExtra(key: String): String {
return meta[key] ?: ""
}
fun DownloadEntity.isSilentUpdate(): Boolean {
return Constants.SILENT_UPDATE == getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE)
}
/**
* Process related
*/
@ -682,6 +772,17 @@ fun LottieAnimationView.doOnAnimationEnd(action: () -> Unit) {
})
}
fun String?.getExtension(): String? {
this ?: return null
tryCatchInRelease {
val lastDotIndex = this.lastIndexOf('.')
return if (lastDotIndex == -1) null else this.substring(lastDotIndex + 1)
}
return null
}
/**
* 检查内容是否一致
* @return true:相同 false:不同
@ -706,4 +807,15 @@ fun List<String>?.checkSameFromStringArray(check2: List<String>?): Boolean {
if (!this.contains(tag)) return false
}
return true
}
/**
* EditText弹出软键盘
*/
fun EditText.showKeyBoard() {
this.postDelayed({
this.requestFocus()
val inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showSoftInput(this, 0)
}, 300)
}

View File

@ -5,6 +5,8 @@ import android.graphics.Color;
import android.text.TextUtils;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.gh.common.constant.Config;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.R;
@ -22,9 +24,6 @@ import com.lightgame.download.DownloadStatus;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.Nullable;
public class GameUtils {
/**
@ -183,6 +182,8 @@ public class GameUtils {
GameUpdateEntity gameUpdateEntity = new GameUpdateEntity();
gameUpdateEntity.setId(gameEntity.getId());
gameUpdateEntity.setIcon(gameEntity.getIcon());
gameUpdateEntity.setRawIcon(gameEntity.getRawIcon());
gameUpdateEntity.setIconSubscript(gameEntity.getIconSubscript());
gameUpdateEntity.setName(gameEntity.getName());
gameUpdateEntity.setPackageName(apkEntity.getPackageName());
gameUpdateEntity.setSize(apkEntity.getSize());
@ -199,6 +200,7 @@ public class GameUtils {
gameUpdateEntity.setDownload(gameEntity.getDownload());
gameUpdateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
gameUpdateEntity.setPluginDesc(gameEntity.getPluginDesc());
gameUpdateEntity.setFormat(apkEntity.getFormat());
GameCollectionEntity pluggableCollection = getPluggableCollectionFromGameEntity(gameEntity, apkEntity.getPackageName());
if (pluggableCollection != null) {

View File

@ -23,7 +23,7 @@ object GdtHelper {
const val PLATFORM = "PLATFORM"
fun init(application: Application) {
GDTAction.init(application, "1110071928", "7fe03caa04ed382e9dce401312b1d0ae")
GDTAction.init(application, "1110680399", "f5ddaafbf520d7d7385499232a408d0a")
}
fun logAction(type: String) {

View File

@ -1,6 +1,7 @@
package com.gh.common.util
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import org.json.JSONArray
@ -10,6 +11,7 @@ import org.json.JSONArray
*/
object GsonUtils {
val gson: Gson = Gson()
val gsonThatIgnoreNull: Gson = GsonBuilder().serializeNulls().create()
@JvmStatic
fun <T> fromJson(json: String, t: Class<T>): T {
@ -32,4 +34,9 @@ object GsonUtils {
fun toJson(any: Any?): String {
return gson.toJson(any)
}
@JvmStatic
fun toJsonIgnoreNull(any: Any?): String {
return gsonThatIgnoreNull.toJson(any)
}
}

View File

@ -1,5 +1,6 @@
package com.gh.common.util
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.Resources
import android.graphics.Bitmap
@ -9,21 +10,21 @@ import android.net.Uri
import android.os.Build
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import com.facebook.common.executors.CallerThreadExecutor
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.drawee.controller.ControllerListener
import com.facebook.drawee.drawable.ScalingUtils
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.core.ImagePipeline
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
import com.facebook.imagepipeline.image.ImageInfo
import com.facebook.imagepipeline.request.ImageRequest
import com.facebook.imagepipeline.request.ImageRequestBuilder
import com.gh.common.constant.Config
import com.gh.gamecenter.R
import com.halo.assistant.HaloApp
import com.squareup.picasso.Picasso
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.io.ByteArrayOutputStream
@ -31,6 +32,10 @@ object ImageUtils {
private const val PIC_MAX_FILE_SIZE: Long = 10 * 1024 * 1024
private val TINY_GIF_SIZE = 30F.dip2px()
private val LARGE_GIF_SIZE = 80F.dip2px()
private val STANDARD_GIF_SIZE = 60F.dip2px()
@JvmStatic
fun getUploadFileMaxSize(): Long {
val uploadLimitSize = Config.getSettings()?.image?.uploadLimitSize
@ -216,17 +221,21 @@ object ImageUtils {
.build()
}
// 获取bitmap
// 获取bitmap (使用 fresco 获取 gif bitmap 会为空https://github.com/facebook/fresco/issues/241)
// 所以这里换用 picasso
@SuppressLint("CheckResult")
@JvmStatic
fun display(context: Context?, url: String?, dataSubscriber: BaseBitmapDataSubscriber) {
val imageRequest = ImageRequestBuilder
.newBuilderWithSource(Uri.parse(url))
.setProgressiveRenderingEnabled(true)
.build()
Fresco.getImagePipeline()
.fetchDecodedImage(imageRequest, context)
.subscribe(dataSubscriber, CallerThreadExecutor.getInstance())
fun getBitmap(url: String, callback: BiCallback<Bitmap, Boolean>) {
Single.just(url)
.map { Picasso.with(HaloApp.getInstance().application).load(url).priority(Picasso.Priority.HIGH).get() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
callback.onFirst(it)
}, {
callback.onSecond(true)
it.printStackTrace()
})
}
/**
@ -240,12 +249,23 @@ object ImageUtils {
// 图片是以 gif 结尾的就
if (it.endsWith(".gif") && view?.getTag(R.id.tag_show_gif) != false) {
if (view?.tag == url) return@let
val controller = Fresco.newDraweeControllerBuilder()
.setUri(url)
.setAutoPlayAnimations(true)
.build()
view?.controller = controller
val width = view?.layoutParams?.width
val height = view?.layoutParams?.height
if (width != null && width > 0) {
val controller = Fresco.newDraweeControllerBuilder()
.setUri(resizeGif(url, width, height ?: 0))
.setAutoPlayAnimations(true)
.build()
view.controller = controller
} else {
view?.post {
val controller = Fresco.newDraweeControllerBuilder()
.setUri(resizeGif(url, view.width, view.height))
.setAutoPlayAnimations(true)
.build()
view.controller = controller
}
}
} else {
val width = view?.layoutParams?.width
if (width != null && width > 0) {
@ -327,14 +347,34 @@ object ImageUtils {
//预加载图片
@JvmStatic
fun prefetchToDiskCache(url: String){
fun prefetchToDiskCache(url: String) {
val imagePipeline = Fresco.getImagePipeline()
val imageRequest = ImageRequest.fromUri(url)
imagePipeline.prefetchToDiskCache(imageRequest, HaloApp.getInstance().application)
}
private fun resizeGif(url: String, width: Int, height: Int): String {
val idealSize = getIdealGifSize(width, height)
return "$url?x-oss-process=image/resize,h_$idealSize,w_$idealSize"
}
private fun getIdealGifSize(width: Int, height: Int): String {
return if (width > LARGE_GIF_SIZE || height > LARGE_GIF_SIZE) {
"256"
} else if (width >= STANDARD_GIF_SIZE || height >= STANDARD_GIF_SIZE) {
"192"
} else if (width > TINY_GIF_SIZE || height > TINY_GIF_SIZE) {
"128"
} else {
"64"
}
}
public interface OnImageloadListener {
fun onLoadFinal(imageInfo: ImageInfo?)
}
fun getVideoSnapshot(videoUrl: String, progress: Long): String {
return "$videoUrl?x-oss-process=video/snapshot,t_$progress,f_jpg,w_0,h_0"
}
}

View File

@ -18,6 +18,7 @@ import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.LibaoEntity;
import com.gh.gamecenter.entity.LibaoStatusEntity;
import com.gh.gamecenter.entity.MeEntity;
import com.gh.gamecenter.entity.NotificationUgc;
import com.gh.gamecenter.entity.UserDataLibaoEntity;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.eventbus.EBUISwitch;
@ -455,20 +456,26 @@ public class LibaoUtils {
adapter.initLibaoCode(new UserDataLibaoEntity(libaoCode, "ling", Utils.getTime(context)));
adapter.notifyDataSetChanged();
final String finalLibaoCode = libaoCode;
DialogUtils.showWarningDialog(context, "领取成功", Html.fromHtml(context.getString(R.string.linged_dialog, libaoCode))
, "关闭", " 复制礼包码"
, () -> {
copyLink(finalLibaoCode, context);
if (isInstallRequired) {
libaoBtn.postDelayed(() -> {
Spanned msg = Html.fromHtml(context.getString(R.string.linged_copy_dialog, finalLibaoCode));
lunningAppDialog(context
, msg, libaoEntity);
}, 300);
}
}, null);
NotificationHelper.showNotificationHintDialog(NotificationUgc.GIFT, isShow -> {
if (!isShow){
DialogUtils.showWarningDialog(context, "领取成功", Html.fromHtml(context.getString(R.string.linged_dialog, finalLibaoCode))
, "关闭", " 复制礼包码"
, () -> {
copyLink(finalLibaoCode, context);
if (isInstallRequired) {
libaoBtn.postDelayed(() -> {
Spanned msg = Html.fromHtml(context.getString(R.string.linged_copy_dialog, finalLibaoCode));
lunningAppDialog(context
, msg, libaoEntity);
}, 300);
}
}, null);
}
return null;
});
}
@Override

View File

@ -1,25 +1,32 @@
package com.gh.common.util;
import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.gh.common.constant.Constants;
import com.gh.common.exposure.ExposureEntity;
import com.gh.common.exposure.ExposureEvent;
import com.gh.common.exposure.ExposureSource;
import com.gh.common.exposure.meta.Meta;
import com.gh.common.exposure.meta.MetaUtil;
import com.gh.common.loghub.LoghubUtils;
import com.gh.download.DownloadDataHelper;
import com.gh.common.loghub.SimpleLogContainerEntity;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.entity.CommunityEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.ShareResultEntity;
import com.gh.gamecenter.entity.SpecialColumn;
import com.gh.gamecenter.manager.UserManager;
import com.gh.gamecenter.qa.entity.Questions;
import com.gh.gamecenter.retrofit.EmptyResponse;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.halo.assistant.HaloApp;
import com.lightgame.download.DownloadEntity;
import com.lightgame.utils.Util_System_Phone_State;
import com.lightgame.utils.Utils;
@ -29,7 +36,9 @@ import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.Nullable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.RequestBody;
/**
* Created by khy on 2/01/18.
@ -53,55 +62,6 @@ public class LogUtils {
uploadVideoStreaming(object);
}
public static void uploadDownloadEvent(DownloadEntity downloadEntity) {
Context context = HaloApp.getInstance().getApplication();
Meta meta = MetaUtil.INSTANCE.getMeta();
JSONObject object = new JSONObject();
try {
object.put("event", DownloadDataHelper.getDownloadStatusAlias(downloadEntity));
object.put("msg", downloadEntity.getError());
object.put("status", downloadEntity.getStatus().getStatus());
// payload
JSONObject payloadObject = new JSONObject();
payloadObject.put("game_id", downloadEntity.getGameId());
payloadObject.put("gameName", downloadEntity.getName());
payloadObject.put("platform", downloadEntity.getPlatform());
payloadObject.put("package", downloadEntity.getPackageName());
payloadObject.put("filename", downloadEntity.getPath().substring(downloadEntity.getPath().lastIndexOf("/") + 1));
payloadObject.put("total_size", (downloadEntity.getSize() / 1024 / 1024));
payloadObject.put("completed_size", (downloadEntity.getProgress() / 1024 / 1024));
object.put("payload", payloadObject);
// meta
JSONObject metaObject = new JSONObject();
metaObject.put("android_id", meta.getAndroid_id());
metaObject.put("android_sdk", meta.getAndroid_sdk());
metaObject.put("android_version", meta.getAndroid_version());
metaObject.put("appVersion", meta.getAppVersion());
metaObject.put("channel", meta.getChannel());
metaObject.put("gid", meta.getGid());
metaObject.put("imei", meta.getImei());
metaObject.put("mac", meta.getMac());
metaObject.put("manufacturer", meta.getManufacturer());
metaObject.put("model", meta.getModel());
metaObject.put("network", DeviceUtils.getNetwork(context));
metaObject.put("os", meta.getOs());
metaObject.put("userId", meta.getUserId());
object.put("meta", metaObject);
object.put("timestamp", System.currentTimeMillis() / 1000);
} catch (Exception e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "download_debug", false);
}
public static void uploadCommunityArticle(String tracers, String articleId, String articleTitle, int readTime, CommunityEntity community, SpecialColumn specialColumn) {
JSONObject object = new JSONObject();
try {
@ -420,6 +380,55 @@ public class LogUtils {
uploadVideoStreaming(object);
}
public static void uploadWelcomeDialog(String action, String dialogId, String linkTitle) {
ExposureEntity payload = new ExposureEntity();
payload.setWelcomeDialogId(dialogId);
payload.setWelcomeDialogId(linkTitle);
SimpleLogContainerEntity entity = new SimpleLogContainerEntity();
entity.setEvent("dialog");
entity.setAction(action);
entity.setMeta(MetaUtil.INSTANCE.getMeta());
entity.setPayload(payload);
entity.setTimestamp(System.currentTimeMillis() / 1000);
LoghubUtils.log(GsonUtils.toJsonIgnoreNull(entity), "event", false);
}
public static void uploadLikeFromWelcomeDialog() {
String dialogId = (String) HaloApp.get(Constants.WELCOME_DIALOG_ID, false);
String linkTitle = (String) HaloApp.get(Constants.WELCOME_DIALOG_LINK_TITLE, false);
ExposureEntity payload = new ExposureEntity();
payload.setWelcomeDialogId(dialogId);
payload.setWelcomeDialogLinkTitle(linkTitle);
SimpleLogContainerEntity entity = new SimpleLogContainerEntity();
entity.setEvent("like");
entity.setMeta(MetaUtil.INSTANCE.getMeta());
entity.setPayload(payload);
entity.setTimestamp(System.currentTimeMillis() / 1000);
LoghubUtils.log(GsonUtils.toJsonIgnoreNull(entity), "event", false);
}
public static void uploadCommentFromWelcomeDialog() {
String dialogId = (String) HaloApp.get(Constants.WELCOME_DIALOG_ID, false);
String linkTitle = (String) HaloApp.get(Constants.WELCOME_DIALOG_LINK_TITLE, false);
ExposureEntity payload = new ExposureEntity();
payload.setWelcomeDialogId(dialogId);
payload.setWelcomeDialogLinkTitle(linkTitle);
SimpleLogContainerEntity entity = new SimpleLogContainerEntity();
entity.setEvent("comment");
entity.setMeta(MetaUtil.INSTANCE.getMeta());
entity.setPayload(payload);
entity.setTimestamp(System.currentTimeMillis() / 1000);
LoghubUtils.log(GsonUtils.toJsonIgnoreNull(entity), "event", false);
}
private static void uploadShare(JSONObject object) {
Meta meta = MetaUtil.INSTANCE.getMeta();
JSONObject metaObject = new JSONObject();
@ -486,6 +495,7 @@ public class LogUtils {
uploadShare(object);
}
@SuppressLint("CheckResult")
public static void uploadShareResult(String shareType, String entrance, String shareResult, String url, String title, String summary, String resourceId) {
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
@ -503,5 +513,13 @@ public class LogUtils {
e.printStackTrace();
}
uploadShare(object);
ShareResultEntity entity = new ShareResultEntity(new ShareResultEntity.Content(url, title, summary), shareType, shareResult);
RequestBody body = RequestBody.create(MediaType.parse("application/json"), GsonUtils.toJson(entity));
RetrofitManager.getInstance(HaloApp.getInstance().getApplication()).getApi()
.postShareResult(body)
.subscribeOn(Schedulers.io())
.subscribe(new EmptyResponse<>());
}
}

View File

@ -2,7 +2,9 @@ package com.gh.common.util
import android.app.Activity
import android.content.Intent
import android.widget.Toast
import com.bytedance.sdk.open.aweme.authorize.model.Authorization
import com.bytedance.sdk.open.douyin.DouYinOpenApiFactory
import com.bytedance.sdk.open.douyin.DouYinOpenConfig
import com.gh.common.constant.Config
import com.gh.gamecenter.R
import com.gh.gamecenter.user.LoginTag
@ -89,6 +91,8 @@ object LoginHelper {
WbSdk.install(context, AuthInfo(context, Config.WEIBO_APPKEY, "http://www.sina.com", WEIBO_SCOPE))
DouYinOpenApiFactory.init(DouYinOpenConfig(Config.DOUYIN_CLIENTKEY))
Utils.log("LoginHelper initialization")
}
@ -107,6 +111,16 @@ object LoginHelper {
mLoginCallback?.get()?.onLoginFailure(LoginTag.wechat, error)
}
@JvmStatic
fun onDouYinLoginSuccess(content: JSONObject) {
mLoginCallback?.get()?.onLoginSuccess(LoginTag.douyin, content)
}
@JvmStatic
fun onDouYinLoginFailure(error: String) {
mLoginCallback?.get()?.onLoginFailure(LoginTag.douyin, error)
}
@JvmStatic
fun onWeiboLoginCallback(requestCode: Int, resultCode: Int, data: Intent?) {
mSsoHandler?.get()?.authorizeCallBack(requestCode, resultCode, data)
@ -159,7 +173,7 @@ object LoginHelper {
if (mAccessToken?.isSessionValid == true) {
// 保存 Token 到 SharedPreferences
AccessTokenKeeper.writeAccessToken(context, mAccessToken)
Toast.makeText(context, "授权成功", Toast.LENGTH_SHORT).show()
Utils.toast(context, "授权成功")
}
}
@ -187,6 +201,19 @@ object LoginHelper {
mAccessToken = AccessTokenKeeper.readAccessToken(context)
}
// 抖音登录
@JvmStatic
fun loginWithDouYin(loginCallback: LoginCallback, context: Activity) {
mLoginCallback = WeakReference(loginCallback)
val douYinOpenApi = DouYinOpenApiFactory.create(context)
val request = Authorization.Request()
request.scope = "user_info" // 用户授权时必选权限
//request.state = "ww"; // 用于保持请求和回调的状态,授权请求后原样带回给第三方。
//request.callerLocalEntry = "com.xxx.xxx...activity";
douYinOpenApi.authorize(request)
}
interface LoginCallback {
fun onLoginSuccess(loginType: LoginTag, jsonContent: JSONObject)

View File

@ -55,6 +55,7 @@ public class LoginUtils {
@Override
public void onFailure(HttpException e) {
super.onFailure(e);
listener.onCaptcha(null);
if (e == null) {
Utils.toast(context, "无法获取验证码,请检查你的网络状态");
return;

View File

@ -18,7 +18,7 @@ import io.reactivex.schedulers.Schedulers
object NotificationHelper {
@JvmStatic
fun showNotificationHintDialog(ugc: NotificationUgc) {
fun showNotificationHintDialog(ugc: NotificationUgc, callBack: ((isShow: Boolean) -> Unit)? = null) {
val showedNewVersion = SPUtils.getInt(Constants.SP_SHOWED_NOTIFICATION_NEW_VERSION, 0)
val currentVersion = PackageUtils.getVersionCode()
// 版本升级后重置数据
@ -29,6 +29,9 @@ object NotificationHelper {
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ARTICLE, false)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_VIDEO, false)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_RATING, false)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_GIFT, false)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_RESERVE_GAME, false)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_FEEDBACK, false)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, "")
SPUtils.setInt(Constants.SP_SHOWED_NOTIFICATION_NEW_VERSION, currentVersion)
@ -37,7 +40,10 @@ object NotificationHelper {
val isShowedToday = SPUtils.getString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, "")
// 每天最多只需提示一次
if (isShowedToday == TimeUtils.getToday()) return
if (isShowedToday == TimeUtils.getToday()){
callBack?.invoke(false)
return
}
val isShowedLogin = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, false)
val isShowedQuestion = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, false)
@ -45,78 +51,115 @@ object NotificationHelper {
val isShowedArticle = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_ARTICLE, false)
val isShowedVideo = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_VIDEO, false)
val isShowedRating = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_RATING, false)
val isShowedGift = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_GIFT, false)
val isShowedReserveGame = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_RESERVE_GAME, false)
val isShowedFeedback = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_FEEDBACK, false)
if (isShowedLogin && isShowedQuestion && isShowedAnswer && isShowedArticle && isShowedVideo && isShowedRating) return
if (isShowedLogin && isShowedQuestion && isShowedAnswer && isShowedArticle && isShowedVideo && isShowedRating && isShowedGift && isShowedReserveGame && isShowedFeedback) {
callBack?.invoke(false)
return
}
when (ugc) {
NotificationUgc.LOGIN -> {
if (!isShowedLogin) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, true)
// 设置今天的时间,表示今天已经触发过了
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
callBack?.invoke(false)
}
}
NotificationUgc.QUESTION -> {
if (!isShowedQuestion) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
callBack?.invoke(false)
}
}
NotificationUgc.ANSWER -> {
if (!isShowedAnswer) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ANSWER, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
callBack?.invoke(false)
}
}
NotificationUgc.ARTICLE -> {
if (!isShowedArticle) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ARTICLE, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
callBack?.invoke(false)
}
}
NotificationUgc.VIDEO -> {
if (!isShowedVideo) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_VIDEO, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
callBack?.invoke(false)
}
}
NotificationUgc.RATING -> {
if (!isShowedRating) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_RATING, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
callBack?.invoke(false)
}
}
NotificationUgc.GIFT -> {
if (!isShowedGift) {
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_GIFT, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
callBack?.invoke(false)
}
}
NotificationUgc.RESERVE_GAME -> {
if (!isShowedReserveGame) {
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_RESERVE_GAME, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
callBack?.invoke(false)
}
}
NotificationUgc.FEEDBACK -> {
if (!isShowedFeedback) {
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_FEEDBACK, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
callBack?.invoke(false)
}
}
}
}
@SuppressLint("CheckResult")
private fun show(activity: AppCompatActivity?) {
fun show(activity: AppCompatActivity?, ugc: NotificationUgc, callBack: ((isShow: Boolean) -> Unit)? = null) {
if (activity == null) return
RetrofitManager.getInstance(activity).api.bootPopup
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<NotificationHint>() {
override fun onSuccess(data: NotificationHint) {
try {
showEnableNotificationDialogIfItsDisabled(activity, data)
} catch (ignore: Exception) {
}
}
})
showEnableNotificationDialogIfItsDisabled(activity, ugc, callBack)
}
@JvmStatic
fun showEnableNotificationDialogIfItsDisabled(activity: AppCompatActivity, notificationHint: NotificationHint) {
fun showEnableNotificationDialogIfItsDisabled(activity: AppCompatActivity, ugc: NotificationUgc, callBack: ((isShow: Boolean) -> Unit)? = null) {
if (notificationIsEnable()) {
Utils.log("notification is enable")
callBack?.invoke(false)
} else {
NotificationHintDialogFragment.getInstance(notificationHint).show(activity.supportFragmentManager, "notification")
callBack?.invoke(true)
NotificationHintDialogFragment.getInstance(ugc).show(activity.supportFragmentManager, "notification")
}
}

View File

@ -16,6 +16,18 @@ object NumberUtils {
}
return s
}
@JvmStatic
fun transSimpleLetterCount(count: Int): String {
val s: String
s = if (count > 10000) {
val number = count / 10000f
val fmt = DecimalFormat("#.0")
fmt.format(number) + "W"
} else {
count.toString()
}
return s
}
@JvmStatic
fun transSimpleUsageTime(second: Long): String {

View File

@ -0,0 +1,129 @@
package com.gh.common.util
import android.app.Application
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import androidx.core.content.FileProvider
import com.gh.common.constant.Constants
import com.gh.common.xapk.XapkInstaller
import com.gh.gamecenter.BuildConfig
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.download.FileUtils
import com.lightgame.utils.Utils
import java.io.File
object PackageInstaller {
/**
* 为了兼容java代码
*/
@JvmStatic
fun install(context: Context, downloadEntity: DownloadEntity) {
install(context, downloadEntity, true)
}
/**
* 启动安装应用程序并取消通知栏安装消息
*
* 兼容所有包安装(apk,xapk),后续可加上apks
*
* 主动点击安装如果是xapk则需要toast提示
*/
@JvmStatic
fun install(context: Context, downloadEntity: DownloadEntity, showUnzipToast: Boolean) {
// 取消状态栏下载完成的通知,若存在
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
val pkgPath = downloadEntity.path
if (XapkInstaller.XAPK_EXTENSION_NAME == pkgPath.getExtension()) {
XapkInstaller.install(context, downloadEntity, showUnzipToast)
} else {
install(context, downloadEntity.path)
}
}
/**
* 启动安装应用程序
*
* 除非特殊情况,请勿使用此方法进行应用安装操作
* 除非你已经确定该文件一定是Apk
*/
@JvmStatic
fun install(context: Context, pkgPath: String) {
try {
if (PackageUtils.isCanLaunchSetup(context, pkgPath)) {
val installIntent = getInstallIntent(context, pkgPath)
context.startActivity(installIntent)
} else {
DialogUtils.showPluginDialog(context) {
uninstall(context, pkgPath)
}
}
} catch (e: Exception) {
Utils.toast(context, e.message)
}
}
/**
* 获取启动安装意图
*
* 除非特殊情况,请勿使用此方法进行应用安装操作
* 除非你已经确定该文件一定是Apk且该次安装无需检查签名情况
*/
@JvmStatic
fun getInstallIntent(context: Context, path: String): Intent {
var uri = Uri.fromFile(File(path))
val installIntent = Intent(Intent.ACTION_VIEW)
if ("smartisan" == Build.MANUFACTURER) {
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, File(path))
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
installIntent.setDataAndType(uri, "application/vnd.android.package-archive")
installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
} else {
// 应用内更新不加 FLAG_ACTIVITY_NEW_TASK 在模拟器上会出现安装完成后安装界面也一并消失的类似闪退的表现
// Application 上下文就更不用说了
val pkgName = PackageUtils.getPackageNameByPath(context, path)
if (pkgName == context.packageName || context is Application) {
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
installIntent.setDataAndType(uri, "application/vnd.android.package-archive")
}
InstallUtils.getInstance(context).addInstall(PackageUtils.getPackageNameByPath(context, path))
return installIntent
}
/**
* 卸载应用
*/
@JvmStatic
fun uninstall(context: Context, path: String) {
val uninstallIntent = Intent()
uninstallIntent.action = Intent.ACTION_DELETE
uninstallIntent.addCategory(Intent.CATEGORY_DEFAULT)
val packageName = PackageUtils.getPackageNameByPath(context, path)
uninstallIntent.data = Uri.parse("package:$packageName")
InstallUtils.getInstance(context).addUninstall(packageName)
context.startActivity(uninstallIntent)
}
@JvmStatic
fun getDownloadPath(gameName: String?, format: String?): String {
return FileUtils.getDownloadPath(HaloApp.getInstance().application, getDownloadFileName(gameName, format))
}
private fun getDownloadFileName(gameName: String?, format: String?): String {
var fileExtension = "apk"
if (format == XapkInstaller.XAPK_EXTENSION_NAME) {
fileExtension = XapkInstaller.XAPK_EXTENSION_NAME
}
return MD5Utils.getContentMD5(gameName + "_" + System.currentTimeMillis()) + "." + fileExtension
}
}

View File

@ -1,7 +1,6 @@
package com.gh.common.util;
import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@ -13,17 +12,18 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.g00fy2.versioncompare.Version;
import com.gh.common.constant.Constants;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.GameUpdateEntity;
import com.gh.gamecenter.manager.PackagesManager;
import com.halo.assistant.HaloApp;
import com.lightgame.download.DownloadEntity;
import com.lightgame.utils.Utils;
import org.json.JSONArray;
@ -31,7 +31,6 @@ import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
@ -42,9 +41,6 @@ import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;
public class PackageUtils {
public static final String publicKey = "OpenSSLRSAPublicKey{modulus=a8c4bb5748fec8d5c35db1a7a182d41ba4721a91131a417330af79ef4ddb43f9fa0ff4907b0a613bfe152de0ed8fc1b2e6f94a908aa98a5f7adc1ce814ba7ec919d75d9910bdfd8649b4789da6a90ffb61f0d23ac4f828a78fcd0d6f6120c1c43c1f87f7498a89eb40ca8e32dfc2f9d5c10d612b95192870223674e241e53305abf320d7eed76ded398778576e4db7b17b3bc6a792f13de5e43a6a5fae4276c73e6990ce97f68dff0ec16fc9594f175c8d49cd0d7877340d9de60942ca0efc737e50b6c295dfe0713e4532b4e810e1ea11b702b4a27753e41559cbceb247e7f044ec4e3ab2e8bccd8b9fd71286e63307550bcde86deee95adb8133076269135b,publicExponent=10001}";
@ -63,6 +59,8 @@ public class PackageUtils {
updateEntity.setId(gameEntity.getId());
updateEntity.setName(gameEntity.getName());
updateEntity.setIcon(gameEntity.getIcon());
updateEntity.setRawIcon(gameEntity.getRawIcon());
updateEntity.setIconSubscript(gameEntity.getIconSubscript());
updateEntity.setPackageName(apkEntity.getPackageName());
updateEntity.setSize(apkEntity.getSize());
updateEntity.setVersion(apkEntity.getVersion());
@ -76,6 +74,7 @@ public class PackageUtils {
updateEntity.setDownload(gameEntity.getDownload());
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
updateEntity.setPluginDesc(gameEntity.getPluginDesc());
updateEntity.setFormat(apkEntity.getFormat());
updateList.add(updateEntity);
}
}
@ -113,6 +112,7 @@ public class PackageUtils {
updateEntity.setTagStyle(gameEntity.getTagStyle());
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
updateEntity.setPluginDesc(gameEntity.getPluginDesc());
updateEntity.setFormat(apkEntity.getFormat());
updateList.add(updateEntity);
}
}
@ -232,29 +232,6 @@ public class PackageUtils {
return ret;
}
/*
* 启动安装应用程序
*/
public static void launchSetup(final Context context, DownloadEntity downloadEntity) {
// 取消状态栏下载完成的通知,若存在
downloadEntity.getMeta().put(Constants.MARK_ALREADY_TRIGGERED_INSTALLATION, "YES");
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity);
launchSetup(context, downloadEntity.getPath());
}
private static void launchSetup(final Context context, final String path) {
try {
if (isCanLaunchSetup(context, path)) {
context.startActivity(PackageUtils.getInstallIntent(context, path));
} else {
DialogUtils.showPluginDialog(context,
() -> context.startActivity(PackageUtils.getUninstallIntent(context, path)));
}
} catch (Exception e) {
Utils.toast(context, e.getMessage());
}
}
/**
* 根据 path 获取 apk 信息确定处理方式
*
@ -291,37 +268,6 @@ public class PackageUtils {
return compareSignatureBetweenInstalledAppWithApk(context, packageName, path);
}
/*
* 根据路径,获取安装游戏的意图
*/
public static Intent getInstallIntent(Context context, String path) {
return getInstallIntent(context, path, false);
}
public static Intent getInstallIntent(Context context, String path, boolean isInAppUpdate) {
Uri uri = Uri.fromFile(new File(path));
Intent installIntent = new Intent(Intent.ACTION_VIEW);
if ("smartisan".equals(Build.MANUFACTURER)) {
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, new File(path));
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
// 应用内更新不加 FLAG_ACTIVITY_NEW_TASK 在模拟器上会出现安装完成后安装界面也一并消失的类似闪退的表现
// Application 上下文就更不用说了
if (isInAppUpdate || context instanceof Application) {
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
}
InstallUtils.getInstance(context).addInstall(getPackageNameByPath(context, path));
return installIntent;
}
/*
* 根据包名,获取卸载游戏的意图
*/
@ -552,9 +498,10 @@ public class PackageUtils {
&& !TextUtils.isEmpty(apkEntity.getGhVersion())
&& !PackageUtils.isSignedByGh(HaloApp.getInstance().getApplication(), apkEntity.getPackageName());
}
/**
* 获取调用者的进程名
*
* @param context 调用者的上下文
* @return 进程名
*/
@ -571,5 +518,38 @@ public class PackageUtils {
}
return null;
}
/**
* 应用是否在前台运行
*/
public static boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getApplicationContext()
.getSystemService(Context.ACTIVITY_SERVICE);
if (activityManager == null) return false;
List<ActivityManager.RunningAppProcessInfo> appProcesses =
activityManager.getRunningAppProcesses();
if (appProcesses == null) return false;
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (pm == null) return false;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
if (!pm.isInteractive()) return false;
} else {
if (!pm.isScreenOn()) return false;
}
String packageName = context.getApplicationContext().getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
// The name of the process that this object is associated with.
if (appProcess.processName.equals(packageName) && appProcess.importance
== ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
return true;
}
}
return false;
}
}

View File

@ -120,7 +120,6 @@ public class PostCommentUtils {
final String commentId,
final PostCommentListener listener) {
Observable<ResponseBody> observable;
if (!TextUtils.isEmpty(answerId)) {
@ -260,7 +259,6 @@ public class PostCommentUtils {
});
}
public interface PostCommentListener {
void postSuccess(JSONObject response);

View File

@ -24,10 +24,9 @@ import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.facebook.common.references.CloseableReference;
import com.facebook.datasource.DataSource;
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
import com.facebook.imagepipeline.image.CloseableImage;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.gh.common.constant.Config;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WeiBoShareActivity;
@ -54,9 +53,6 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import static com.gh.common.util.LoginHelper.WEIBO_SCOPE;
/**
@ -72,7 +68,6 @@ public class ShareUtils {
private String mTitle;
private String mSummary;
private int[] arrLogo = {
R.drawable.share_wechat_logo,
R.drawable.share_wechatmoments_logo,
@ -247,17 +242,17 @@ public class ShareUtils {
e.printStackTrace();
}
contentView.setOnClickListener(v -> popupWindow.get().dismiss());
contentView.setOnClickListener(v -> safelyDismiss());
contentView.setOnKeyListener((v, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.getRepeatCount() == 0
&& popupWindow != null
&& popupWindow.get() != null
&& popupWindow.get().isShowing()) {
if (callBack != null) {
callBack.onCancel();
}
popupWindow.get().dismiss();
safelyDismiss();
}
return false;
});
@ -298,7 +293,7 @@ public class ShareUtils {
}
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
safelyDismiss();
}
}
@ -336,9 +331,9 @@ public class ShareUtils {
req.message = msg;
req.scene = SendMessageToWX.Req.WXSceneSession;
loadBitMap(shareIcon, msg, req);
loadBitmapAndShare(shareIcon, msg, req);
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
safelyDismiss();
}
}
@ -346,10 +341,10 @@ public class ShareUtils {
return (type == null) ? String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis();
}
private void loadBitMap(final String iconUrl, final WXMediaMessage msg, final SendMessageToWX.Req req) {
ImageUtils.display(mContext, iconUrl, new BaseBitmapDataSubscriber() {
private void loadBitmapAndShare(final String iconUrl, final WXMediaMessage msg, final SendMessageToWX.Req req) {
ImageUtils.getBitmap(iconUrl, new BiCallback<Bitmap, Boolean>() {
@Override
protected void onNewResultImpl(Bitmap bitmap) {
public void onFirst(Bitmap bitmap) {
if (mShareEntrance == ShareEntrance.video) {
// 分享类型为视频时裁为正方形
int dimension = Math.min(bitmap.getWidth(), bitmap.getHeight());
@ -367,8 +362,7 @@ public class ShareUtils {
}
@Override
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
Utils.log("分享获取bitmap失败");
public void onSecond(Boolean aBoolean) {
}
});
}
@ -454,7 +448,7 @@ public class ShareUtils {
}
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
safelyDismiss();
}
}
@ -497,9 +491,9 @@ public class ShareUtils {
req.message = msg;
req.scene = SendMessageToWX.Req.WXSceneTimeline;
loadBitMap(shareIcon, msg, req);
loadBitmapAndShare(shareIcon, msg, req);
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
safelyDismiss();
}
}
@ -520,7 +514,7 @@ public class ShareUtils {
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
safelyDismiss();
}
}
@ -562,8 +556,8 @@ public class ShareUtils {
e.printStackTrace();
}
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
if (mShareEntrance != ShareEntrance.shareGh ) {
safelyDismiss();
}
}
@ -575,7 +569,7 @@ public class ShareUtils {
cmb.setText(copyContent);
if (mShareEntrance != ShareEntrance.shareGh) {
Utils.toast(mContext, "复制成功");
popupWindow.get().dismiss();
safelyDismiss();
} else {
Utils.toast(mContext, "复制成功,请到微信/QQ粘贴分享");
}
@ -661,7 +655,7 @@ public class ShareUtils {
break;
case 7:
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
safelyDismiss();
} else {
shareType = "copy_link";
LogUtils.uploadShareType(shareType, shareEntrance.getName(), shareUrl, mTitle, mSummary, resourceId);
@ -689,6 +683,12 @@ public class ShareUtils {
}
}
}
private void safelyDismiss() {
if (popupWindow.get() != null) {
popupWindow.get().dismiss();
}
}
interface OnItemClickListener {
void onItemClick(int position);

View File

@ -5,10 +5,9 @@ import android.graphics.Color
import android.graphics.Typeface
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.AbsoluteSizeSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StrikethroughSpan
import android.text.style.StyleSpan
import android.text.TextPaint
import android.text.style.*
import android.view.View
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import com.gh.common.view.CenterImageSpan
@ -23,6 +22,12 @@ class SpanBuilder(content: String) {
return this
}
fun color(start: Int, end: Int, colorRes: Int): SpanBuilder {
val colorSpan = ForegroundColorSpan(ContextCompat.getColor(HaloApp.getInstance().application, colorRes))
spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
return this
}
fun color(start: Int, end: Int, colorHexInString: String): SpanBuilder {
tryWithDefaultCatch {
val colorSpan = ForegroundColorSpan(Color.parseColor(colorHexInString))
@ -65,6 +70,23 @@ class SpanBuilder(content: String) {
return this
}
fun click(start: Int, end: Int, colorRes: Int, onClick: () -> Unit): SpanBuilder {
val clickSpan = object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds)
ds.color = ContextCompat.getColor(HaloApp.getInstance().application, colorRes)
ds.isUnderlineText = false
}
override fun onClick(widget: View) {
onClick.invoke()
}
}
spannableString.setSpan(clickSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
return this
}
fun build(): SpannableStringBuilder {
return spannableString
}

View File

@ -23,6 +23,7 @@ object TimeUtils {
fun getFormatTime(time: Long, pattern: String = "yyyy-MM-dd"): String {
val f = SimpleDateFormat(pattern, Locale.CHINA)
f.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
return f.format(Date(time * 1000))
}
@ -84,4 +85,19 @@ object TimeUtils {
val second = length % 60
return String.format(Locale.CHINA, "%02d:%02d", minute, second)
}
@JvmStatic
fun getDayString(date: Long): String {
val offSet = Calendar.getInstance().timeZone.rawOffset
val today = (System.currentTimeMillis() + offSet) / 86400000
val start = (date * 1000 + offSet) / 86400000
return when ((start - today).toInt()) {
-2 -> "(前天)"
-1 -> "(昨天)"
0 -> "(今天)"
1 -> "(明天)"
2 -> "(后天)"
else -> ""
}
}
}

View File

@ -3,6 +3,7 @@ package com.gh.common.util
import android.widget.Toast
import com.halo.assistant.HaloApp
import com.lightgame.utils.toast.ToastHandler
object ToastUtils {
/** 之前显示的内容 */
@ -32,7 +33,7 @@ object ToastUtils {
*/
fun showToast(message: String, gravity: Int = -1, yOffset: Int = 0) {
if (mToast == null) {
mToast = Toast.makeText(HaloApp.getInstance().application, message, Toast.LENGTH_SHORT)
mToast = ToastHandler.INSTANCE.getToastInstance(HaloApp.getInstance().application, message, Toast.LENGTH_SHORT)
if (gravity != -1) mToast!!.setGravity(gravity, 0, yOffset) else
mToast!!.setGravity(DisplayUtils.getToastDefaultGravity(), 0, DisplayUtils.getToastOffset())
mToast!!.show()

View File

@ -61,7 +61,7 @@ object VideoRecordUtils {
if (!UserManager.getInstance().isLoggedIn) return
val requestMap = HashMap<String, Any>()
val videoIds = videoRecordSet.toList().map { it.videoId }
requestMap["g_id"] = HaloApp.getInstance().gid
requestMap["g_id"] = HaloApp.getInstance().gid ?: ""
requestMap["time"] = time
requestMap["video_id"] = videoIds
RetrofitManager.getInstance(HaloApp.getInstance().application).api

View File

@ -5,10 +5,12 @@ import android.graphics.drawable.Animatable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
@ -19,6 +21,7 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.gh.gamecenter.R;
import com.scwang.smartrefresh.layout.api.RefreshInternal;
import com.scwang.smartrefresh.layout.api.RefreshKernel;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
@ -74,21 +77,21 @@ public abstract class AbstractSwipeRefreshHeader<T extends AbstractSwipeRefreshH
progressView.setId(ID_IMAGE_PROGRESS);
centerLayout.setId(android.R.id.widget_frame);
LinearLayout.LayoutParams lpHeaderText = new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
centerLayout.addView(titleView, lpHeaderText);
// LinearLayout.LayoutParams lpHeaderText = new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
// centerLayout.addView(titleView, lpHeaderText);
RelativeLayout.LayoutParams lpHeaderLayout = new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
lpHeaderLayout.addRule(CENTER_IN_PARENT);
thisGroup.addView(centerLayout, lpHeaderLayout);
RelativeLayout.LayoutParams lpArrow = new RelativeLayout.LayoutParams(mDensityUtil.dip2px(15), mDensityUtil.dip2px(15));
RelativeLayout.LayoutParams lpArrow = new RelativeLayout.LayoutParams(mDensityUtil.dip2px(35), mDensityUtil.dip2px(35));
lpArrow.addRule(CENTER_VERTICAL);
lpArrow.addRule(LEFT_OF, android.R.id.widget_frame);
lpArrow.addRule(CENTER_IN_PARENT, android.R.id.widget_frame);
thisGroup.addView(arrowView, lpArrow);
RelativeLayout.LayoutParams lpProgress = new RelativeLayout.LayoutParams((ViewGroup.LayoutParams) lpArrow);
lpProgress.addRule(CENTER_VERTICAL);
lpProgress.addRule(LEFT_OF, android.R.id.widget_frame);
lpProgress.addRule(CENTER_IN_PARENT, android.R.id.widget_frame);
progressView.animate().setInterpolator(new LinearInterpolator());
thisGroup.addView(progressView, lpProgress);

View File

@ -190,8 +190,8 @@ class AdBannerView : LinearLayout {
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val ad = mDatas[position % mDatas.size]
val view = holder.itemView as ImageView
Picasso.with(context).load(ad.image).into(view)
val view = holder.itemView as SimpleDraweeView
ImageUtils.display(view,ad.image)
holder.itemView.setOnClickListener {
onItemClick?.invoke(position % mDatas.size)
}

View File

@ -47,7 +47,7 @@ public class ClearEditTextNormal extends androidx.appcompat.widget.AppCompatEdit
mClearDrawable = getCompoundDrawables()[2];
if (mClearDrawable == null) {
// throw new NullPointerException("You can add drawableRight attribute in XML");
mClearDrawable = getResources().getDrawable(R.drawable.icon_close);
mClearDrawable = getResources().getDrawable(R.drawable.icon_input_close);
}
// mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());

View File

@ -13,8 +13,8 @@ import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.gh.common.util.DisplayUtils
import com.gh.common.view.ConfigFilterView.SortSize.Companion.SORT_SIZE_LIST
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.google.android.flexbox.FlexboxLayout
class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
@ -26,6 +26,8 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
var ratingTv: TextView //目前只在专题页面显示
var recommendedTv: TextView
var sizeFilterArray: ArrayList<SubjectSettingEntity.Size>? = null
private var mOnConfigFilterSetupListener: OnConfigFilterSetupListener? = null
init {
@ -37,6 +39,7 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
recommendedTv = findViewById(R.id.recommended_tv)
mSizeTv.setOnClickListener {
mOnConfigFilterSetupListener?.onShowSortSize()
showSelectionPopupWindow(this, mSizeTv, mSizeTv.text.toString())
}
@ -98,12 +101,21 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
val backgroundView = layout.findViewById<View>(R.id.background)
sizeFilterArray = if (sizeFilterArray == null) {
getDefaultSizeFilterArray()
} else {
sizeFilterArray?.apply {
if (firstOrNull()?.text != "全部大小") {
add(0, SubjectSettingEntity.Size(min = -1, max = -1, text = "全部大小"))
}
}
}
backgroundView.setOnClickListener {
popupWindow.dismiss()
}
for ((index, sortSizeText) in SORT_SIZE_LIST.withIndex()) {
for (size in sizeFilterArray!!) {
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
// 单列 4 个,强行设置宽度为屏幕的 1/4
@ -114,22 +126,22 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
flexboxLayout.addView(item)
val tv = item.findViewById<TextView>(R.id.size_tv)
tv.text = sortSizeText
tv.text = size.text
if (sizeText == sortSizeText) {
if (sizeText == size.text) {
toggleHighlightedTextView(tv, true)
} else {
toggleHighlightedTextView(tv, false)
}
tv.tag = SortSize.values()[index]
tv.tag = size.text
item.setOnClickListener {
toggleHighlightedTextView(tv, true)
popupWindow.dismiss()
sizeTv.text = sortSizeText
sizeTv.text = size.text
mOnConfigFilterSetupListener?.onSetupSortSize(tv.tag as SortSize)
mOnConfigFilterSetupListener?.onSetupSortSize(size)
}
}
@ -145,8 +157,20 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
popupWindow.showAsDropDown(containerView, 0, 0)
}
private fun getDefaultSizeFilterArray(): ArrayList<SubjectSettingEntity.Size> {
return arrayListOf<SubjectSettingEntity.Size>().apply {
add(SubjectSettingEntity.Size(min = -1, max = -1, text = "全部大小"))
add(SubjectSettingEntity.Size(min = -1, max = 20, text = "20M以下"))
add(SubjectSettingEntity.Size(min = 20, max = 50, text = "20-50M"))
add(SubjectSettingEntity.Size(min = 50, max = 100, text = "50-100M"))
add(SubjectSettingEntity.Size(min = 100, max = 500, text = "100-500M"))
add(SubjectSettingEntity.Size(min = 500, max = -1, text = "500M以上"))
}
}
interface OnConfigFilterSetupListener {
fun onSetupSortSize(sortSize: SortSize)
fun onShowSortSize()
fun onSetupSortSize(sortSize: SubjectSettingEntity.Size)
fun onSetupSortType(sortType: SortType)
}
@ -156,41 +180,4 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
RATING
}
enum class SortSize(val value: String) {
UNSPECIFIED("全部大小"),
SMALLER_THAN_20M("20M以下"),
BETWEEN_20M_AND_50M("20-50M"),
BETWEEN_50M_AND_100M("50-100M"),
BETWEEN_100M_AND_500M("100-500M"),
LARGER_THAN_500M("500M以上");
override fun toString() = value
fun toSize(): Size {
return when (this) {
UNSPECIFIED -> Size(minSize = -1, maxSize = -1)
SMALLER_THAN_20M -> Size(minSize = -1, maxSize = 20)
BETWEEN_20M_AND_50M -> Size(minSize = 20, maxSize = 50)
BETWEEN_50M_AND_100M -> Size(minSize = 50, maxSize = 100)
BETWEEN_100M_AND_500M -> Size(minSize = 100, maxSize = 500)
LARGER_THAN_500M -> Size(minSize = 500, maxSize = -1)
}
}
companion object {
val SORT_SIZE_LIST = arrayListOf<String>().apply {
values().iterator().forEach {
this.add(it.toString())
}
}
}
data class Size(var minSize: Int = -1, var maxSize: Int = -1)
}
}

View File

@ -9,6 +9,8 @@ import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import com.gh.common.util.DisplayUtils;
public class CropImageBorderView extends View {
/**
@ -28,7 +30,7 @@ public class CropImageBorderView extends View {
*/
private int mBorderWidth = 1;
private Paint mPaint, mPaintRect;
private Paint mPaint, mPaintRect, mAnglePaint;
private float mRatio = 1; // 宽高比
@ -48,7 +50,7 @@ public class CropImageBorderView extends View {
// 绘制阴影
mPaintRect = new Paint();
mPaintRect.setARGB(136, 0, 0, 0);
mPaintRect.setARGB(80, 0, 0, 0);
mPaintRect.setStyle(Style.FILL);
// 绘制边框
@ -56,7 +58,12 @@ public class CropImageBorderView extends View {
mPaint.setStyle(Style.STROKE);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.WHITE);
mPaint.setStrokeWidth(mBorderWidth);
mPaint.setStrokeWidth(0.5F);
// 绘制边框
mAnglePaint = new Paint();
mAnglePaint.setStyle(Style.FILL);
mAnglePaint.setColor(Color.WHITE);
}
@ -86,6 +93,45 @@ public class CropImageBorderView extends View {
canvas.drawRect(mHorizontalPadding, mVerticalPadding,
mHorizontalPadding + mWidth, getHeight() - mVerticalPadding, mPaint);
// 左上
canvas.drawRect(mHorizontalPadding - DisplayUtils.dip2px(1F)
, mVerticalPadding - DisplayUtils.dip2px(1F)
, mHorizontalPadding + DisplayUtils.dip2px(16F)
, mVerticalPadding + DisplayUtils.dip2px(1F), mAnglePaint);
canvas.drawRect(mHorizontalPadding - DisplayUtils.dip2px(1F)
, mVerticalPadding - DisplayUtils.dip2px(1F)
, mHorizontalPadding + DisplayUtils.dip2px(1F)
, mVerticalPadding + DisplayUtils.dip2px(16F), mAnglePaint);
// 右上
canvas.drawRect(mHorizontalPadding + mWidth - DisplayUtils.dip2px(16F)
, mVerticalPadding - DisplayUtils.dip2px(1F)
, mHorizontalPadding + mWidth
, mVerticalPadding + DisplayUtils.dip2px(1F), mAnglePaint);
canvas.drawRect(mHorizontalPadding + mWidth - DisplayUtils.dip2px(1F)
, mVerticalPadding - DisplayUtils.dip2px(1F)
, mHorizontalPadding + mWidth + DisplayUtils.dip2px(1F)
, mVerticalPadding + DisplayUtils.dip2px(16F), mAnglePaint);
// 左下
canvas.drawRect(mHorizontalPadding - DisplayUtils.dip2px(1F)
, getHeight() - mVerticalPadding - DisplayUtils.dip2px(16F)
, mHorizontalPadding + DisplayUtils.dip2px(1F)
, getHeight() - mVerticalPadding - DisplayUtils.dip2px(1F), mAnglePaint);
canvas.drawRect(mHorizontalPadding - DisplayUtils.dip2px(1F)
, getHeight() - mVerticalPadding - DisplayUtils.dip2px(1F)
, mHorizontalPadding + DisplayUtils.dip2px(16F)
, getHeight() - mVerticalPadding + DisplayUtils.dip2px(1F), mAnglePaint);
// 右下
canvas.drawRect(mHorizontalPadding + mWidth - DisplayUtils.dip2px(16F)
, getHeight() - mVerticalPadding - DisplayUtils.dip2px(1F)
, mHorizontalPadding + mWidth
, getHeight() - mVerticalPadding + DisplayUtils.dip2px(1F), mAnglePaint);
canvas.drawRect(mHorizontalPadding + mWidth - DisplayUtils.dip2px(1F)
, getHeight() - mVerticalPadding - DisplayUtils.dip2px(16F)
, mHorizontalPadding + mWidth + DisplayUtils.dip2px(1F)
, getHeight() - mVerticalPadding + DisplayUtils.dip2px(1F), mAnglePaint);
}
public void setHorizontalPadding(int mHorizontalPadding, float ratio) {

View File

@ -2,7 +2,6 @@ package com.gh.common.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ImageView;
@ -58,24 +57,17 @@ public class CropImageCustom extends RelativeLayout {
return mZoomImageView.clip();
}
// 用户头像压缩规则
public boolean savePicture(String path) {
float limitSize = 900;
int quality = 90;
Bitmap bitmap = mZoomImageView.clip();
File file = new File(path);
if (bitmap.getHeight() > limitSize || bitmap.getWidth() > limitSize) {
Matrix matrix = new Matrix();
matrix.setScale(limitSize / bitmap.getWidth(), limitSize / bitmap.getHeight());
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
try {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.WEBP, quality, bos);
bos.flush();
bos.close();
Bitmap clip = mZoomImageView.clip();
try {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(path)));
clip.compress(Bitmap.CompressFormat.WEBP, 100, bos);
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
return false;

View File

@ -318,11 +318,18 @@ public class CropImageZoomView extends AppCompatImageView implements
if (dw <= getWidth() - mHorizontalPadding * 2
&& dh <= getHeight() - mVerticalPadding * 2) {// 如果图片的高度<截图区高度,并且图片宽度<截图区宽度时
float scaleW = (getWidth() * 1.0f - mHorizontalPadding * 2)
/ dw;
float scaleW = (getWidth() * 1.0f - mHorizontalPadding * 2) / dw;
float scaleH = (getHeight() * 1.0f - mVerticalPadding * 2) / dh;
scale = Math.max(scaleW, scaleH);
}
// 宽、高均超出截图区域
if (dw > getWidth() - mHorizontalPadding * 2 && dh > getHeight() - mVerticalPadding * 2) {
float scaleW = (getWidth() * 1.0f - mHorizontalPadding * 2) / dw;
float scaleH = (getHeight() * 1.0f - mVerticalPadding * 2) / dh;
scale = Math.max(scaleW, scaleH);
}
initScale = scale;
SCALE_MID = initScale * 2;
SCALE_MAX = initScale * 4;

View File

@ -0,0 +1,25 @@
package com.gh.common.view
import android.content.Context
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.gh.common.util.DisplayUtils
import com.gh.common.util.dip2px
import com.gh.gamecenter.R
import com.github.mikephil.charting.components.MarkerView
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.highlight.Highlight
import com.github.mikephil.charting.utils.MPPointF
class CustomMarkerView(context: Context) : MarkerView(context, R.layout.layout_chart_markerview) {
var markerView: TextView = findViewById(R.id.markerView)
override fun refreshContent(e: Entry, highlight: Highlight?) {
markerView.text = e.y.toInt().toString()
super.refreshContent(e, highlight)
}
override fun getOffset(): MPPointF {
return MPPointF((-(width / 2)).toFloat(), (-height).toFloat() - 3f.dip2px())
}
}

View File

@ -0,0 +1,19 @@
package com.gh.common.view
import android.content.Context
import android.util.AttributeSet
import android.widget.LinearLayout
/**
* 自定义ViewGroup中child绘制顺序
*/
class CustomOrderDrawChildLinearLayout(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {
override fun isChildrenDrawingOrderEnabled(): Boolean {
return true
}
override fun getChildDrawingOrder(childCount: Int, i: Int): Int {
return childCount - i - 1//倒序
}
}

View File

@ -15,12 +15,12 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ProgressBar;
import com.gh.common.util.DisplayUtils;
import com.gh.gamecenter.R;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import com.gh.common.util.DisplayUtils;
import com.gh.gamecenter.R;
public class DownloadProgressBar extends ProgressBar {
public static final int MAX_LENGTH = 1000;
public static final int DOWNLOAD_NORMAL_STYLE = 0;
@ -38,7 +38,11 @@ public class DownloadProgressBar extends ProgressBar {
DOWNLOADING_PLUGIN,
RESERVABLE,
RESERVED,
H5_GAME
H5_GAME,
XAPK_UNZIPPING,
XAPK_SUCCESS,
XAPK_FAILURE,
}
private PorterDuffXfermode mDuffXFerMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
@ -214,6 +218,12 @@ public class DownloadProgressBar extends ProgressBar {
setProgressDrawable(getResources().getDrawable(R.drawable.game_item_btn_pause_dn));
mDefaultColor = ContextCompat.getColor(getContext(), R.color.all_white);
break;
case XAPK_FAILURE:
case XAPK_SUCCESS:
case XAPK_UNZIPPING:
setProgressDrawable(getResources().getDrawable(R.drawable.progressbar_xapk_detail_style));
mDefaultColor = ContextCompat.getColor(getContext(), R.color.all_white);
break;
}
mDownloadType = downloadType;

View File

@ -0,0 +1,117 @@
package com.gh.common.view
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.ViewConfiguration
import com.github.piasy.biv.view.BigImageView
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
import kotlin.math.sqrt
class DraggableBigImageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
: BigImageView(context, attrs, defStyle) {
private var mInitScale: Float? = null
private val mScaledTouchSlop by lazy { ViewConfiguration.get(context).scaledTouchSlop }
private val mDismissEdge by lazy { height * 0.12 }
private var mSingleTouch = true
private var mFakeDragOffset = 0F
private var mLastX = 0F
private var mLastY = 0F
private var mListener: DragListener? = null
fun setDragListener(listener: DragListener) {
mListener = listener
}
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
when (event.actionMasked) {
MotionEvent.ACTION_POINTER_DOWN -> {
setSingleTouch(false)
animate()
.translationX(0F).translationY(0F).scaleX(1F).scaleY(1F)
.setDuration(200).start()
}
MotionEvent.ACTION_DOWN -> if (mInitScale == null || mInitScale == 0F) mInitScale = ssiv?.scale
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> up()
MotionEvent.ACTION_MOVE -> {
if (mSingleTouch && mInitScale != 0F && ssiv?.scale == mInitScale) {
if (mLastX == 0F) mLastX = event.rawX
if (mLastY == 0F) mLastY = event.rawY
val offsetX = event.rawX - mLastX
val offsetY = event.rawY - mLastY
fakeDrag(offsetX, offsetY)
}
}
}
return super.dispatchTouchEvent(event)
}
private fun fakeDrag(offsetX: Float, offsetY: Float) {
if (mFakeDragOffset == 0F) {
// 大于60度才响应下拉消失
if (abs(offsetY) / sqrt(3F) > abs(offsetX)) {
if (offsetY > mScaledTouchSlop) {
mFakeDragOffset = mScaledTouchSlop.toFloat()
} else if (offsetY < -mScaledTouchSlop) {
mFakeDragOffset = (-mScaledTouchSlop).toFloat()
}
}
}
if (mFakeDragOffset != 0F) {
val fixedOffsetY = offsetY - mFakeDragOffset
parent?.requestDisallowInterceptTouchEvent(true)
val fraction = abs(max(-1F, min(1F, fixedOffsetY / height)))
val fakeScale = 1 - min(0.4F, fraction)
scaleX = fakeScale
scaleY = fakeScale
translationY = fixedOffsetY
translationX = offsetX / 2
mListener?.onDrag(this, fraction)
}
}
private fun up() {
parent?.requestDisallowInterceptTouchEvent(false)
setSingleTouch(true)
mFakeDragOffset = 0F
mLastX = 0F
mLastY = 0F
if (abs(translationY) > mDismissEdge) {
mListener?.onRelease(this, scaleX)
} else {
val offsetY = translationY
val fraction = min(1F, offsetY / height)
mListener?.onRestore(this, fraction)
animate().translationX(0F)
.translationY(0F)
.scaleX(1F)
.scaleY(1F)
.setDuration(200).start()
}
}
fun isDragging(): Boolean {
return mFakeDragOffset != 0F
}
private fun setSingleTouch(value: Boolean) {
mSingleTouch = value
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
animate().cancel()
}
interface DragListener {
fun onDrag(draggableBigImageView: DraggableBigImageView, fraction: Float)
fun onRelease(draggableBigImageView: DraggableBigImageView, scale: Float)
fun onRestore(draggableBigImageView: DraggableBigImageView, fraction: Float)
}
}

View File

@ -194,6 +194,8 @@ public class ExpandTextView extends AppCompatTextView {
msp.replace(expandTextStartPosition, length, finalEndText + mExpandText);
if (expandTextStartPosition + mEndText.length() >= msp.length()) return;
msp.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(@NonNull TextPaint ds) {

View File

@ -24,7 +24,8 @@ public class FixLinearLayoutManager extends LinearLayoutManager {
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
try {
super.onLayoutChildren(recycler, state);
} catch (Exception ignore) {
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,24 @@
package com.gh.common.view
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.widget.ScrollView
/**
* 不能滑动的 ScrollView
*/
class FixedScrollView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : ScrollView(context, attrs) {
override fun onTouchEvent(ev: MotionEvent?): Boolean {
return when (ev?.action) {
MotionEvent.ACTION_DOWN -> true
else -> super.onTouchEvent(ev)
}
}
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
return true
}
}

View File

@ -0,0 +1,68 @@
package com.gh.common.view
import android.content.Context
import android.text.TextUtils
import android.util.AttributeSet
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import com.facebook.drawee.generic.RoundingParams
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.common.util.DisplayUtils
import com.gh.common.util.ImageUtils
import com.gh.common.util.goneIf
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.GameEntity
import kotlinx.android.synthetic.main.layout_game_icon.view.*
class GameIconView : ConstraintLayout {
private var mCornerRadius = 10
private var mBorderColor = 0
private var mBorderWidth = 1
constructor(context: Context) : super(context, null)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs, 0) {
initView(attrs)
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
initView(attrs)
}
fun initView(attrs: AttributeSet) {
View.inflate(context, R.layout.layout_game_icon, this)
val ta = context.obtainStyledAttributes(attrs, R.styleable.GameIconView)
mCornerRadius = ta.getDimensionPixelSize(R.styleable.GameIconView_gameIconCornerRadius, DisplayUtils.dip2px(10F))
mBorderColor = ta.getColor(R.styleable.GameIconView_gameIconBorderColor, 0)
mBorderWidth = ta.getDimensionPixelSize(R.styleable.GameIconView_gameIconBorderWidth, 1)
ta.recycle()
val roundingParams = RoundingParams.fromCornersRadius(mCornerRadius.toFloat())
if (mBorderColor != 0) {
roundingParams.setBorder(mBorderColor, mBorderWidth.toFloat())
}
gameIconIv.hierarchy.roundingParams = roundingParams
gameIconDecoratorIv.hierarchy.roundingParams = roundingParams
}
fun displayGameIcon(game: GameEntity) {
if (!TextUtils.isEmpty(game.rawIcon)) {
displayGameIcon(game.rawIcon ?: "", game.iconSubscript)
} else {
displayGameIcon(game.icon ?: "", null)
}
}
fun displayGameIcon(icon: String?, iconSubscript: String?) {
ImageUtils.display(gameIconIv, icon)
ImageUtils.display(gameIconDecoratorIv, iconSubscript)
gameIconDecoratorIv.goneIf(TextUtils.isEmpty(iconSubscript))
}
fun getIconIv(): SimpleDraweeView = gameIconIv
fun getIconDecoratorIv(): SimpleDraweeView = gameIconDecoratorIv
}

View File

@ -4,9 +4,10 @@ import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
import com.gh.common.util.DisplayUtils;
public class HorizontalItemDecoration extends RecyclerView.ItemDecoration {
@ -14,6 +15,7 @@ public class HorizontalItemDecoration extends RecyclerView.ItemDecoration {
private Paint paint;
private int mInterval = 0;
private int mSize = 0;
private boolean mIncludeEnd = false;
public HorizontalItemDecoration(Context context, int interval, int size) {
paint = new Paint();
@ -22,6 +24,15 @@ public class HorizontalItemDecoration extends RecyclerView.ItemDecoration {
mSize = size;
}
public HorizontalItemDecoration(Context context, int interval, int size, boolean includeEnd) {
paint = new Paint();
paint.setColor(Color.WHITE);
mInterval = DisplayUtils.dip2px(context, interval);
mSize = size;
mIncludeEnd = includeEnd;
}
// @Override
// public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
// int top = parent.getPaddingTop();
@ -39,7 +50,7 @@ public class HorizontalItemDecoration extends RecyclerView.ItemDecoration {
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
if (parent.getChildPosition(view) == mSize - 1) {
if (!mIncludeEnd && parent.getChildPosition(view) == mSize - 1) {
outRect.set(0, 0, 0, 0);
} else {
outRect.set(0, 0, mInterval, 0);

View File

@ -9,13 +9,14 @@ import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.view.View;
import androidx.appcompat.widget.AppCompatTextView;
import com.gh.gamecenter.R;
import java.util.ArrayList;
import java.util.List;
public class MessageSpannableTextView extends androidx.appcompat.widget.AppCompatTextView {
public class MessageSpannableTextView extends AppCompatTextView {
private OnSpannableClickListener mSpannableClickListener;

View File

@ -269,6 +269,7 @@ public class NestedScrollWebView2 extends DWebView implements NestedScrollingChi
ev.setAction(MotionEvent.ACTION_CANCEL);
returnValue = super.onTouchEvent(ev);
}
initVelocityTrackerIfNotExists();
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);

View File

@ -0,0 +1,26 @@
package com.gh.common.view;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.ScrollView;
public class NoScrollFocusScrollView extends ScrollView {
public NoScrollFocusScrollView(Context context) {
super(context);
}
public NoScrollFocusScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NoScrollFocusScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
return 0;
}
}

View File

@ -14,11 +14,11 @@ import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.gh.common.DefaultJsApi;
import com.gh.common.constant.Config;
import com.gh.common.util.DeviceUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EmptyCallback;
import com.gh.common.util.GsonUtils;
import com.gh.common.util.HtmlUtils;
import com.gh.common.util.ImageUtils;
@ -69,6 +69,10 @@ public class RichEditor extends WebView {
private int mDefaultImageWidth;
private int mThumbnailImageWidth;
private EmptyCallback mInitialLayoutCallback;
private String mCurrentContent = "";
public enum Type {
BOLD,
ITALIC,
@ -173,6 +177,10 @@ public class RichEditor extends WebView {
mChromeClientListener = chromeClientListener;
}
public void setLayoutCallback(EmptyCallback layoutCallback) {
mInitialLayoutCallback = layoutCallback;
}
private void callback(String text) {
mContents = text.replaceFirst(CALLBACK_SCHEME, "");
if (mTextChangeListener != null) {
@ -594,6 +602,10 @@ public class RichEditor extends WebView {
this.mContentOwner = contentOwner;
}
public String getCurrentContent() {
return mCurrentContent;
}
public interface WebChromeClientListener {
void onPageFinished(WebView view, String url);
@ -720,4 +732,15 @@ public class RichEditor extends WebView {
}
}
}
@Override
public void invalidate() {
super.invalidate();
if (mInitialLayoutCallback != null &&getHeight() > 0) {
// 仅初次 layout 完成会有回调
mInitialLayoutCallback.onCallback();
mInitialLayoutCallback = null;
}
}
}

View File

@ -1,9 +1,8 @@
package com.gh.common.view;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
@ -11,6 +10,9 @@ import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import com.scwang.smartrefresh.layout.R;
import com.scwang.smartrefresh.layout.api.RefreshHeader;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
@ -23,6 +25,7 @@ import com.scwang.smartrefresh.layout.util.DensityUtil;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
@SuppressLint("RestrictedApi")
@SuppressWarnings({"unused", "UnusedReturnValue"})
public class SwipeRefreshHeader extends AbstractSwipeRefreshHeader<SwipeRefreshHeader> implements RefreshHeader {
@ -83,7 +86,7 @@ public class SwipeRefreshHeader extends AbstractSwipeRefreshHeader<SwipeRefreshH
} else {
mArrowDrawable = new ArrowDrawable();
mArrowDrawable.setColor(0xff666666);
mArrowView.setImageDrawable(mArrowDrawable);
mArrowView.setImageResource(com.gh.gamecenter.R.drawable.refresh_icon);
}
if (ta.hasValue(R.styleable.ClassicsHeader_srlDrawableProgress)) {
@ -91,7 +94,7 @@ public class SwipeRefreshHeader extends AbstractSwipeRefreshHeader<SwipeRefreshH
} else {
mProgressDrawable = new ProgressDrawable();
mProgressDrawable.setColor(0xff666666);
mProgressView.setImageDrawable(mProgressDrawable);
mProgressView.setImageResource(com.gh.gamecenter.R.drawable.refresh_anim);
}
if (ta.hasValue(R.styleable.ClassicsHeader_srlTextSizeTitle)) {
@ -140,7 +143,7 @@ public class SwipeRefreshHeader extends AbstractSwipeRefreshHeader<SwipeRefreshH
mCenterLayout.setVisibility(VISIBLE);
mTitleText.setText(REFRESH_HEADER_PULLING);
mArrowView.setVisibility(VISIBLE);
mArrowView.animate().rotation(0);
// mArrowView.animate().rotation(0);
break;
case Refreshing:
case RefreshReleased:
@ -153,7 +156,7 @@ public class SwipeRefreshHeader extends AbstractSwipeRefreshHeader<SwipeRefreshH
successView.setVisibility(GONE);
mCenterLayout.setVisibility(VISIBLE);
mTitleText.setText(REFRESH_HEADER_RELEASE);
mArrowView.animate().rotation(180);
// mArrowView.animate().rotation(180);
break;
case Loading:
successView.setVisibility(GONE);

View File

@ -0,0 +1,37 @@
package com.gh.common.view
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.ViewConfiguration
import androidx.recyclerview.widget.RecyclerView
import kotlin.math.abs
/**
* 如非特殊情况请勿使用,会强行改变RecyclerView的拦截事件,可能会出现意料之外的问题
*/
class TouchSlopRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
: RecyclerView(context, attrs) {
private var mPrevX = 0f
// 触控角度,用来控制触发左右滑动的敏感度
var touchSlop = ViewConfiguration.get(context).scaledTouchSlop
// 默认关闭,否则会误杀上下滑动事件
var touchSlopEnabled = false
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> mPrevX = event.x
MotionEvent.ACTION_MOVE -> {
val eventX = event.x
val xDiff = abs(eventX - mPrevX)
if (touchSlopEnabled && xDiff > touchSlop) {
return false
}
}
}
return super.onInterceptTouchEvent(event)
}
}

View File

@ -8,6 +8,7 @@ import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import com.gh.base.fragment.BaseDialogFragment
import com.gh.common.TimeElapsedHelper
import com.gh.common.constant.Constants
import com.gh.common.constant.Constants.SP_LAST_OPENING_ID
import com.gh.common.constant.Constants.SP_LAST_OPENING_TIME
import com.gh.common.util.*
@ -15,12 +16,19 @@ import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.DialogWelcomeBinding
import com.gh.gamecenter.entity.CommunityEntity
import com.gh.gamecenter.entity.WelcomeDialogEntity
import com.halo.assistant.HaloApp
class WelcomeDialog : BaseDialogFragment() {
companion object {
const val TAG = "welcome_dialog"
@JvmStatic
fun getInstance(welcomeEntity: WelcomeDialogEntity?) = WelcomeDialog().apply { mWelcomeEntity = welcomeEntity }
fun getInstance(welcomeEntity: WelcomeDialogEntity?) = WelcomeDialog().apply {
arguments = Bundle()
arguments?.putParcelable(TAG, welcomeEntity)
LogUtils.uploadWelcomeDialog("show", welcomeEntity?.id, welcomeEntity?.text)
}
}
private var mWelcomeEntity: WelcomeDialogEntity? = null
@ -34,12 +42,18 @@ class WelcomeDialog : BaseDialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mWelcomeEntity = arguments?.getParcelable(TAG)
mTimeHelper = TimeElapsedHelper(this)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_welcome, container, false)
binding.ivOpeningCover.setOnClickListener {
HaloApp.put(Constants.WELCOME_DIALOG_ID, mWelcomeEntity?.id)
HaloApp.put(Constants.WELCOME_DIALOG_LINK_TITLE, mWelcomeEntity?.text)
LogUtils.uploadWelcomeDialog("click", mWelcomeEntity?.id, mWelcomeEntity?.text)
when (mWelcomeEntity?.type) {
EntranceUtils.HOST_ARTICLE -> {
DirectUtils.directToArticle(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
@ -51,10 +65,10 @@ class WelcomeDialog : BaseDialogFragment() {
DirectUtils.directToSubject(requireContext(), mWelcomeEntity?.link!!, null, EntranceUtils.ENTRANCE_WELCOME)
}
EntranceUtils.HOST_QUESTION -> {
DirectUtils.directToQuestionDetail(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME, "首页弹窗")
DirectUtils.directToQuestionDetail(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
}
EntranceUtils.HOST_ANSWER -> {
DirectUtils.directToAnswerDetail(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME, "首页弹窗")
DirectUtils.directToAnswerDetail(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
}
EntranceUtils.HOST_WEB -> {
DirectUtils.directToWebView(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
@ -67,7 +81,7 @@ class WelcomeDialog : BaseDialogFragment() {
}
// else -> DialogUtils.showLowVersionDialog(context)
else -> DirectUtils.directToLinkPage(requireContext(), mWelcomeEntity
?: WelcomeDialogEntity(), EntranceUtils.ENTRANCE_WELCOME, "首页弹窗")
?: WelcomeDialogEntity(), EntranceUtils.ENTRANCE_WELCOME, "")
}
mDismissByClickImage = true
@ -111,15 +125,9 @@ class WelcomeDialog : BaseDialogFragment() {
}
override fun onDestroy() {
val type = if (mDismissByClickImage) {
"点击图片"
} else {
"点击关闭"
}
val type = if (mDismissByClickImage) "点击图片" else "点击关闭"
DataUtils.trackTimeEvent(context, "启动弹窗",
mTimeHelper?.elapsedTime!!,
type, "No parameter.")
MtaHelper.onEventWithTime("启动弹窗", mTimeHelper?.elapsedTime!!, type, "No parameter.")
PreferenceManager.getDefaultSharedPreferences(context?.applicationContext).edit {
putString(SP_LAST_OPENING_ID, mWelcomeEntity?.id)

View File

@ -75,6 +75,12 @@ public class DWebView extends WebView {
}
}
@Keep
@JavascriptInterface
public String call(String methodName) {
return call(methodName, "");
}
@Keep
@JavascriptInterface
public String call(String methodName, String argStr) {
@ -93,7 +99,7 @@ public class DWebView extends WebView {
PrintDebugInfo(error);
return ret.toString();
}
Object arg=null;
Object arg = null;
Method method = null;
String callback = null;
@ -102,7 +108,7 @@ public class DWebView extends WebView {
if (args.has("_dscbstub")) {
callback = args.getString("_dscbstub");
}
if(args.has("data")) {
if (args.has("data")) {
arg = args.get("data");
}
} catch (JSONException e) {
@ -123,7 +129,10 @@ public class DWebView extends WebView {
try {
method = cls.getMethod(methodName, new Class[]{Object.class});
} catch (Exception ex) {
try {
method = cls.getMethod(methodName, new Class[]{});
} catch (Exception ignore) {
}
}
}
@ -187,7 +196,12 @@ public class DWebView extends WebView {
}
});
} else {
retData = method.invoke(jsb, arg);
Class<?>[] methodParameterTypes = method.getParameterTypes();
if (methodParameterTypes.length == 0) {
retData = method.invoke(jsb);
} else {
retData = method.invoke(jsb, arg);
}
ret.put("code", 0);
ret.put("data", retData);
return ret.toString();
@ -307,7 +321,10 @@ public class DWebView extends WebView {
try {
method = cls.getMethod(nameStr[1], new Class[]{Object.class});
} catch (Exception ex) {
try {
method = cls.getMethod(nameStr[1], new Class[]{});
} catch (Exception ignore) {
}
}
}
if (method != null) {
@ -336,7 +353,7 @@ public class DWebView extends WebView {
|| javascriptCloseWindowListener.onClose()) {
Context context = getContext();
if (context instanceof Activity) {
((Activity)context).onBackPressed();
((Activity) context).onBackPressed();
}
}
}
@ -359,7 +376,7 @@ public class DWebView extends WebView {
@Keep
@JavascriptInterface
public void returnValue(final Object obj){
public void returnValue(final Object obj) {
runOnMainThread(new Runnable() {
@Override
public void run() {
@ -390,7 +407,17 @@ public class DWebView extends WebView {
private void _evaluateJavascript(String script) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
DWebView.super.evaluateJavascript(script, null);
try {
DWebView.super.evaluateJavascript(script, null);
} catch (Exception e) {
// 部分机型把自己伪装成 Android 4.4 然后没 evaluateJavascript 方法!
e.printStackTrace();
try {
super.loadUrl("javascript:" + script);
} catch (Exception ignored){
}
}
} else {
super.loadUrl("javascript:" + script);
}
@ -422,9 +449,9 @@ public class DWebView extends WebView {
runOnMainThread(new Runnable() {
@Override
public void run() {
if (url != null && url.startsWith("javascript:")){
if (url != null && url.startsWith("javascript:")) {
DWebView.super.loadUrl(url);
}else{
} else {
callInfoList = new ArrayList<>();
DWebView.super.loadUrl(url);
}
@ -444,9 +471,9 @@ public class DWebView extends WebView {
runOnMainThread(new Runnable() {
@Override
public void run() {
if (url != null && url.startsWith("javascript:")){
if (url != null && url.startsWith("javascript:")) {
DWebView.super.loadUrl(url, additionalHttpHeaders);
}else{
} else {
callInfoList = new ArrayList<>();
DWebView.super.loadUrl(url, additionalHttpHeaders);
}
@ -996,7 +1023,4 @@ public class DWebView extends WebView {
mainHandler.post(runnable);
}
}

View File

@ -0,0 +1,27 @@
package com.gh.common.view.vertical_recycler
import android.content.Context
import android.graphics.PointF
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSmoothScroller
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.tryWithDefaultCatch
class SnappingLinearLayoutManager(val context: Context) : LinearLayoutManager(context) {
override fun smoothScrollToPosition(recyclerView: RecyclerView?, state: RecyclerView.State?, position: Int) {
tryWithDefaultCatch {
val smoothScroller = object : LinearSmoothScroller(context) {
override fun getVerticalSnapPreference(): Int = SNAP_TO_START
override fun computeScrollVectorForPosition(targetPosition: Int): PointF =
this@SnappingLinearLayoutManager.computeScrollVectorForPosition(targetPosition)
?: PointF(0F, 0F)
}
smoothScroller.targetPosition = position
startSmoothScroll(smoothScroller)
}
}
override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
tryWithDefaultCatch { super.onLayoutChildren(recycler, state) }
}
}

View File

@ -0,0 +1,15 @@
package com.gh.common.xapk
import com.lightgame.download.DownloadEntity
interface IXapkUnzipListener {
fun onProgress(downloadEntity: DownloadEntity, unzipPath: String, unzipSize: Long, unzipProgress: Long)
fun onNext(downloadEntity: DownloadEntity, unzipPath: String)
fun onCancel(downloadEntity: DownloadEntity)
fun onFailure(downloadEntity: DownloadEntity, exception: Exception)
fun onSuccess(downloadEntity: DownloadEntity)
}

View File

@ -0,0 +1,175 @@
package com.gh.common.xapk
import android.content.Context
import android.os.Build
import com.gh.common.AppExecutor
import com.gh.common.util.*
import com.gh.download.DownloadManager
import com.gh.gamecenter.BuildConfig
import com.halo.assistant.HaloApp
import com.lightgame.download.DataChanger
import com.lightgame.download.DownloadEntity
import com.lightgame.utils.Util_System_Phone_State
import com.lightgame.utils.Utils
import java.text.DecimalFormat
import java.util.*
/**
* 目前已知的Xapk内容是:只有一个apk包和一个或做多个obb数据包(多余文件不解压,如果存在多个apk包,则以下安装无效)
*
* 每次安装都会重新跑一遍解压安装流程
* 目前检验是否已解压的根据是存在相同文件名且大小一致(暂时想不到校验MD5值的方法)
*
* obb文件直接解压至根目录即可,无需操作文件
* apk文件这解压的gh-download文件夹中
*/
object XapkInstaller : IXapkUnzipListener {
private const val XAPK_PACKAGE_PATH_TAG = "xapk_package_path"
// private const val XAPK_DATA_PATH_TAG = "xapk_data_path"
const val XAPK_EXTENSION_NAME = "xapk"
// 通过解压过程存放于 DownloadEntity meta
const val XAPK_UNZIP_PERCENT = "unzip_percent"
const val XAPK_UNZIP_STATUS = "unzip_status"
const val XAPK_DATA_EXTENSION_NAME = "obb"
const val PACKAGE_EXTENSION_NAME = "apk"
private var mContext = HaloApp.getInstance().application.applicationContext
// 是否需要开启特定线程处理
private val mXapkUnzipThreadMap = Collections.synchronizedMap(HashMap<String, XapkUnzipThread>())
// 按并行解压
@JvmStatic
fun install(context: Context, downloadEntity: DownloadEntity, showUnzipToast: Boolean = false) {
this.mContext = context
val filePath = downloadEntity.path
if (XAPK_EXTENSION_NAME == filePath.getExtension()) {
unzipXapkFile(downloadEntity)
if (showUnzipToast) {
Utils.toast(mContext, "解压过程请勿退出光环助手!")
}
} else {
throwExceptionInDebug("如果是Apk包请使用PackageInstaller进行安装")
PackageInstaller.install(mContext, downloadEntity)
}
}
private fun unzipXapkFile(downloadEntity: DownloadEntity) {
if (mXapkUnzipThreadMap[downloadEntity.path] == null) {
val xapkUnzipThread = XapkUnzipThread(downloadEntity, this)
xapkUnzipThread.start()
mXapkUnzipThreadMap[downloadEntity.path] = xapkUnzipThread
} else {
debugOnly {
Utils.log("unzip", "重复解压,该文件解压已在队列中")
}
}
}
override fun onProgress(downloadEntity: DownloadEntity, unzipPath: String, unzipSize: Long, unzipProgress: Long) {
AppExecutor.uiExecutor.execute {
val df = DecimalFormat("#.0")
var percent = 0.0
tryCatchInRelease {
percent = df.format((unzipProgress / unzipSize.toFloat()) * 100).toDouble()
}
downloadEntity.meta[XAPK_UNZIP_PERCENT] = percent.toString()
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.UNZIPPING.name
DataChanger.notifyDataChanged(downloadEntity)
}
debugOnly {
Utils.log("unzip", "onProgress->" + (unzipProgress / unzipSize.toFloat()))
}
}
override fun onNext(downloadEntity: DownloadEntity, unzipPath: String) {
if (PACKAGE_EXTENSION_NAME == unzipPath.getExtension()) {
downloadEntity.meta[XAPK_PACKAGE_PATH_TAG] = unzipPath
DownloadManager.getInstance(mContext).updateDownloadEntity(downloadEntity)
}
debugOnly {
Utils.log("unzip", "onNext->$unzipPath")
}
}
/**
* 取消解压回调
*
* 取消后的表现与下载完成一致
*/
override fun onCancel(downloadEntity: DownloadEntity) {
mXapkUnzipThreadMap.remove(downloadEntity.path)
AppExecutor.uiExecutor.execute {
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "0.0"
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.CANCEL.name
DataChanger.notifyDataChanged(downloadEntity)
DownloadManager.getInstance(mContext).updateDownloadEntity(downloadEntity)
}
}
override fun onFailure(downloadEntity: DownloadEntity, exception: Exception) {
mXapkUnzipThreadMap.remove(downloadEntity.path)
AppExecutor.uiExecutor.execute {
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.FAILURE.name
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
DataChanger.notifyDataChanged(downloadEntity)
DownloadManager.getInstance(mContext).updateDownloadEntity(downloadEntity)
}
MtaHelper.onEvent("解压失败"
, "安卓版本", Build.VERSION.RELEASE
, "IMEI", Util_System_Phone_State.getDeviceId(HaloApp.getInstance().application)
, "光环版本", BuildConfig.VERSION_NAME
, "厂商", Build.MANUFACTURER
, "机型", Build.MODEL
, "游戏", downloadEntity.name
, "网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().application))
debugOnly {
Utils.log("unzip", "onFailure->$exception")
}
}
override fun onSuccess(downloadEntity: DownloadEntity) {
mXapkUnzipThreadMap.remove(downloadEntity.path)
AppExecutor.uiExecutor.execute {
val pkgPath = checkNotNull(downloadEntity.meta[XAPK_PACKAGE_PATH_TAG])
PackageInstaller.install(mContext, pkgPath)
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "100.0"
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.SUCCESS.name
DataChanger.notifyDataChanged(downloadEntity)
DownloadManager.getInstance(mContext).updateDownloadEntity(downloadEntity)
}
debugOnly {
Utils.log("unzip", "onSuccess->${downloadEntity.path}")
}
}
@JvmStatic
fun cancelUnzipTask(downloadEntity: DownloadEntity) {
val xapkUnzipThread = mXapkUnzipThreadMap[downloadEntity.path]
if (xapkUnzipThread != null) {
xapkUnzipThread.canceled = true
} else {
onCancel(downloadEntity) // 刷新页面
}
}
}
enum class XapkUnzipStatus(status: String) {
UNZIPPING("unzipping"),
SUCCESS("success"),
CANCEL("cancel"),
FAILURE("failure");
}

View File

@ -0,0 +1,211 @@
package com.gh.common.xapk
import android.os.Environment
import com.gh.common.util.getExtension
import com.gh.common.util.throwException
import com.gh.common.util.throwExceptionInDebug
import com.gh.gamecenter.BuildConfig
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.download.FileUtils
import com.lightgame.utils.Utils
import net.lingala.zip4j.progress.ProgressMonitor
import java.io.File
import java.util.zip.ZipFile
class XapkUnzipThread(private var mDownloadEntity: DownloadEntity,
private var mUnzipListener: IXapkUnzipListener) : Thread() {
private val mDefaultBufferSize = 1024 * 1024
var canceled = false
override fun run() {
super.run()
try {
val path = mDownloadEntity.path
var unzipSize = 0L
try {
unzipSize = getUnzipSize(path)
} catch (e: Exception) {
planB()
return
}
val msg = FileUtils.isCanDownload(HaloApp.getInstance().application, unzipSize)
if (!msg.isNullOrEmpty()) {
// 空间不足应该不用刷新页面,保持不变就好
Utils.toast(HaloApp.getInstance().application, "设备存储空间不足,请清理后重试!")
mUnzipListener.onCancel(mDownloadEntity)
return
}
var unzipProgress = 0L
val absolutePath = Environment.getExternalStorageDirectory().absolutePath
val xapkFile = File(path)
ZipFile(xapkFile).use { zip ->
for (zipEntry in zip.entries().asSequence()) {
val outputFile = if (zipEntry.name.getExtension() == XapkInstaller.XAPK_DATA_EXTENSION_NAME) {
File(absolutePath + File.separator + zipEntry.name)
} else if (zipEntry.name.getExtension() == XapkInstaller.PACKAGE_EXTENSION_NAME) {
// apk文件名称 = xapk文件名+本身的文件名称
val fileName = xapkFile.nameWithoutExtension + "_" + zipEntry.name
File(FileUtils.getDownloadPath(HaloApp.getInstance().application, fileName))
} else continue // 暂时只需要解压xpk/obb文件
if (zipEntry.isDirectory) {
if (!outputFile.exists()) {
throwException("unzip create file path failure", !outputFile.mkdirs())
}
continue
}
if (!outputFile.parentFile.exists()) {
throwException("unzip create file path failure", !outputFile.parentFile.mkdirs())
}
// 如果存在同名且大小一致,可以认为该文件已经解压缩(在不解压缩的情况下如果如果获取压缩文件的MD5????)
if (!outputFile.exists()) {
throwException("unzip create file failure", !outputFile.createNewFile())
} else if (outputFile.length() != zipEntry.size) {
throwException("unzip delete existing file failure", !outputFile.delete())
throwException("unzip create file failure", !outputFile.createNewFile())
} else {
unzipProgress += zipEntry.size
mUnzipListener.onProgress(mDownloadEntity, outputFile.path, unzipSize, unzipProgress)
mUnzipListener.onNext(mDownloadEntity, outputFile.path)
continue
}
// unzip
zip.getInputStream(zipEntry).use { input ->
outputFile.outputStream().use { output ->
val buffer = ByteArray(mDefaultBufferSize)
var bytes = input.read(buffer)
while (bytes >= 0) {
output.write(buffer, 0, bytes)
unzipProgress += bytes
bytes = input.read(buffer)
if (canceled) {
mUnzipListener.onCancel(mDownloadEntity)
return
} else {
mUnzipListener.onProgress(mDownloadEntity, outputFile.path, unzipSize, unzipProgress)
}
}
}
}
mUnzipListener.onNext(mDownloadEntity, outputFile.path)
}
}
mUnzipListener.onSuccess(mDownloadEntity)
} catch (e: Exception) {
if (BuildConfig.DEBUG) throw e
mUnzipListener.onFailure(mDownloadEntity, e)
}
}
/**
* 部分未知情况(有可能是项目配置问题有可能时Zip包破损)原生的ZipFile无法打开压缩包,则启动以下备用方案
* 具体复现机型:小米 9(Android 9)
* 具体复现的压缩包:太空竞速2 具体可以咨询陈思雨
*
* 实现方式请参考:https://github.com/srikanth-lingala/zip4j
* 注意使用该库的ZipInputStream依然无法解压,提示头文件丢失
*
* 后续如果有需要可以直接使用该方法进行解压
*/
private fun planB() {
val zipPath = mDownloadEntity.path
val absolutePath = Environment.getExternalStorageDirectory().absolutePath
val zipFile = net.lingala.zip4j.ZipFile(zipPath)
val progressMonitor = zipFile.progressMonitor
zipFile.isRunInThread = true
val fileHeaders = zipFile.fileHeaders
var unzipSize = 0L
for (fileHeader in fileHeaders) {
unzipSize += fileHeader.uncompressedSize;
}
var unzipProgress = 0L
var completedSize = 0L
for (fileHeader in fileHeaders) {
if (canceled) {
mUnzipListener.onCancel(mDownloadEntity)
return
}
// 暂时只需要解压xpk/obb文件
val extension = fileHeader.fileName.getExtension()
if (extension != XapkInstaller.XAPK_DATA_EXTENSION_NAME && extension != XapkInstaller.PACKAGE_EXTENSION_NAME) continue
var unzipPath = ""
if (extension == XapkInstaller.XAPK_DATA_EXTENSION_NAME) {
unzipPath = absolutePath + File.separator + fileHeader.fileName
if (hasUnzipFile(unzipPath, fileHeader.uncompressedSize)) {
mUnzipListener.onNext(mDownloadEntity, unzipPath)
continue
}
zipFile.extractFile(fileHeader.fileName, absolutePath)
}
if (extension == XapkInstaller.PACKAGE_EXTENSION_NAME) {
val downloadDir = FileUtils.getDownloadDir(HaloApp.getInstance().application)
val unzipFileName = File(zipPath).nameWithoutExtension + "_" + fileHeader.fileName
unzipPath = downloadDir + File.separator + unzipFileName
if (hasUnzipFile(unzipPath, fileHeader.uncompressedSize)) {
mUnzipListener.onNext(mDownloadEntity, unzipPath)
continue
}
zipFile.extractFile(fileHeader.fileName, downloadDir, unzipFileName)
}
throwExceptionInDebug("check unzipPath", unzipPath.isEmpty())
// 回调太频繁了,变态吗? 4K回调一次,还不能改,FUCK
var filterCounter = 0
val filterInterval = 1024 * 10
while (progressMonitor.state != ProgressMonitor.State.READY) {
filterCounter++
if (filterCounter % filterInterval == 0) {
unzipProgress = completedSize + progressMonitor.workCompleted
mUnzipListener.onProgress(mDownloadEntity, unzipPath, unzipSize, unzipProgress)
if (canceled) {
progressMonitor.isCancelAllTasks = true
mUnzipListener.onCancel(mDownloadEntity)
return
}
}
}
completedSize += fileHeader.uncompressedSize
mUnzipListener.onNext(mDownloadEntity, unzipPath)
}
mUnzipListener.onSuccess(mDownloadEntity)
}
private fun hasUnzipFile(unzipPath: String, uncompressedSize: Long): Boolean {
val unzipFile = File(unzipPath)
if (unzipFile.exists() || unzipFile.length() == uncompressedSize) return true
return false
}
private fun getUnzipSize(path: String): Long {
var totalSize = 0L
for (entry in ZipFile(File(path)).entries()) {
totalSize += entry.size
}
return totalSize
}
}

View File

@ -1,11 +1,21 @@
package com.gh.download
import android.content.pm.PackageManager
import com.gh.common.exposure.meta.MetaUtil.getMeta
import com.gh.common.loghub.LoghubUtils
import com.gh.common.util.DeviceUtils
import com.gh.gamecenter.BuildConfig
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import com.lightgame.utils.Utils
import org.json.JSONArray
import org.json.JSONObject
object DownloadDataHelper {
private const val DOWNLOAD_SPEED_TIME = "download_speed_time"
private const val DOWNLOAD_SPEED_SIZE = "download_speed_size"
const val DOWNLOAD_RESUME_WAY = "download_resume_way"
const val DOWNLOAD_RESUME_MANUAL = "manual"
const val DOWNLOAD_RESUME_AUTO = "auto"
@ -14,9 +24,16 @@ object DownloadDataHelper {
const val DOWNLOAD_CANCEL_MANUAL = "manual"
const val DOWNLOAD_CANCEL_AUTO = "auto"
const val DOWNLOAD_FIRST_START = "download_first_start"
private val mDownloadSpeedMap = HashMap<String, MutableList<Long>>()
private val mDownloadHeartbeatList = mutableListOf<JSONObject>()
private val mDownloadHeartbeatSheet = HashMap<String, JSONObject>()
@JvmStatic
fun getDownloadStatusAlias(downloadEntity: DownloadEntity): String {
val status = downloadEntity.status
fun getDownloadStatusAlias(downloadEntity: DownloadEntity, downloadStatus: DownloadStatus? = null): String {
val status = downloadStatus ?: downloadEntity.status
return if (status == DownloadStatus.add) {
"开始下载"
} else if (status == DownloadStatus.pause) {
@ -53,4 +70,236 @@ object DownloadDataHelper {
"未知状态"
}
}
@JvmStatic
fun uploadDownloadEvent(downloadEntity: DownloadEntity) {
if (downloadEntity.status != DownloadStatus.downloading) {
uploadDownloadStatusEvent(downloadEntity)
}
if (downloadEntity.status == DownloadStatus.downloading) {
val startupTime = downloadEntity.meta[DownloadEntity.DOWNLOAD_STARTUP_TIME_KEY]
if (startupTime != null) {
uploadDownloadStartupTimeEvent(downloadEntity, startupTime.toInt())
downloadEntity.meta.remove(DownloadEntity.DOWNLOAD_STARTUP_TIME_KEY)
DownloadManager.getInstance(HaloApp.getInstance().application).updateDownloadEntity(downloadEntity)
}
}
if (downloadEntity.status == DownloadStatus.downloading || downloadEntity.status == DownloadStatus.done) {
val time = downloadEntity.meta[DOWNLOAD_SPEED_TIME]
val size = downloadEntity.meta[DOWNLOAD_SPEED_SIZE]
if (downloadEntity.speed == 0L || time == null || size == null) {
downloadEntity.meta[DOWNLOAD_SPEED_TIME] = System.currentTimeMillis().toString()
downloadEntity.meta[DOWNLOAD_SPEED_SIZE] = downloadEntity.progress.toString()
DownloadManager.getInstance(HaloApp.getInstance().application).updateDownloadEntity(downloadEntity)
} else {
val offset = System.currentTimeMillis() - time.toLong()
if (offset > 5000) {
//记录并重置
val downloadedSize = downloadEntity.progress - size.toLong()
val averageSpeed = downloadedSize / offset
val speedList = mDownloadSpeedMap[downloadEntity.url]
if (speedList == null) {
mDownloadSpeedMap[downloadEntity.url] = arrayListOf(averageSpeed)
} else {
speedList.add(averageSpeed)
if (speedList.size >= 6 || downloadEntity.status == DownloadStatus.done) {
uploadDownloadAverageSpeed(downloadEntity, speedList)
if (downloadEntity.status == DownloadStatus.done) {
mDownloadSpeedMap.remove(downloadEntity.url)
} else {
speedList.clear()
}
}
}
downloadEntity.meta[DOWNLOAD_SPEED_TIME] = System.currentTimeMillis().toString()
downloadEntity.meta[DOWNLOAD_SPEED_SIZE] = downloadEntity.progress.toString()
DownloadManager.getInstance(HaloApp.getInstance().application).updateDownloadEntity(downloadEntity)
}
}
}
}
private fun uploadDownloadStartupTimeEvent(downloadEntity: DownloadEntity, startupTime: Int) {
val jsonObject = JSONObject()
try {
jsonObject.put("event", "下载线程启动")
val startupStatus = downloadEntity.meta[DownloadEntity.DOWNLOAD_STARTUP_STATUS_KEY]
if (startupStatus != null) {
jsonObject.put("msg", getDownloadStatusAlias(downloadEntity, DownloadStatus.valueOf(startupStatus)))
}
jsonObject.put("meta", getMetaJson())
jsonObject.put("timestamp", System.currentTimeMillis() / 1000)
// payload
val payloadObject = JSONObject()
payloadObject.put("game_id", downloadEntity.gameId)
payloadObject.put("gameName", downloadEntity.name)
payloadObject.put("platform", downloadEntity.platform)
payloadObject.put("package", downloadEntity.packageName)
payloadObject.put("filename", downloadEntity.path.substring(downloadEntity.path.lastIndexOf("/") + 1))
payloadObject.put("launch_ms", startupTime)
jsonObject.put("payload", payloadObject)
} catch (e: Exception) {
e.printStackTrace()
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->$jsonObject")
}
LoghubUtils.log(jsonObject, "download_debug", false)
}
private fun uploadDownloadStatusEvent(downloadEntity: DownloadEntity) {
val jsonObject = JSONObject()
try {
jsonObject.put("event", getDownloadStatusAlias(downloadEntity))
jsonObject.put("msg", downloadEntity.error)
jsonObject.put("status", downloadEntity.status.status)
jsonObject.put("meta", getMetaJson())
jsonObject.put("timestamp", System.currentTimeMillis() / 1000)
// payload
val payloadObject = JSONObject()
payloadObject.put("game_id", downloadEntity.gameId)
payloadObject.put("gameName", downloadEntity.name)
payloadObject.put("platform", downloadEntity.platform)
payloadObject.put("package", downloadEntity.packageName)
payloadObject.put("filename", downloadEntity.path.substring(downloadEntity.path.lastIndexOf("/") + 1))
payloadObject.put("total_size", downloadEntity.size / 1024 / 1024)
payloadObject.put("completed_size", downloadEntity.progress / 1024 / 1024)
if (downloadEntity.status == DownloadStatus.resume) {
if (downloadEntity.meta[DOWNLOAD_FIRST_START] == "YES") {
payloadObject.put("is_first_start", true)
} else {
payloadObject.put("is_first_start", false)
}
}
if (downloadEntity.status == DownloadStatus.resume || downloadEntity.status == DownloadStatus.add) {
downloadEntity.meta[DOWNLOAD_FIRST_START] = "NO"
DownloadManager.getInstance(HaloApp.getInstance().application).updateDownloadEntity(downloadEntity)
}
jsonObject.put("payload", payloadObject)
} catch (e: Exception) {
e.printStackTrace()
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->$jsonObject")
}
LoghubUtils.log(jsonObject, "download_debug", false)
}
private fun uploadDownloadAverageSpeed(downloadEntity: DownloadEntity, averageSpeedList: List<Long>) {
val jsonObject = JSONObject()
try {
jsonObject.put("event", "下载进度")
jsonObject.put("msg", "")
jsonObject.put("meta", getMetaJson())
jsonObject.put("timestamp", System.currentTimeMillis() / 1000)
// payload
val payloadObject = JSONObject()
payloadObject.put("game_id", downloadEntity.gameId)
payloadObject.put("gameName", downloadEntity.name)
payloadObject.put("platform", downloadEntity.platform)
payloadObject.put("package", downloadEntity.packageName)
payloadObject.put("filename", downloadEntity.path.substring(downloadEntity.path.lastIndexOf("/") + 1))
payloadObject.put("speed_progress", JSONArray(averageSpeedList))
payloadObject.put("is_finished", downloadEntity.status == DownloadStatus.done)
jsonObject.put("payload", payloadObject)
} catch (e: Exception) {
e.printStackTrace()
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->$jsonObject")
}
LoghubUtils.log(jsonObject, "download_debug", false)
}
/**
* 分片检测下载进度,每隔15秒内记录一次,60秒上传一次
*
* 请见:https://gitlab.ghzs.com/stats/stats-issues/-/issues/188#note_66919
*/
fun uploadDownloadHeartbeat(upload: Boolean) {
val allDownloadEntity = DownloadManager.getInstance(HaloApp.getInstance().application).allDownloadEntity
for (downloadEntity in allDownloadEntity) {
if (downloadEntity.status == DownloadStatus.downloading) {
var sheet = mDownloadHeartbeatSheet[downloadEntity.url]
if (sheet == null) {
sheet = JSONObject()
val host = downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] ?: "unknown"
sheet.put("host", host)
sheet.put("game_id", downloadEntity.gameId)
sheet.put("platform", downloadEntity.platform)
sheet.put("package", downloadEntity.packageName)
sheet.put("filename", downloadEntity.path.substring(downloadEntity.path.lastIndexOf("/") + 1))
sheet.put("total_size", downloadEntity.size / 1024 / 1024)
sheet.put("current_progress_size", downloadEntity.progress / 1024)
mDownloadHeartbeatSheet[downloadEntity.url] = sheet
} else {
val progressSize = sheet.getLong("current_progress_size")
sheet.put("total_size", downloadEntity.size / 1024 / 1024) // 初始化记录的 total_size 有可能为0
sheet.put("progress_size", downloadEntity.progress / 1024 - progressSize)
sheet.put("current_progress_size", downloadEntity.progress / 1024)
mDownloadHeartbeatList.add(JSONObject(sheet.toString()))
}
} else {
mDownloadHeartbeatSheet.remove(downloadEntity.url)
}
}
if (upload && mDownloadHeartbeatList.isNotEmpty()) {
val jsonObject = JSONObject()
try {
jsonObject.put("event", "progress")
jsonObject.put("meta", getMetaJson())
jsonObject.put("timestamp", System.currentTimeMillis() / 1000)
val payloads = JSONArray()
for (heartbeatData in mDownloadHeartbeatList) {
heartbeatData.remove("current_progress_size")
payloads.put(heartbeatData)
}
jsonObject.put("payloads", payloads)
} catch (e: Exception) {
e.printStackTrace()
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->$jsonObject")
}
mDownloadHeartbeatList.clear()
LoghubUtils.log(jsonObject, "download_debug", false)
}
}
private fun getMetaJson(): JSONObject {
val context = HaloApp.getInstance().application
val meta = getMeta()
// meta
val metaObject = JSONObject()
metaObject.put("android_id", meta.android_id)
metaObject.put("android_sdk", meta.android_sdk)
metaObject.put("android_version", meta.android_version)
metaObject.put("appVersion", meta.appVersion)
metaObject.put("channel", meta.channel)
metaObject.put("gid", meta.gid)
metaObject.put("imei", meta.imei)
metaObject.put("mac", meta.mac)
metaObject.put("manufacturer", meta.manufacturer)
metaObject.put("model", meta.model)
metaObject.put("network", DeviceUtils.getNetwork(context))
metaObject.put("os", meta.os)
metaObject.put("MNC", DeviceUtils.getTelephonySubscriberId(context) ?: "")
metaObject.put("userId", meta.userId)
return metaObject
}
}

View File

@ -11,10 +11,9 @@ import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.collection.ArrayMap;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.ProcessLifecycleOwner;
import com.gh.common.AppExecutor;
import com.gh.common.constant.Constants;
import com.gh.common.exposure.ExposureEvent;
import com.gh.common.exposure.ExposureUtils;
import com.gh.common.history.HistoryHelper;
@ -22,10 +21,11 @@ import com.gh.common.util.AppDebugConfig;
import com.gh.common.util.DataCollectionUtils;
import com.gh.common.util.DeviceUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.ExtensionsKt;
import com.gh.common.util.GdtHelper;
import com.gh.common.util.HomePluggableHelper;
import com.gh.common.util.MD5Utils;
import com.gh.common.util.NetworkUtils;
import com.gh.common.util.PackageInstaller;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.SPUtils;
import com.gh.gamecenter.entity.ApkEntity;
@ -186,7 +186,7 @@ public class DownloadManager implements DownloadStatusListener {
}
};
List<DownloadEntity> list = getAll();
List<DownloadEntity> list = getAllDownloadEntity();
for (DownloadEntity downloadEntity : list) {
statusMap.put(downloadEntity.getUrl(), downloadEntity.getStatus());
if (!DownloadStatus.done.equals(downloadEntity.getStatus())) {
@ -243,8 +243,7 @@ public class DownloadManager implements DownloadStatusListener {
DownloadEntity downloadEntity = new DownloadEntity();
downloadEntity.setUrl(apkEntity.getUrl());
downloadEntity.setName(gameEntity.getName());
downloadEntity.setPath(FileUtils.getDownloadPath(context,
MD5Utils.getContentMD5(gameEntity.getName() + "_" + System.currentTimeMillis()) + ".apk"));
downloadEntity.setPath(PackageInstaller.getDownloadPath(gameEntity.getName(), apkEntity.getFormat()));
downloadEntity.setETag(apkEntity.getEtag());
downloadEntity.setIcon(gameEntity.getIcon());
downloadEntity.setPlatform(apkEntity.getPlatform());
@ -253,6 +252,8 @@ public class DownloadManager implements DownloadStatusListener {
downloadEntity.setEntrance(entrance);
downloadEntity.setLocation(location);
downloadEntity.setVersionName(apkEntity.getVersion());
ExtensionsKt.addMetaExtra(downloadEntity, Constants.RAW_GAME_ICON, gameEntity.getRawIcon());
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_ICON_SUBSCRIPT, gameEntity.getIconSubscript());
int installed = 0;
for (ApkEntity apk : gameEntity.getApk()) {
if (PackagesManager.INSTANCE.isInstalled(apk.getPackageName())) {
@ -475,7 +476,7 @@ public class DownloadManager implements DownloadStatusListener {
public void initGameMap() {
gameMap.clear();
List<DownloadEntity> list = getAll();
List<DownloadEntity> list = getAllDownloadEntity();
if (list != null && list.size() != 0) {
String name;
for (DownloadEntity downloadEntity : list) {
@ -492,11 +493,9 @@ public class DownloadManager implements DownloadStatusListener {
/**
* 获取所有下载列表中的任务
*
* @return null表示没有下载任务
*/
@NonNull
public List<DownloadEntity> getAll() {
public List<DownloadEntity> getAllDownloadEntity() {
if (CommonDebug.IS_DEBUG) {
CommonDebug.logMethodName(this);
}
@ -504,6 +503,31 @@ public class DownloadManager implements DownloadStatusListener {
return all != null ? all : new ArrayList<>();
}
/**
* 获取所有下载列表中的任务排除静默更新
*/
public List<DownloadEntity> getAllDownloadEntityExcludeSilentUpdate() {
if (CommonDebug.IS_DEBUG) {
CommonDebug.logMethodName(this);
}
List<DownloadEntity> all = mDownloadDao.getAll();
return filterSilentDownloadTask(all);
}
private ArrayList<DownloadEntity> filterSilentDownloadTask(List<DownloadEntity> downloadEntityList) {
ArrayList<DownloadEntity> filteredDownloadEntityList = new ArrayList<>();
if (downloadEntityList == null) return filteredDownloadEntityList;
for (DownloadEntity downloadEntity : downloadEntityList) {
if (!Constants.SILENT_UPDATE.equals(ExtensionsKt.getMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE))) {
filteredDownloadEntityList.add(downloadEntity);
}
}
return filteredDownloadEntityList;
}
public ArrayMap<String, DownloadEntity> getEntryMap(String name) {
return gameMap.get(name);
}
@ -621,7 +645,7 @@ public class DownloadManager implements DownloadStatusListener {
*/
public void initDownloadService() {
final List<String> urlList = new ArrayList<>(DataChanger.INSTANCE.getDownloadingTasks().keySet());
for (DownloadEntity downloadEntity : getAll()) {
for (DownloadEntity downloadEntity : getAllDownloadEntity()) {
if (!urlList.contains(downloadEntity.getUrl()) &&
(downloadEntity.getStatus().equals(DownloadStatus.downloading)
|| downloadEntity.getStatus().equals(DownloadStatus.waiting))) {
@ -645,13 +669,11 @@ public class DownloadManager implements DownloadStatusListener {
DataChanger.INSTANCE.deleteObserver(dataWatcher);
}
private void startDownloadService() {
public void startDownloadService() {
Intent serviceIntent = new Intent(mContext, DownloadService.class);
// 当满足系统版本大于 8.0 并且进程处于 CREATED 状态 (ON_STOP后的状态) 的时候才以前台服务开启
// "not allowed to start service, app is in background" 的错误概率比 "startForegroundService() did not then call Service.startForeground() " 低
// 所以还是老老实实地以 startService 为主吧
// 当满足系统版本大于 8.0 并且应用在后台运行时以前台服务开启
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
&& ProcessLifecycleOwner.get().getLifecycle().getCurrentState() == Lifecycle.State.CREATED) {
&& !PackageUtils.isAppOnForeground(mContext)) {
serviceIntent.putExtra(DownloadService.KEY_SERVICE_ACTION, DownloadService.START_FOREGROUND);
mContext.startForegroundService(serviceIntent);
} else {
@ -671,10 +693,16 @@ public class DownloadManager implements DownloadStatusListener {
downloadEntity.getMeta().put(DownloadEntity.NETWORK_STATUS_KEY, network);
}
if (status == DownloadStatus.add || status == DownloadStatus.subscribe) {
if (downloadEntity.getMeta().get(DownloadDataHelper.DOWNLOAD_FIRST_START) == null) {
downloadEntity.getMeta().put(DownloadDataHelper.DOWNLOAD_FIRST_START, "YES");
}
}
Intent serviceIntent = getIntent(downloadEntity, status);
// 当满足系统版本大于 8.0 应用在后台运行时以前台服务开启
// 当满足系统版本大于 8.0 并且应用在后台运行时以前台服务开启
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
&& ProcessLifecycleOwner.get().getLifecycle().getCurrentState() == Lifecycle.State.CREATED) {
&& !PackageUtils.isAppOnForeground(mContext)) {
serviceIntent.putExtra(DownloadService.KEY_SERVICE_ACTION, DownloadService.START_FOREGROUND);
mContext.startForegroundService(serviceIntent);
} else {
@ -685,7 +713,7 @@ public class DownloadManager implements DownloadStatusListener {
public void checkRetryDownload() {
if (!NetworkUtils.isWifiConnected(mContext)) return;
for (DownloadEntity downloadEntity : DownloadManager.getInstance(mContext).getAll()) {
for (DownloadEntity downloadEntity : DownloadManager.getInstance(mContext).getAllDownloadEntityExcludeSilentUpdate()) {
if (DownloadStatus.neterror.equals(downloadEntity.getStatus()) ||
DownloadStatus.timeout.equals(downloadEntity.getStatus()) ||
DownloadStatus.subscribe.equals(downloadEntity.getStatus())) {
@ -709,7 +737,7 @@ public class DownloadManager implements DownloadStatusListener {
boolean showRedPoint = false;
int downloadingSize = 0;
for (DownloadEntity downloadEntity : getAll()) {
for (DownloadEntity downloadEntity : getAllDownloadEntityExcludeSilentUpdate()) {
if (DownloadStatus.done.equals(downloadEntity.getStatus())) {
String mark = downloadEntity.getMeta().get(DOWNLOADED_IS_READ_MARK);
if (TextUtils.isEmpty(mark)) showRedPoint = true;
@ -767,7 +795,7 @@ public class DownloadManager implements DownloadStatusListener {
}
public boolean isContainsUnreadDownloadedTask() {
for (DownloadEntity downloadEntity : getAll()) {
for (DownloadEntity downloadEntity : getAllDownloadEntityExcludeSilentUpdate()) {
if (DownloadStatus.done.equals(downloadEntity.getStatus())) {
String mark = downloadEntity.getMeta().get(DOWNLOADED_IS_READ_MARK);
if (TextUtils.isEmpty(mark)) {
@ -785,7 +813,7 @@ public class DownloadManager implements DownloadStatusListener {
AppExecutor.getIoExecutor().execute(() -> {
boolean markHasChanged = false;
List<DownloadEntity> all = getAll();
List<DownloadEntity> all = getAllDownloadEntityExcludeSilentUpdate();
for (DownloadEntity downloadEntity : all) {
DownloadStatus status = downloadEntity.getStatus();
if (status == DownloadStatus.done) {
@ -825,7 +853,7 @@ public class DownloadManager implements DownloadStatusListener {
AppExecutor.getIoExecutor().execute(() -> {
boolean markHasChanged = false;
List<DownloadEntity> all = getAll();
List<DownloadEntity> all = getAllDownloadEntityExcludeSilentUpdate();
for (DownloadEntity downloadEntity : all) {
if (downloadEntity.getStatus() != DownloadStatus.done) {
if (isRead) {

View File

@ -2,6 +2,7 @@ package com.gh.download
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkManager
import com.gh.common.util.tryWithDefaultCatch
import java.util.concurrent.TimeUnit
object DownloadWorkManager {
@ -22,12 +23,13 @@ object DownloadWorkManager {
.addTag(TAG_DOWNLOAD)
.build()
WorkManager.getInstance().enqueue(workerRequest)
// TODO 某些特殊场景下会出现 WorkManagerImpl.getInstance() 为空的情况,下版本更新 WorkManager
tryWithDefaultCatch { WorkManager.getInstance().enqueue(workerRequest) }
}
@JvmStatic
fun cancelWorker() {
WorkManager.getInstance().cancelAllWorkByTag(TAG_DOWNLOAD)
tryWithDefaultCatch { WorkManager.getInstance().cancelAllWorkByTag(TAG_DOWNLOAD) }
}
}

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