Compare commits

..

363 Commits

Author SHA1 Message Date
c118d7e4ad tinker_base 3.7.2-bugfix 2020-01-20 09:02:42 +08:00
babc55739b Merge branch '3.7.2-bugfix' of gitlab.ghzs.com:halo/assistant-android into 3.7.2-bugfix 2020-01-19 16:53:03 +08:00
df8790c6ff 更改首页我的光环tab小红点大小 2020-01-19 16:52:57 +08:00
30ccdcd750 Merge branch '3.7.2-bugfix' of gitlab.ghzhushou.com:halo/assistant-android into 3.7.2-bugfix 2020-01-19 16:44:23 +08:00
79d23bb203 兼容新游戏详情视频数量字段 2020-01-19 16:42:13 +08:00
b2c5e6551b 去掉预加载5M限制 2020-01-19 15:59:56 +08:00
ec49d7f20a 处理AndroidVideoCache异常问题 2020-01-19 15:39:51 +08:00
5a35d13d70 Merge branch '3.7.2-bugfix' of gitlab.ghzs.com:halo/assistant-android into 3.7.2-bugfix 2020-01-19 15:34:30 +08:00
dcfa4fdaaf 光环助手V3.7.2 RELEASE 20200117-1830 测试汇总 3,4 https://gitlab.ghzs.com/pm/halo-app-issues/issues/764 2020-01-19 15:34:26 +08:00
43324ca44e Merge branch '3.7.2-bugfix' of gitlab.ghzhushou.com:halo/assistant-android into 3.7.2-bugfix 2020-01-19 15:02:58 +08:00
8e778e8172 修复日志触发上传过于频繁的问题 2020-01-19 14:59:22 +08:00
928a98831e Merge branch '3.7.2-bugfix' of gitlab.ghzs.com:halo/assistant-android into 3.7.2-bugfix 2020-01-19 12:21:15 +08:00
3dc678bc27 修复游戏详情加载变慢问题 2020-01-19 12:21:03 +08:00
d2b19a128d 修复初始化下载服务时可能的闪退问题 2020-01-19 11:50:20 +08:00
cc75cb497d 屏蔽下载限速,修复专题详情闪退问题 2020-01-19 11:13:17 +08:00
4840c5c604 修复插件化弹窗闪退的问题 2020-01-19 10:17:22 +08:00
347cfdb72d tinker_base 3.7.2 2020-01-17 15:25:02 +08:00
06ec87ba6d 解决miui系统更改状态栏颜色导致视频流播放异常 2020-01-17 14:56:32 +08:00
1206800a3d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-17 09:45:23 +08:00
d4763468c1 帮助详情增加长按复制操作 2020-01-17 09:45:16 +08:00
9c1a186a28 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-17 09:37:35 +08:00
bd9b914c18 视频流播放移动网络提醒 2020-01-17 09:37:30 +08:00
d40a57bcaa 微调UI 2020-01-16 15:38:58 +08:00
1892758288 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-16 15:29:38 +08:00
ca2e26756a 修复视频封面显示异常问题 2020-01-16 15:29:28 +08:00
ed5696f4bd Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-16 14:57:51 +08:00
cee34e7d76 处理视频流暂停显示问题 2020-01-16 14:57:44 +08:00
54decbade3 调整详情页自定义栏目显示逻辑 2020-01-16 14:28:38 +08:00
11167670f8 增加通用分享弹窗 MTA 事件 2020-01-16 14:28:15 +08:00
37c7629cf0 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-16 11:17:56 +08:00
947236f85d 修复个别手机下载流量toast提示被覆盖掉的问题 2020-01-16 11:17:49 +08:00
eafa13ec76 修复非曝光入口进入游戏详情触发预约会闪退的问题 2020-01-16 11:13:56 +08:00
7258812537 视频流接口添加随机数 2020-01-16 10:55:29 +08:00
e0a82f5050 优化逻辑 2020-01-16 09:42:29 +08:00
e0e7cbd2a3 处理编译问题 2020-01-16 09:33:57 +08:00
554ec20493 修复视频流滑动卡顿的问题 2020-01-15 22:08:47 +08:00
31c3ed3bc5 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-15 20:44:00 +08:00
466b690ac0 光环助手V3.7.2 RELEASE 20200115-1000 测试汇总3,4,9 https://gitlab.ghzs.com/pm/halo-app-issues/issues/760 2020-01-15 20:43:51 +08:00
0420557f47 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-15 19:58:50 +08:00
c0edbf1a57 光环助手V3.7.2 RELEASE 20200115-1000 测试汇总(1.5.8)https://gitlab.ghzs.com/pm/halo-app-issues/issues/760 2020-01-15 19:58:40 +08:00
374610dbc0 崩溃问题 2020-01-15 19:56:30 +08:00
080ac5f1d5 Merge branches 'dev' and 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-15 17:09:34 +08:00
9dc967087d MIUI系统更改状态栏字体颜色 2020-01-15 17:09:29 +08:00
80a238253d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-15 17:02:15 +08:00
d7b7f11ebf RichEditor onVideoClick 进行Catch操作 2020-01-15 17:02:07 +08:00
9abb14e37f Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-15 15:50:16 +08:00
5fbb93cbee 视频流不循环加载问题 2020-01-15 15:50:12 +08:00
20b75ff046 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-15 15:35:07 +08:00
73374017a5 微调UI 2020-01-15 15:35:00 +08:00
73c3d5cd4d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-15 14:46:30 +08:00
01a02a000f 光环助手V3.7.2 RELEASE 20200113-1830 测试汇总 11 https://gitlab.ghzs.com/pm/halo-app-issues/issues/759 2020-01-15 14:46:25 +08:00
8998f1323f Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-15 14:18:12 +08:00
bb77cf4624 fix bug 2020-01-15 14:18:05 +08:00
772705ed0f Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-15 11:19:36 +08:00
6e2f568ad3 光环助手V3.7.2 RELEASE 20200113-1830 测试汇总3,9,12,13 https://gitlab.ghzs.com/pm/halo-app-issues/issues/759 2020-01-15 11:19:31 +08:00
df20c8235e Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-15 11:07:19 +08:00
4882cc5203 光环助手视频新年活动页面(WEB)(一 3~7,四 5,7,五 4)https://gitlab.ghzs.com/pm/halo-app-issues/issues/742 2020-01-15 11:07:07 +08:00
4fa6a41681 我的光环数据刷新 2020-01-14 18:55:20 +08:00
f77e9d4949 视频流优化 2020-01-14 17:38:24 +08:00
1bc167fe7b Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-14 16:16:40 +08:00
98213ad3ee 完成光环助手V3.7.2 RELEASE(20200111-0250)测试问题汇总 10,13 https://gitlab.ghzs.com/pm/halo-app-issues/issues/757 2020-01-14 16:16:33 +08:00
0b101d693d 修复下载通知刷新时闪烁问题 2020-01-14 15:41:41 +08:00
8655822d88 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-14 14:22:08 +08:00
386923d16e 视频流优化 2020-01-14 11:47:40 +08:00
013536b147 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-14 10:33:38 +08:00
880eef90fb 光环助手V3.7.2 RELEASE(20200111-0250)测试问题汇总(4.5.6)https://gitlab.ghzs.com/pm/halo-app-issues/issues/757 2020-01-14 10:33:25 +08:00
61e3784991 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-13 16:44:02 +08:00
0664d92e62 尝试解决离开页面会继续缓冲问题 2020-01-13 16:43:56 +08:00
aab99b0c29 微调UI 2020-01-13 14:33:18 +08:00
2e6ca9c524 修复隐私弹窗按钮拉伸问题 2020-01-13 14:09:40 +08:00
0a402e4e92 更换一些资源文件 2020-01-13 09:02:14 +08:00
7e75cd7859 视频流无数据不显示引导动画 2020-01-11 15:09:19 +08:00
e3522d4160 视频流延迟隐藏mBottomContainer使用Rxjava实现计时器 2020-01-11 15:00:40 +08:00
c9d0b813b6 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-11 02:35:28 +08:00
3a7e28fac2 光环助手V3.7.2 RELEASE(20200110-1830)测试问题汇总 1,6,9 https://gitlab.ghzs.com/pm/halo-app-issues/issues/755 2020-01-11 02:35:24 +08:00
9aca24c02b Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-11 01:24:35 +08:00
9c818e1470 个人主页问答跳转至相关详情页面 2020-01-11 01:24:20 +08:00
614ed0e7e2 修复从视频 tab 回到桌面再回到光环状态栏变黑的问题 2020-01-11 00:49:40 +08:00
55b1d43e73 修复禁言文案错误问题 2020-01-11 00:31:42 +08:00
25526f3666 update submodule 2020-01-10 23:56:28 +08:00
773f2e798d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-10 23:55:42 +08:00
58b5ec4eb9 尝试解决离开页面仍然会继续缓存视频的问题 2020-01-10 23:53:21 +08:00
007cef39a7 完成20200107-1830的(20200110测试补充3) https://gitlab.ghzs.com/pm/halo-app-issues/issues/751 2020-01-10 23:04:44 +08:00
ba1a702ea1 修复图片上传失败问题(可能是文件名导致) 2020-01-10 22:30:52 +08:00
56d8b58f72 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-10 22:30:21 +08:00
f53c8377e6 修复视频流接口相关问题 2020-01-10 22:30:13 +08:00
cfb1d86e8e 完成20200107-1830的(20200110测试补充3) https://gitlab.ghzs.com/pm/halo-app-issues/issues/751 2020-01-10 21:45:44 +08:00
8f0caa0949 修复我的光环页面滚动脱节的问题 2020-01-10 21:41:04 +08:00
8ef13cb4ff 游戏库入口修改默认图片 2020-01-10 21:37:58 +08:00
e6d4f60d4f Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-10 21:20:47 +08:00
e67f85c084 调整首页UI 2020-01-10 21:20:40 +08:00
5318693650 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-10 20:58:24 +08:00
3bf242b145 光环助手V3.7.2 RELEASE(20200109-1830)测试问题汇总4,10,12,19,20,23 https://gitlab.ghzs.com/pm/halo-app-issues/issues/754 2020-01-10 20:58:18 +08:00
0ba82a334e 光环助手V3.7.2 RELEASE(20200109-1830)测试问题汇总(6.9.11.16.17.24.25.26) https://gitlab.ghzs.com/pm/halo-app-issues/issues/754 2020-01-10 20:56:33 +08:00
0a385bb720 RichEditor 增加js接口(判断当前页面是不是编辑状态) 2020-01-10 19:44:10 +08:00
7658fd2a4f Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-10 18:25:10 +08:00
e40e655bfa 首页大图游戏 摘要前增加游戏标签 2020-01-10 18:25:02 +08:00
cfa000bf88 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-10 17:14:04 +08:00
12c35cebc4 我的光环用户数据刷新 2020-01-10 17:13:59 +08:00
92089e60ce 完成 20200108-2100 测试汇总的 (3,4,6,11) https://gitlab.ghzs.com/pm/halo-app-issues/issues/753 2020-01-10 17:03:39 +08:00
141a6df8ab 修复首页游戏库入口动画无法显示问题 2020-01-10 16:49:50 +08:00
7719e9763d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-10 15:23:34 +08:00
8d3307986d 修改游戏库入口的占位符 2020-01-10 15:23:21 +08:00
d0b7ec39a7 光环助手V3.7.2 RELEASE(20200108-2100)测试问题汇总2,5,7,8,10 https://gitlab.ghzs.com/pm/halo-app-issues/issues/753 2020-01-10 15:13:44 +08:00
cfd198b4ab 光环助手V3.7.2 RELEASE(20200107-1830)测试问题汇总 6 https://gitlab.ghzs.com/pm/halo-app-issues/issues/752 2020-01-10 11:24:56 +08:00
a557c12c6d 问题详情视频审核中/未通过显示默认封面图 2020-01-10 10:16:12 +08:00
6b777d4ec8 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-09 21:01:47 +08:00
882dd95190 光环助手V3.7.2 (20200107-1830) 测试问题汇总4、5、7-9、14、15、19 https://gitlab.ghzs.com/pm/halo-app-issues/issues/752 2020-01-09 21:01:42 +08:00
7764bd29c8 完成 20200107-1830 测试汇总的 10 https://gitlab.ghzs.com/pm/halo-app-issues/issues/752 2020-01-09 20:55:39 +08:00
08730f1ce9 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-09 18:27:37 +08:00
f9c15d3427 fix bug 2020-01-09 18:27:30 +08:00
8e8668036e Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-09 18:25:24 +08:00
cc65eed48d 光环助手V3.7.2 RELEASE(20200107-1830)测试问题汇总(视频相关)https://gitlab.ghzs.com/pm/halo-app-issues/issues/751 2020-01-09 18:25:19 +08:00
29f4e547a1 RichEditor更改初始化Html方法 2020-01-09 17:15:11 +08:00
419003ae23 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-09 16:33:46 +08:00
0519872d81 RichEditor 增加判断是不是作者的接口 2020-01-09 16:33:36 +08:00
e9b52bb70b 修复今日头条推广SDK激活问题以及下载劫持弹窗的显示问题 2020-01-09 16:08:46 +08:00
681ea201c3 更换视频流引导点击动画 2020-01-09 14:06:51 +08:00
a5466bb6ad 修复下载重试过程中速度降为 0K 每秒时会闪退的问题 2020-01-09 12:03:06 +08:00
3a3998ae84 更换首页tab gif文件 2020-01-09 11:42:57 +08:00
7e27502430 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-09 10:49:24 +08:00
8956885f1c fix bug 2020-01-09 10:38:36 +08:00
caeb0a1362 修复已安装列表和视频流列表缺失曝光事件的问题 2020-01-08 20:12:17 +08:00
cc094889b8 完成20200106测试汇总(5~7,19~21) https://gitlab.ghzs.com/pm/halo-app-issues/issues/749 2020-01-08 19:27:37 +08:00
839386c5f4 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/fragment/MainWrapperFragment.java
2020-01-08 19:05:32 +08:00
6c5de65278 首页tab动画部分改为gif 2020-01-08 18:46:24 +08:00
3aadac942c 修复插件化显示异常问题 2020-01-08 16:27:06 +08:00
dca9b49d75 光环助手V3.7.2 (20200106-1838)测试问题汇总12-18 https://gitlab.ghzs.com/pm/halo-app-issues/issues/749 2020-01-08 15:57:20 +08:00
8e764dc22a 启动预约弹窗优化
问题详情视频审核状态显示规则修改
2020-01-08 15:16:20 +08:00
383cf4941e Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/fragment/MainWrapperFragment.java
2020-01-08 10:58:34 +08:00
05510a8588 光环助手V3.7.2首页优化第二期:占位图&预约上线弹窗(预约上线弹窗未经过测试)https://gitlab.ghzs.com/pm/halo-app-issues/issues/744 2020-01-08 10:55:34 +08:00
eb611a9ff1 处理我的光环滑动卡顿 2020-01-07 18:18:20 +08:00
15aa3713e6 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-07 15:42:59 +08:00
7d11713c49 修改视频流页面 2020-01-07 15:42:54 +08:00
66ff610078 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-07 09:47:03 +08:00
f351761d9e 微调视频投稿UI
修复图片详情保存后无法刷新到图片库问题
2020-01-07 09:46:56 +08:00
6bb5e18253 修改问答-关注-推荐关注按钮样式 2020-01-07 09:38:51 +08:00
c44e8cffcc Fix typo 2020-01-06 18:37:52 +08:00
39d4c35504 修复数据统计需求(光环数据后台) 20200103测试问题 https://gitlab.ghzs.com/pm/halo-app-issues/issues/734 2020-01-06 18:24:25 +08:00
d42b57f385 视频功能优化(问答相关)(2.7.8.9)https://gitlab.ghzs.com/pm/halo-app-issues/issues/731 2020-01-06 18:15:40 +08:00
2142a1676e 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-01-06 16:53:13 +08:00
b0fa41bded 隐私弹窗相关图片增加占位符 2020-01-06 16:52:02 +08:00
28f552ca19 完成下载管理与下载提示优化的20200106测试 https://gitlab.ghzs.com/pm/halo-app-issues/issues/726 2020-01-06 16:46:41 +08:00
da0b256054 微调UI 2020-01-06 16:44:16 +08:00
8b477c357a Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-06 16:32:10 +08:00
650075488d 修复意见反馈"添加图片"图标被切割问题 2020-01-06 16:31:59 +08:00
8cff41defa 完成新增游戏时长功能 20200106测试 (2,3,6) https://gitlab.ghzs.com/pm/halo-app-issues/issues/722 2020-01-06 16:25:01 +08:00
6519eca511 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-06 16:22:33 +08:00
85d8463972 我的游戏跳转规则 2020-01-06 16:22:28 +08:00
c762a7c755 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-06 16:17:36 +08:00
142859fd39 首页优化:视频入口、插件化区域、导航栏按钮(20200103测试,20200104测试) https://gitlab.ghzs.com/pm/halo-app-issues/issues/730 2020-01-06 16:17:25 +08:00
d7f84ff3c8 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-06 14:04:40 +08:00
6c4545e364 完成20200104测试补充2-7 https://gitlab.ghzs.com/pm/halo-app-issues/issues/732 2020-01-06 14:04:34 +08:00
a3d9f12414 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-06 11:30:12 +08:00
412d2ff9dc 修复数据库版本升级问题 2020-01-06 11:30:05 +08:00
65f8440637 降级查看大图的库避免在新版本 MUMU 模拟器上的初始化问题 2020-01-06 11:29:33 +08:00
f06359f5c3 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-04 18:42:32 +08:00
433088116e 微调UI 2020-01-04 18:42:09 +08:00
c93e55f306 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-04 18:12:17 +08:00
e613066ed3 关注按钮样式 2020-01-04 18:12:11 +08:00
9aabfde5b0 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-04 18:06:58 +08:00
9f4c9431b9 修改图片详情页面的实现方式,适配大图/长图 2020-01-04 18:06:50 +08:00
74f64d9782 使下载完成通知在点击安装后消失 https://gitlab.ghzs.com/pm/halo-app-issues/issues/726 2020-01-04 17:55:25 +08:00
d79b3f10e8 评论被隐藏跳转去修改 2020-01-04 15:42:31 +08:00
b29d32c8f2 Merge branches 'dev' and 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-04 14:32:10 +08:00
b8ec93c6a1 完成20200104测试问题:2-5 https://gitlab.ghzs.com/pm/halo-app-issues/issues/720 2020-01-04 14:32:05 +08:00
dad3c9aee7 修复华为设备下载完成通知不能置顶的问题 2020-01-04 11:50:27 +08:00
833e0406f0 修改游戏广告问题 2020-01-04 10:28:24 +08:00
3d6b556dfd 修复评论标签不显示问题 2020-01-04 09:42:31 +08:00
ad0a5525f0 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-03 18:41:10 +08:00
a012c3e3de 修改视频流下载按钮样式 2020-01-03 18:41:06 +08:00
6c2d489940 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-03 18:31:38 +08:00
0ea56b01eb 微调意见反馈UI 2020-01-03 18:31:31 +08:00
f65c226657 处理一个数组越界闪退 2020-01-03 18:25:43 +08:00
006b82381b Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-03 18:21:30 +08:00
059414b9f8 更换首页tab动效 2020-01-03 18:21:26 +08:00
93c1105346 微调隐私弹窗UI 2020-01-03 18:15:34 +08:00
7ca92e8b7f Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-03 17:56:11 +08:00
eeb7415086 Merge branch '3.7.1_game' into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/fragment/MainWrapperFragment.java
#	app/src/main/java/com/gh/gamecenter/fragment/SearchToolWrapperFragment.java
#	app/src/main/java/com/halo/assistant/HaloApp.java
#	app/src/main/res/layout/fragment_main.xml
2020-01-03 17:55:59 +08:00
9a288e8870 修复游戏评论使用的星星库在三星安卓10设备上的闪退问题 2020-01-03 17:45:23 +08:00
351fefd57b Merge remote-tracking branch 'origin/dev' into dev 2020-01-03 17:23:30 +08:00
4915cdc3ba 完成下载管理与下载提示优化20200101测试的 1,3,4 及20200103测试的 1,2 https://gitlab.ghzs.com/pm/halo-app-issues/issues/726 2020-01-03 17:23:21 +08:00
9d044a4001 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-03 17:19:47 +08:00
8e465c17dd 视频功能优化(基础功能)(1.2.3.4.5.7) https://gitlab.ghzs.com/pm/halo-app-issues/issues/715 2020-01-03 17:19:38 +08:00
fa73ac790c 修复模拟器应用内更新的闪退问题 2020-01-03 17:19:11 +08:00
899f442f14 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-03 17:07:42 +08:00
698af5d584 光环助手V3.7.2-评论引导标签 20200103测试 https://gitlab.ghzs.com/pm/halo-app-issues/issues/728 2020-01-03 17:07:37 +08:00
66dea77546 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-03 16:26:38 +08:00
eed2eed992 发表游戏评论支持跳转在线客服&意见反馈(20200103测试问题)https://gitlab.ghzs.com/pm/halo-app-issues/issues/723 2020-01-03 16:26:31 +08:00
913c0027a6 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-03 15:38:51 +08:00
a7884325c8 我的游戏评论数据刷新 2020-01-03 15:38:38 +08:00
a7caa063ef Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-03 15:31:46 +08:00
ee99895cba 视频功能优化(数据与算法)https://gitlab.ghzs.com/pm/halo-app-issues/issues/737 2020-01-03 15:31:42 +08:00
cf7a14e80a 问答推荐跳转视频流 2020-01-03 15:15:29 +08:00
07a64d118a 光环助手前端优化汇总(2019年12月)(11~15)https://gitlab.ghzs.com/pm/halo-app-issues/issues/745 2020-01-03 11:11:29 +08:00
72329d0222 微调隐私弹窗UI 2020-01-03 10:52:07 +08:00
16e85e9222 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-03 10:50:46 +08:00
dd11883eab 修复MTA事件缺失问题 2020-01-03 10:50:36 +08:00
be70ce8551 完成0102测试问题1-8 https://gitlab.ghzs.com/pm/halo-app-issues/issues/720 2020-01-03 10:33:50 +08:00
d428c46957 修复一键修复按钮常驻的问题 2020-01-02 18:29:58 +08:00
516b956269 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-02 18:12:36 +08:00
8bb90f4d4c 更换底部icon动效 2020-01-02 18:12:31 +08:00
2f9e9fe976 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-02 17:59:42 +08:00
bf2271ac06 部分页面跳转视频详情添加path路径 2020-01-02 17:59:35 +08:00
f279564e02 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-02 17:38:53 +08:00
386eafa0bc 光环助手前端优化汇总(2019年12月)1~9.16.17 https://gitlab.ghzs.com/pm/halo-app-issues/issues/745 2020-01-02 17:38:46 +08:00
619b5a3cc3 首页优化:视频入口、插件化区域、导航栏按钮(14)https://gitlab.ghzs.com/pm/halo-app-issues/issues/730 2020-01-02 17:23:08 +08:00
d0391c779d 修改隐私弹窗默认文案 2020-01-02 16:44:38 +08:00
fc9d3f2e91 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-02 16:31:47 +08:00
42c7123d2d 视频功能优化(问答相关) https://gitlab.ghzs.com/pm/halo-app-issues/issues/731 2020-01-02 16:31:39 +08:00
8e66f80360 修复移动网络下在视频 tab 点暂不播放会退出光环的问题 2020-01-02 16:26:56 +08:00
b80fab06ad 修复新增游戏时长功能部分测试问题 https://gitlab.ghzs.com/pm/halo-app-issues/issues/722 2020-01-02 16:23:33 +08:00
943c359c22 Merge remote-tracking branch 'origin/dev' into dev 2020-01-02 11:13:30 +08:00
8631045874 更新今日头条广告SDK(增加上报OAID) https://gitlab.ghzs.com/pm/halo-app-issues/issues/743 2020-01-02 11:13:14 +08:00
5991a90353 设置首页底部padding 2020-01-02 10:14:19 +08:00
8534455344 恢复设置页面的版本更新提示 https://gitlab.ghzs.com/pm/halo-app-issues/issues/720 2020-01-02 09:57:00 +08:00
1a21fceeb7 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2020-01-02 09:45:43 +08:00
274739c885 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/video/detail/VideoAdapter.kt
2020-01-02 09:45:37 +08:00
5134fa19be 补充遗漏的下载按钮打开网页逻辑 https://gitlab.ghzs.com/pm/halo-app-issues/issues/727 2020-01-02 09:32:56 +08:00
7342e94bdc 完成1231测试问题1-6 https://gitlab.ghzs.com/pm/halo-app-issues/issues/720 2020-01-02 09:31:50 +08:00
28bf579518 完成光环助手V3.7.2数据统计需求 https://gitlab.ghzs.com/pm/halo-app-issues/issues/734 2019-12-31 21:09:10 +08:00
9e490ef349 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-31 18:19:35 +08:00
548206792e 首页tab切换改变颜色 2019-12-31 18:19:30 +08:00
c87d7f9c28 视频详情广告 2019-12-31 18:18:36 +08:00
cfe1584fc3 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.
2019-12-31 16:26:49 +08:00
137a95f5ab 发表游戏评论支持跳转在线客服&意见反馈(1225测试问题) https://gitlab.ghzs.com/pm/halo-app-issues/issues/723 2019-12-31 16:25:42 +08:00
6ab8b24353 修复无法删除下载目录旧更新包的问题 2019-12-31 15:24:44 +08:00
1515cc1ddd 修复隐私弹窗页面切换时状态栏占位问题 2019-12-31 14:47:00 +08:00
abfd4834ef Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-31 14:18:12 +08:00
03032a0dbd 首页优化:视频入口、插件化区域、导航栏按钮(6) https://gitlab.ghzs.com/pm/halo-app-issues/issues/730 2019-12-31 14:18:05 +08:00
75545a5929 修改首页视频退出全屏后页面白屏 2019-12-31 10:42:03 +08:00
1425a95bc8 完成标签列表页的曝光统计 https://gitlab.ghzs.com/pm/halo-app-issues/issues/734 2019-12-31 09:54:00 +08:00
23674a1c55 处理接口未同步至正式环境造成的闪退问题 2019-12-31 09:52:49 +08:00
caf0a8d5f5 修复滑动视频闪退问题 2019-12-31 09:28:15 +08:00
b11928528c Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-30 18:23:35 +08:00
cf9bd70c6c web端跳转到光环视频相关页面 2019-12-30 18:23:30 +08:00
c6ab68e9b4 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-30 18:16:03 +08:00
899da43682 下载行为监控-数据埋点需求 https://gitlab.ghzs.com/pm/halo-app-issues/issues/738 2019-12-30 18:15:30 +08:00
1825f713b3 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-30 17:04:52 +08:00
760bc9b63c 视频详情游戏下载 2019-12-30 17:04:46 +08:00
4974c105bf 处理答案/文章内容有反斜杠导致无法插入的问题 2019-12-30 17:04:02 +08:00
9c910ce6de 首页底部切换Tab播放动画 2019-12-30 11:56:53 +08:00
fcd1c2d418 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-28 18:37:42 +08:00
5c0c227c3b 更换底部导航icon 2019-12-28 18:37:37 +08:00
a69669a7ca 优化一些UI问题 2019-12-28 18:31:29 +08:00
166e2e341a Merge branch 'dev' of gitlab.ghzhushou.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.
2019-12-28 18:12:16 +08:00
8cb689cc99 修复下载通知分组问题(删除分组内所有通知后会残留分组摘要) 2019-12-28 18:11:07 +08:00
1dd5c5fd40 修复模拟器启动时没有删除旧光环安装包的问题 2019-12-28 17:57:43 +08:00
92719c538e Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-28 15:40:33 +08:00
3448dfddef 完成20191228测试 https://gitlab.ghzs.com/pm/halo-app-issues/issues/716 2019-12-28 15:40:26 +08:00
b190b31afa 处理文章/答案摘要包含英文双引号时造成的解析问题 2019-12-28 11:38:11 +08:00
083a62ed9d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-28 11:00:18 +08:00
5f0bfd1184 暴力预防下载通知状态改变时无法刷新问题 2019-12-28 11:00:11 +08:00
15bb7d654c 修复在模拟器上进行应用内更新出现的安装界面消失问题 2019-12-27 18:26:23 +08:00
f42278b91f 修复在模拟器上进行应用内更新出现的安装界面消失问题 2019-12-27 18:14:45 +08:00
aa23d515c6 恢复误删的首页启动模式 2019-12-27 18:10:35 +08:00
b3417749ed Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-27 17:34:38 +08:00
4c33977568 完成1226测试问题 https://gitlab.ghzs.com/pm/halo-app-issues/issues/720 2019-12-27 17:34:33 +08:00
1ecd83b6af 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.
2019-12-27 16:33:40 +08:00
b202302a7e 调整隐私弹窗间距 2019-12-27 16:31:51 +08:00
7450edd177 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-27 16:18:58 +08:00
4c7ab844e8 首页视频流页面 2019-12-27 16:18:52 +08:00
fd6581671d 调整首页插件化区域显示规则
修复启动过程中部分数据无法初始化问题
2019-12-27 15:42:35 +08:00
71cc0962d3 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-26 21:07:49 +08:00
9c70d802b5 1225测试问题:二(1.3.4.5.7.8)https://gitlab.ghzs.com/pm/halo-app-issues/issues/724 2019-12-26 21:07:40 +08:00
ed6bec0cfc Merge branch 'dev' of gitlab.ghzhushou.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.
2019-12-26 18:05:38 +08:00
36834cfec7 隐私政策说明(第二期)(动态设置标题)https://gitlab.ghzs.com/pm/halo-app-issues/issues/717 2019-12-26 18:04:38 +08:00
7dfaf45dc2 完成下载管理和板块轮播图的曝光统计 https://gitlab.ghzs.com/pm/halo-app-issues/issues/734 2019-12-26 17:49:21 +08:00
5efddb05b3 视频上传封面圆角 2019-12-26 11:56:46 +08:00
f46122787c Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-26 11:44:32 +08:00
1b8cde1c91 视频功能优化(基础功能)(二) https://gitlab.ghzs.com/pm/halo-app-issues/issues/715 2019-12-26 11:44:24 +08:00
1694603cd0 完成1225测试问题:1,2,3,5 https://gitlab.ghzs.com/pm/halo-app-issues/issues/719 2019-12-26 11:27:20 +08:00
4243f37126 我的光环页面滑动冲突 2019-12-25 17:58:45 +08:00
63e0b9887c Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-25 17:39:18 +08:00
201efd9628 首页优化:视频入口、插件化区域、导航栏按钮(1.2.3.4.5.15.16)https://gitlab.ghzs.com/pm/halo-app-issues/issues/730 2019-12-25 17:39:04 +08:00
c7c29b7ca8 Merge remote-tracking branch 'origin/dev' into dev 2019-12-25 14:08:15 +08:00
0b3fd3a123 处理曝光闪退问题 2019-12-25 14:07:59 +08:00
99e988a0d9 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-25 14:07:31 +08:00
eaa3b81e31 修改评论标签显示 2019-12-25 14:07:19 +08:00
dbbf9a846e 修改视频滑动引导 2019-12-25 11:56:06 +08:00
af8b336434 支持插件使用光环进行二次跳转 https://gitlab.ghzs.com/pm/halo-plugin-issues/issues/120 2019-12-25 11:35:00 +08:00
ce84c0f9c9 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-25 10:40:12 +08:00
0f8d9cd5d3 隐私政策说明(第二期) https://gitlab.ghzs.com/pm/halo-app-issues/issues/717 2019-12-25 10:40:06 +08:00
cb70e12632 修复已安装页面可能的闪退问题 2019-12-25 09:57:45 +08:00
a5ad403614 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-24 18:02:20 +08:00
e674a8313a 视频详情引导动画 2019-12-24 18:02:14 +08:00
1cef4bb53d 光环助手-意见反馈优化(三) https://gitlab.ghzs.com/pm/halo-app-issues/issues/724 2019-12-24 17:38:48 +08:00
3851aeb790 发表游戏评论支持跳转在线客服&意见反馈(MTA)https://gitlab.ghzs.com/pm/halo-app-issues/issues/723 2019-12-24 16:17:53 +08:00
7680e2e125 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-24 15:43:09 +08:00
f674aa4a79 下载重试增加移动网络重试 2019-12-24 15:41:10 +08:00
be1533a5df 视频播放数据埋点(点击行为、播放行为) 2019-12-24 10:49:26 +08:00
eca3bdd4e5 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-23 18:44:01 +08:00
c885579516 游戏评论对接web编辑器 2019-12-23 18:43:56 +08:00
341d849e29 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-23 18:33:32 +08:00
2bb5c79c38 光环助手V3.7.2-下载管理与下载提示优化(三)https://gitlab.ghzs.com/pm/halo-app-issues/issues/726 2019-12-23 18:33:23 +08:00
fa26e1a17b 完成轮播图数据上报 https://gitlab.ghzs.com/pm/halo-app-issues/issues/734 2019-12-23 10:17:19 +08:00
8ed76089eb 完成游戏预约数据上报 https://gitlab.ghzs.com/pm/halo-app-issues/issues/734 2019-12-22 20:36:23 +08:00
678418da0b 完成部分曝光数据上报(新首页&安利墙) https://gitlab.ghzs.com/pm/halo-app-issues/issues/734 2019-12-22 18:33:45 +08:00
1c11fc4469 光环助手V3.7.2-下载管理与下载提示优化(一.二.四.七)https://gitlab.ghzs.com/pm/halo-app-issues/issues/726 2019-12-21 18:01:29 +08:00
78f277fd6d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-21 15:37:26 +08:00
5520fd7122 修改 游戏时长记录 弹窗 2019-12-21 15:37:18 +08:00
cb6ce2e14f Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-21 15:19:50 +08:00
80933e82eb 限制视频上下滑动频率 2019-12-21 15:19:44 +08:00
e32dce2ef9 视频功能优化(基础功能)(三.四)https://gitlab.ghzs.com/pm/halo-app-issues/issues/715 2019-12-21 14:28:57 +08:00
e252a9ebf8 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-20 19:31:59 +08:00
08936a22c8 光环助手-意见反馈优化(二.四.五1)https://gitlab.ghzs.com/pm/halo-app-issues/issues/724 2019-12-20 19:31:46 +08:00
3fea57d05f Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-20 14:54:43 +08:00
52ae5fc451 视频详情UI 2019-12-20 14:53:43 +08:00
045dea265d 3.7.1-game tinker base 2019-12-20 10:09:36 +08:00
501282f243 意见反馈增加游戏收录弹窗 2019-12-20 09:53:48 +08:00
998cf70723 游戏库图标增加占位符/预加载
升级fresco库
对DiffUtilAdapter DiffUtil 进行 try catch 处理
2019-12-19 16:33:49 +08:00
1a10fcac71 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-19 15:03:20 +08:00
ee5862eddd 视频预加载 2019-12-19 15:03:12 +08:00
c1527ec37e 增加帮助详情页面 2019-12-19 10:04:21 +08:00
eb112b358e tinker base 3.7.1-game-tab 2019-12-18 17:24:33 +08:00
b860ab912a 修改游戏库显示逻辑 2019-12-18 16:30:15 +08:00
b14ee68882 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-18 12:03:04 +08:00
44065fcb06 意见反馈增加 使用帮助 模块(部分细节尚未优化) https://gitlab.ghzs.com/pm/halo-app-issues/issues/724 2019-12-18 12:02:53 +08:00
ec5305b76f Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-18 11:34:25 +08:00
ddfb651d6a 我的光环缓存数据 2019-12-18 11:34:20 +08:00
8a828a3250 修复下载数据(新)插件化更新上报错乱的问题 2019-12-18 10:40:12 +08:00
31f5795e27 我的游戏评论 https://gitlab.ghzs.com/pm/halo-app-issues/issues/719 2019-12-17 17:05:41 +08:00
dbde817b59 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-17 16:49:23 +08:00
83e251492d web端跳转到光环视频相关页面定义host 2019-12-17 16:49:17 +08:00
5fa22c7f5d 我的游戏评论 2019-12-17 16:46:26 +08:00
b4ad18c806 设置增加"流量下载提醒"选项 2019-12-17 16:46:10 +08:00
61eb35cf31 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-17 16:16:29 +08:00
07e54d5b5e 修改 下载/更新 红点提示逻辑 2019-12-17 16:16:20 +08:00
e0c27f721c 修复消费 windowInset 时在部分 4.4 设备上的闪退问题 2019-12-17 11:53:48 +08:00
d2bf6bb211 修复一些闪退问题 2019-12-17 11:33:01 +08:00
e2681494db 切换首页tab更改状态栏颜色 2019-12-17 10:30:12 +08:00
ac1d078681 我的光环页面改版&优化已完成 2019-12-16 17:25:55 +08:00
624d9c1e2d Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev 2019-12-13 18:33:26 +08:00
892cc3cdde 我的光环UI 2019-12-13 18:33:20 +08:00
fd7b9263bf 完成下载按钮支持打开 H5 页面 https://gitlab.ghzs.com/pm/halo-app-issues/issues/727 2019-12-13 15:23:41 +08:00
a9428ddb3b 启动app删除视频缓存文件并添加nomedia文件 2019-12-13 10:42:29 +08:00
319f526e0f 增加视频浏览记录 2019-12-12 18:30:23 +08:00
4755542933 Merge branch 'dev' of gitlab.ghzs.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/video/detail/DetailPlayerView.kt
#	app/src/main/java/com/gh/gamecenter/video/detail/VideoAdapter.kt
#	app/src/main/java/com/gh/gamecenter/video/detail/VideoDetailContainerFragment.kt
#	app/src/main/res/layout/layout_video_detail_base.xml
#	app/src/main/res/layout/layout_video_detail_surface.xml
2019-12-12 14:58:40 +08:00
f221e20169 视频详情增加静音、全屏、拖动进度等 2019-12-12 14:45:55 +08:00
a149666d3a 视频投稿支持更换封面图 2019-12-11 16:41:58 +08:00
0ff428b61a Merge branch 'dev_3.7.2' into 'dev'
Dev 3.7.2

See merge request !9
2019-12-11 15:14:19 +08:00
cfedc72955 Merge branch 'dev_3.7.2' of gitlab.ghzs.com:halo/assistant-android into dev_3.7.2 2019-12-11 15:11:30 +08:00
16de588c30 重新整理图片剪裁以便兼容后续视频封面更换 2019-12-11 15:11:21 +08:00
779d907397 Merge branch 'dev_3.7.2' of gitlab.ghzs.com:halo/assistant-android into dev_3.7.2 2019-12-11 15:09:35 +08:00
f91e2e41b6 修改视频详情UI 2019-12-11 15:09:30 +08:00
a04e4874f3 基本完成下载限速功能 https://gitlab.ghzs.com/pm/halo-app-issues/issues/726 2019-12-11 14:54:39 +08:00
d303b67e35 修改我的光环页面 2019-12-11 10:56:27 +08:00
31c0c43d14 Merge branch 'dev_3.7.2' of gitlab.ghzs.com:halo/assistant-android into dev_3.7.2 2019-12-10 18:20:16 +08:00
fafb73d03c 跳转抖音 2019-12-10 18:20:11 +08:00
e4ee4d9efe 实名认证 2019-12-10 18:16:52 +08:00
3a043b2704 发表游戏评论支持跳转在线客服&意见反馈 https://gitlab.ghzs.com/pm/halo-app-issues/issues/723 2019-12-10 17:06:10 +08:00
8c9c7309a5 去除调试入后 2019-12-10 11:35:40 +08:00
09330e9cbf 提高时长统计的准确性 2019-12-10 11:33:42 +08:00
08ad62dc70 Merge branch 'dev_3.7.2' of gitlab.ghzs.com:halo/assistant-android into dev_3.7.2
# Conflicts:
#	app/src/main/java/com/halo/assistant/fragment/SettingsFragment.java
2019-12-09 17:51:24 +08:00
464482a507 光环助手V3.7.2-新增游戏时长功能(玩过页面展示完成,数据上报部分统计不准)https://gitlab.ghzs.com/pm/halo-app-issues/issues/722 2019-12-09 17:49:30 +08:00
d449b1266f 跳转高级认证 2019-12-09 11:31:44 +08:00
6d0c4b18d6 设置页面功能调整顺序 2019-12-09 11:30:32 +08:00
a83d1b5761 Merge branch 'dev_3.7.2' of gitlab.ghzs.com:halo/assistant-android into dev_3.7.2
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
2019-12-06 16:18:21 +08:00
99d564278e 我的游戏评论 2019-12-06 16:14:36 +08:00
482f45d43f 我的光环页面改版 2019-12-06 16:13:36 +08:00
21335a843a 版本以及API升到3.7.2 2019-12-06 10:21:50 +08:00
d02a527b36 光环助手V3.7.2-新增游戏时长功能(基本完成数据提交部分) https://gitlab.ghzs.com/pm/halo-app-issues/issues/722 2019-12-05 18:10:35 +08:00
75883e11d8 权限弹窗优化(引导设置 “通知管理” 第二期)https://gitlab.ghzs.com/pm/halo-app-issues/issues/716 2019-12-04 11:54:37 +08:00
563 changed files with 19720 additions and 5684 deletions

View File

@ -207,6 +207,7 @@ dependencies {
implementation "com.facebook.fresco:fresco:${fresco}"
implementation "com.facebook.fresco:animated-gif:${fresco}"
implementation "com.facebook.fresco:animated-drawable:${fresco}"
implementation "com.squareup.okhttp3:okhttp:${okHttp}"
@ -259,7 +260,9 @@ dependencies {
implementation "com.squareup.picasso:picasso:${picasso}"
// for video streaming
implementation "com.shuyu:gsyVideoPlayer-java:$gsyVideo"
implementation ("com.shuyu:gsyVideoPlayer-java:$gsyVideo",{
exclude module: "gsyvideoplayer-androidvideocache"
})
implementation "com.shuyu:gsyVideoPlayer-armv7a:$gsyVideo"
implementation "com.shuyu:gsyVideoPlayer-x86:$gsyVideo"
@ -278,20 +281,25 @@ 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.aliyun.dpa:oss-android-sdk:2.9.2'
implementation "com.airbnb.android:lottie:$lottie"
implementation("com.github.piasy:BigImageViewer:$bigImageViewer", {
exclude group: 'com.squareup.okhttp3'
})
implementation project(':libraries:LGLibrary')
implementation project(':libraries:MTA')
implementation project(':libraries:QQShare')
implementation project(':libraries:TalkingData')
implementation project(':libraries:UmengPush')
// implementation project(':libraries:WechatShare')
implementation project(':libraries:LogHub')
implementation project(':libraries:im')
implementation project(':libraries:Matisse')
implementation project(path: ':libraries:gsyVideoPlayer-proxy_cache')
}
File propFile = file('sign.properties')
if (propFile.exists()) {

Binary file not shown.

View File

@ -28,6 +28,10 @@
<!-- 修改系统设置的权限 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
<!-- bugly with tinker -->
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
@ -37,7 +41,8 @@
com.shuyu.gsyvideoplayer.armv7a,
com.shuyu.gsyvideoplayer.x86,
com.shuyu.gsy.base,
shuyu.com.androidvideocache" />
shuyu.com.androidvideocache,
pl.droidsonroids.gif" />
<!-- 去掉 SDK 一些流氓权限 -->
<uses-permission
@ -78,6 +83,7 @@
<activity
android:name="com.gh.gamecenter.MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/AppCompatTheme.APP"
@ -190,10 +196,6 @@
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.SuggestSelectActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.SuggestionActivity"
android:screenOrientation="portrait" />
@ -448,6 +450,19 @@
android:name="com.gh.gamecenter.game.upload.GameSubmissionActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.halo.assistant.fragment.user.UserPortraitCropImageActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.HelpAndFeedbackActivity"
android:windowSoftInputMode="stateHidden"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.help.HelpDetailActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.comment.CommentActivity"
android:screenOrientation="portrait"
@ -456,8 +471,12 @@
<activity
android:name="com.gh.gamecenter.video.detail.VideoDetailActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait"
android:theme="@style/TransparentStatusBarAndNavigationBar" />
<activity
android:name=".gamedetail.myrating.MyRatingActivity"
android:screenOrientation="portrait" />
<!-- 使用小米/华为推送弹窗功能提高推送成功率-->
<activity

View File

@ -0,0 +1 @@
{"v":"5.5.9","fr":60,"ip":0,"op":90,"w":1080,"h":202,"nm":"click","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"椭圆形","sr":1,"ks":{"o":{"a":0,"k":20,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204,1455,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":[{"d":1,"ty":"el","s":{"a":0,"k":[24,24],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"椭圆形","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":63,"s":[10]},{"t":70,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204,1455,0],"ix":2},"a":{"a":0,"k":[0,0,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":39,"s":[100,100,100]},{"t":49,"s":[110,110,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[36,36],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"圆环","refId":"comp_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.531],"y":[0]},"t":28,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":38,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.526],"y":[0]},"t":48,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.446],"y":[0]},"t":63,"s":[50]},{"t":82,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[125.951,79.658,0],"ix":2},"a":{"a":0,"k":[205.951,1458.658,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.601,0.601,0.333],"y":[0,0,0]},"t":28,"s":[50,50,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.528,0.528,0.333],"y":[0,0,0]},"t":38,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.526,0.526,0.333],"y":[0,0,0]},"t":48,"s":[120,120,100]},{"t":63,"s":[100,100,100]}],"ix":6}},"ao":0,"w":1080,"h":1920,"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"点击手","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.596],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.515],"y":[0]},"t":63,"s":[100]},{"t":83,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.507],"y":[0]},"t":10,"s":[6]},{"t":30,"s":[2]}],"ix":10},"p":{"a":0,"k":[178.982,123.325,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.489,0.489,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"t":30,"s":[90,90,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.33,-8.3],[3.89,0.27],[-4.4,-1.68],[-4.33,-0.67],[-4.08,9.32],[3.33,5.44],[3.39,4.6],[0.87,-3.7],[3.6,-0.86],[1.03,-0.21],[2.34,-0.53],[0.96,1.15],[4.22,5.48],[-1.18,-4.56]],"o":[[1.11,1.71],[-3.89,-0.27],[6.42,2.5],[4.33,0.66],[1.63,-5.32],[-3.34,-5.45],[-1.68,-2.1],[-0.71,3.14],[-3.43,0.95],[-0.57,0.08],[-3.86,1.12],[-3.23,-3.94],[-1.89,-2.28],[2.42,4.64]],"v":[[-5.387,9.698],[-10.717,8.498],[-12.327,15.628],[5.813,21.748],[23.313,11.778],[20.273,-1.202],[11.563,-13.962],[5.393,-12.362],[1.083,-13.722],[-2.087,-9.742],[-5.707,-11.752],[-8.777,-7.572],[-18.297,-20.542],[-23.827,-17.832]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","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":"路径备份 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}],"markers":[]}

View File

@ -0,0 +1 @@
{"v":"5.5.9","fr":60,"ip":0,"op":120,"w":1080,"h":586,"nm":"上滑","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"手","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.642],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.558],"y":[0]},"t":60,"s":[100]},{"t":71,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.479,"y":0},"t":3,"s":[611,475,0],"to":[0,-62.75,0],"ti":[0,62.75,0]},{"t":40,"s":[611,98.5,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[90,90,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-7.78,-12.06],[5.68,0.39],[-6.42,-2.45],[-6.32,-0.97],[-5.95,13.55],[4.87,7.91],[4.94,6.69],[1.26,-5.37],[5.25,-1.25],[1.5,-0.3],[3.4,-0.77],[1.4,1.68],[6.15,7.98],[-1.73,-6.64]],"o":[[1.62,2.49],[-5.68,-0.39],[9.37,3.63],[6.31,0.98],[2.39,-7.74],[-4.87,-7.92],[-2.45,-3.05],[-1.05,4.57],[-4.99,1.39],[-0.83,0.13],[-5.63,1.63],[-4.71,-5.72],[-2.75,-3.31],[3.52,6.76]],"v":[[-7.86,14.26],[-15.64,12.52],[-17.99,22.89],[8.47,31.78],[33.98,17.29],[29.55,-1.59],[16.85,-20.15],[7.86,-17.83],[1.56,-19.8],[-3.05,-14.02],[-8.33,-16.94],[-12.44,-11.045],[-26.761,-30.19],[-34.75,-25.78]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"矩形","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.715],"y":[0]},"t":57,"s":[100]},{"t":67,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[525,228.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.491,"y":0},"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[24.328,180.5],[-22,180.5],[-22,204.5],[24.328,204.5]],"c":true}]},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[24.328,-207.5],[-22,-207.5],[-22,204.5],[24.328,204.5]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"蒙版 1"}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[6,137],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,1,1,0.5,1,1,1,1,1,1,1,0,1,0.5,0.5,1,0],"ix":9}},"s":{"a":0,"k":[0,-68.5],"ix":5},"e":{"a":0,"k":[0,68.5],"ix":6},"t":1,"nm":"Gradient Fill 1","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},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":33,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":3,"op":123,"st":3,"bm":0}],"markers":[]}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"v":"5.5.9","fr":30,"ip":0,"op":20,"w":66,"h":66,"nm":"tab_index","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"椭圆形备份","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.596],"y":[0]},"t":0,"s":[0]},{"t":6,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,40.493,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.167,0.167,0.167],"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.54,0.54,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.555,0.555,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.552,0.552,0.333],"y":[0,0,0]},"t":13,"s":[90,90,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[5,5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.635],"y":[0]},"t":0,"s":[0]},{"t":8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","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":1.5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","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.5,"op":59.5,"st":-0.5,"bm":0},{"ddd":0,"ind":2,"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,32.993,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.508,0.508,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.488,0.488,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.502,0.502,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.534,0.534,0.333],"y":[0,0,0]},"t":13,"s":[95,95,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.24,-1.21],[-1.93,-1.89],[-0.24,-0.57],[0,-0.06],[0,-2.63],[1.76,0],[0,0],[0,1.72],[0,2.63],[-0.24,0.61],[-0.03,0.02],[-1.93,1.89]],"o":[[1.92,1.89],[0.02,0.02],[0.24,0.57],[0,2.63],[0,1.72],[0,0],[-1.76,0],[0,-2.62],[0,-0.07],[0.25,-0.61],[1.92,-1.89],[1.24,-1.21]],"v":[[2.26,-9.09],[8.03,-3.42],[8.76,-2.38],[9,-1.02],[9,6.88],[5.82,10],[-5.82,10],[-9,6.88],[-9,-0.99],[-8.71,-2.38],[-8.01,-3.43],[-2.23,-9.09]],"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":[-4.902,-4.663],"ix":5},"e":{"a":0,"k":[8.159,8.646],"ix":6},"t":1,"nm":"Gradient Fill 1","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":60,"st":0,"bm":0}],"markers":[]}

View File

@ -0,0 +1 @@
{"v":"5.5.9","fr":30,"ip":0,"op":20,"w":66,"h":66,"nm":"tab_video","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 1","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.771],"y":[0]},"t":0,"s":[0]},{"t":5,"s":[100]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-3.742,6.835,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[30.937,31.042,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sr","sy":2,"d":1,"pt":{"a":0,"k":3,"ix":3},"p":{"a":0,"k":[0,0],"ix":4},"r":{"a":0,"k":0,"ix":5},"or":{"a":0,"k":29.286,"ix":7},"os":{"a":0,"k":75,"ix":9},"ix":1,"nm":"多边星形路径 1","mn":"ADBE Vector Shape - Star","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":13,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-20.75,-13.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[102.743,88.578],"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":"多边星形 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.657],"y":[0]},"t":0,"s":[0]},{"t":8,"s":[100]}],"ix":2},"o":{"a":0,"k":-115,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"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,33.004,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.508,0.508,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.488,0.488,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.502,0.502,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.534,0.534,0.333],"y":[0,0,0]},"t":13,"s":[95,95,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.16,0.38],[3.22,-0.55],[0.38,-2.16],[-0.55,-3.22],[-2.16,-0.38],[-1.63,0],[-1.61,0.27],[-0.38,2.16],[0.55,3.22]],"o":[[-0.38,-2.16],[-3.22,-0.55],[-2.16,0.38],[-0.55,3.22],[0.38,2.16],[1.61,0.27],[1.63,0],[2.16,-0.38],[0.55,-3.22],[0,0]],"v":[[9.09,-4.86],[4.86,-9.09],[-4.86,-9.09],[-9.09,-4.86],[-9.09,4.86],[-4.86,9.09],[0,9.5],[4.86,9.09],[9.09,4.86],[9.09,-4.86]],"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":[-5.174,-4.43],"ix":5},"e":{"a":0,"k":[8.612,8.214],"ix":6},"t":1,"nm":"Gradient Fill 3","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":60,"st":0,"bm":0}],"markers":[]}

View File

@ -63,6 +63,12 @@ RE.setHtml = function(contents) {
RE.editor.innerHTML = decodeURIComponent(contents.replace(/\+/g, '%20'));
}
// 后续初始化html代码,都用该方法
RE.setHtmlByVideoStatus = function(contents) {
RE.editor.innerHTML = decodeURIComponent(contents.replace(/\+/g, '%20'));
}
// Deprecated
RE.getHtml = function() {
return RE.editor.innerHTML;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -9,23 +9,17 @@ import android.text.TextUtils;
import android.view.Window;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import com.gh.common.constant.Constants;
import com.gh.common.util.DataUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.RunningUtils;
import com.gh.common.util.ShareUtils;
import com.gh.common.util.StringUtils;
import com.gh.common.util.TeaHelper;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.LoginActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.SuggestionActivity;
import com.gh.gamecenter.eventbus.EBShowDialog;
import com.gh.gamecenter.suggest.SuggestType;
import com.lightgame.BaseAppCompatActivity;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.Utils;
@ -39,6 +33,8 @@ import org.json.JSONObject;
import java.lang.ref.WeakReference;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import butterknife.ButterKnife;
import pub.devrel.easypermissions.EasyPermissions;
@ -47,14 +43,13 @@ import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
/**
* 只提供基础的服务(EventBus/ButterKnife/Share/GlobalDialog/Permissions)
* <p>
* 需要通道工具栏的页面请继承{@link ToolBarActivity}
* 需要工具栏的页面请继承{@link ToolBarActivity}
*/
public abstract class BaseActivity extends BaseAppCompatActivity implements EasyPermissions.PermissionCallbacks {
// global dialog key
public final static String DOWNLOAD_HIJACK = "hijack";
public final static String DOWNLOAD_NOT_FOUND = "notfound";
public final static String LOGIN_EXCEPTION = "loginException";
public final static String PLUGGABLE = "plugin";
@ -138,9 +133,9 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
shareSummary,
shareType);
if (shareType == ShareUtils.ShareType.game || shareType == ShareUtils.ShareType.plugin) {
DataUtils.onEvent(this, "内容分享", shareTitle + shareSummary);
MtaHelper.onEvent("内容分享", shareTitle + shareSummary);
} else {
DataUtils.onEvent(this, "内容分享", shareTitle);
MtaHelper.onEvent("内容分享", shareTitle);
}
}
@ -149,7 +144,7 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)
&& this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
if (DOWNLOAD_HIJACK.equals(showDialog.getType())) {
DialogUtils.showQqSessionDialog(this, "2586716223");// 建议用户联系客服
DialogUtils.showQqSessionDialog(this);// 建议用户联系客服
} else if (PLUGGABLE.equals(showDialog.getType())) {
DialogUtils.showPluginDialog(this, () -> {
if (FileUtils.isEmptyFile(showDialog.getPath())) {
@ -176,25 +171,17 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
} catch (Exception e) {
e.printStackTrace();
}
} else if (DOWNLOAD_NOT_FOUND.equals(showDialog.getType())) {
DialogUtils.showAlertDialog(this, "下载失败", "下载链接已失效,建议提交反馈"
, "立即反馈", "取消"
, () -> SuggestionActivity.startSuggestionActivity(this,
SuggestType.gameQuestion, null,
(showDialog.getPath() + ",问题反馈:下载链接失效")), null);
}
}
}
@Override
protected void onPause() {
TeaHelper.onPause(this);
super.onPause();
}
@Override
protected void onResume() {
TeaHelper.onResume(this);
super.onResume();
}

View File

@ -11,6 +11,7 @@ import android.view.View
import android.webkit.JavascriptInterface
import butterknife.OnClick
import com.gh.common.util.DialogUtils
import com.gh.common.util.MtaHelper
import com.gh.common.view.RichEditor
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.GameEntity
@ -68,7 +69,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
val game = data?.getParcelableExtra<GameEntity>(GameEntity::class.java.simpleName)
if (game != null) insertData = EditorInsertEntity.transform(game)
}
INSERT_VIDEO_CODE -> {
VideoActivity.INSERT_VIDEO_CODE -> {
val video = data?.getParcelableExtra<MyVideoEntity>(MyVideoEntity::class.java.simpleName)
if (video != null) mRichEditor.insertCustomVideo(video)
return
@ -126,19 +127,30 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
R.id.editor_font_bold -> {
mEditorFontBold.isChecked = !mEditorFontBold.isChecked
mRichEditor.setBold()
if (mEditorFontBold.isChecked) {
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-加粗")
}
}
R.id.editor_font_italic -> {
mEditorFontItalic.isChecked = !mEditorFontItalic.isChecked
mRichEditor.setItalic()
if (mEditorFontItalic.isChecked) {
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-斜体")
}
}
R.id.editor_font_strikethrough -> {
mEditorFontStrikeThrough.isChecked = !mEditorFontStrikeThrough.isChecked
mRichEditor.setStrikeThrough()
if (mEditorFontStrikeThrough.isChecked) {
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-删除线")
}
}
R.id.editor_paragraph_h1 -> {
if (mEditorParagraphH1.isChecked) {
mRichEditor.formatBlock()
} else {
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-1级标题")
mRichEditor.setHeading(1)
}
mEditorParagraphH1.isChecked = !mEditorParagraphH1.isChecked
@ -147,6 +159,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
if (mEditorParagraphH2.isChecked) {
mRichEditor.formatBlock()
} else {
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-2级标题")
mRichEditor.setHeading(2)
}
mEditorParagraphH2.isChecked = !mEditorParagraphH2.isChecked
@ -155,6 +168,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
if (mEditorParagraphH3.isChecked) {
mRichEditor.formatBlock()
} else {
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-3级标题")
mRichEditor.setHeading(3)
}
mEditorParagraphH3.isChecked = !mEditorParagraphH3.isChecked
@ -163,6 +177,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
if (mEditorParagraphH4.isChecked) {
mRichEditor.formatBlock()
} else {
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-4级标题")
mRichEditor.setHeading(4)
}
mEditorParagraphH4.isChecked = !mEditorParagraphH4.isChecked
@ -171,21 +186,26 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
if (mEditorParagraphQuote.isChecked) {
mRichEditor.formatBlock()
} else {
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-引用")
mRichEditor.setBlockquote()
}
mEditorParagraphQuote.isChecked = !mEditorParagraphQuote.isChecked
}
R.id.editor_link_answer -> {
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-回答")
startActivityForResult(InsertAnswerWrapperActivity.getIntent(this), INSERT_ANSWER_CODE)
}
R.id.editor_link_article -> {
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-文章")
startActivityForResult(InsertArticleWrapperActivity.getIntent(this), INSERT_ARTICLE_CODE)
}
R.id.editor_link_game -> {
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-游戏")
startActivityForResult(GameActivity.getIntent(this, "插入游戏"), INSERT_GAME_CODE)
}
R.id.editor_link_video -> {
startActivityForResult(VideoActivity.getIntent(this), INSERT_VIDEO_CODE)
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-视频")
startActivityForResult(VideoActivity.getIntent(this), VideoActivity.INSERT_VIDEO_CODE)
}
}
}
@ -231,6 +251,8 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
}
}
abstract fun mtaEventName(): String
companion object {
const val ELEMENT_NAME_BOLD = " b "
const val ELEMENT_NAME_ITALIC = " i "
@ -244,6 +266,5 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
const val INSERT_ANSWER_CODE = 411
const val INSERT_ARTICLE_CODE = 412
const val INSERT_GAME_CODE = 413
const val INSERT_VIDEO_CODE = 414
}
}

View File

@ -140,8 +140,9 @@ class GHUmengNotificationService : UmengMessageService() {
notificationManager.notify(getNotificationTag(context), NOTIFICATION_ID, notification)
} else {
if (UserManager.getInstance().isLoggedIn
&& HALO_MESSAGE_DIALOG == pushData.body?.custom) {
if (UserManager.getInstance().isLoggedIn &&
HALO_MESSAGE_DIALOG == pushData.body?.custom &&
MessageUnreadRepository.unreadLiveData.value != null) {
// 回答了问题或者关注了问题的消息
val msg = gson.fromJson(message, PushMessageEntity::class.java)
val data = msg?.extra?.data

View File

@ -5,6 +5,7 @@ import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@ -193,10 +194,20 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
private void updateDownloadCountHint(List<GameUpdateEntity> updateList) {
if (mDownloadCountHint == null) return;
int count = DownloadManager.getInstance(getApplicationContext()).getDownloadOrUpdateCount(updateList);
if (count != 0) {
String count = DownloadManager.getInstance(getApplicationContext()).getDownloadOrUpdateCount(updateList);
if (count != null) {
mDownloadCountHint.setVisibility(View.VISIBLE);
mDownloadCountHint.setText(String.valueOf(count));
mDownloadCountHint.setText(count);
ViewGroup.LayoutParams params = mDownloadCountHint.getLayoutParams();
if (TextUtils.isEmpty(count)) {
params.width = DisplayUtils.dip2px(6);
params.height = DisplayUtils.dip2px(6);
} else {
params.width = DisplayUtils.dip2px(12);
params.height = DisplayUtils.dip2px(12);
}
mDownloadCountHint.setLayoutParams(params);
} else {
mDownloadCountHint.setVisibility(View.GONE);
}

View File

@ -9,14 +9,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.Lifecycle;
import com.gh.base.OnListClickListener;
import com.gh.base.OnRequestCallBackListener;
import com.gh.common.constant.Constants;
@ -33,6 +25,12 @@ import org.greenrobot.eventbus.ThreadMode;
import java.lang.ref.WeakReference;
import java.util.List;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import butterknife.ButterKnife;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@ -185,7 +183,11 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
}
public void toast(String msg) {
Utils.toast(getContext(), msg);
try {
Utils.toast(getContext(), msg);
} catch (Exception ignore) {
}
}
public void toastLong(@StringRes int msg) {

View File

@ -14,16 +14,16 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Checkable;
import com.gh.gamecenter.fragment.MainWrapperFragment;
import java.util.List;
import androidx.annotation.IdRes;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.viewpager.widget.ViewPager;
import com.gh.gamecenter.fragment.MainWrapperFragment;
import java.util.List;
/**
* ViewPager 配合ViewGroup Checkable实现双切换<br/>
@ -78,7 +78,18 @@ public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_View
public void onPageSelected(int index) {
onPageChanged(index);
try {
// 补充Viewpager Fragment的生命周期
// 补充Viewpager Fragment的生命周期 先调用旧选中 fragment 的 onPause 再当前的 onResume
if (mFragmentsList.size() > mLastPosition) {
Fragment fragment = mFragmentsList.get(mLastPosition);
fragment.onPause();
FragmentManager childFragmentManager = fragment.getChildFragmentManager();
List<Fragment> fragments = childFragmentManager.getFragments();
for (Fragment childFragment : fragments) {
childFragment.onPause();
}
}
if (mFragmentsList.size() > index) {
Fragment fragment = mFragmentsList.get(index);
fragment.onResume();
@ -89,17 +100,6 @@ public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_View
childFragment.onResume();
}
}
if (mFragmentsList.size() > mLastPosition) {
Fragment fragment = mFragmentsList.get(mLastPosition);
fragment.onPause();
FragmentManager childFragmentManager = fragment.getChildFragmentManager();
List<Fragment> fragments = childFragmentManager.getFragments();
for (Fragment childFragment : fragments) {
childFragment.onPause();
}
}
mLastPosition = index;
} catch (Exception ignore) {

View File

@ -0,0 +1,163 @@
package com.gh.base.fragment
import android.os.Bundle
import com.gh.gamecenter.normal.NormalFragment
/**
* 懒加载(支持多层嵌套)
*/
abstract class BaseLazyFragment : NormalFragment() {
private var mIsFirstVisible = true
private var isViewCreated = false
private var isSupportVisible = false
/**
* 用于分发可见时间的时候父获取 fragment 是否隐藏
*
* @return true fragment 不可见, false 父 fragment 可见
*/
private val isParentInvisible: Boolean
get() {
val parentFragment = parentFragment
return if (parentFragment is BaseLazyFragment) {
val fragment = parentFragment as BaseLazyFragment?
!fragment!!.isSupportVisible
} else {
false
}
}
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
// 对于默认 tab 和 间隔 checked tab 需要等到 isViewCreated = true 后才可以通过此通知用户可见
// 这种情况下第一次可见不是在这里通知 因为 isViewCreated = false 成立,等从别的界面回到这里后会使用 onFragmentResume 通知可见
// 对于非默认 tab mIsFirstVisible = true 会一直保持到选择则这个 tab 的时候,因为在 onActivityCreated 会返回 false
if (isViewCreated) {
if (isVisibleToUser && !isSupportVisible) {
dispatchUserVisibleHint(true)
} else if (!isVisibleToUser && isSupportVisible) {
dispatchUserVisibleHint(false)
}
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
isViewCreated = true
// !isHidden() 默认为 true 在调用 hide show 的时候可以使用
if (!isHidden && userVisibleHint) {
dispatchUserVisibleHint(true)
}
}
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (hidden) {
dispatchUserVisibleHint(false)
} else {
dispatchUserVisibleHint(true)
}
}
override fun onResume() {
super.onResume()
if (!mIsFirstVisible) {
if (!isHidden && !isSupportVisible && userVisibleHint) {
dispatchUserVisibleHint(true)
}
}
}
override fun onPause() {
super.onPause()
// 当前 Fragment 包含子 Fragment 的时候 dispatchUserVisibleHint 内部本身就会通知子 Fragment 不可见
// 子 fragment 走到这里的时候自身又会调用一遍
if (isSupportVisible && userVisibleHint) {
dispatchUserVisibleHint(false)
}
}
/**
* 统一处理 显示隐藏
*
* @param visible
*/
private fun dispatchUserVisibleHint(visible: Boolean) {
//当前 Fragment 是 child 时候 作为缓存 Fragment 的子 fragment getUserVisibleHint = true
//但当父 fragment 不可见所以 currentVisibleState = false 直接 return 掉
// 这里限制则可以限制多层嵌套的时候子 Fragment 的分发
if (visible && isParentInvisible) return
//此处是对子 Fragment 不可见的限制,因为 子 Fragment 先于父 Fragment回调本方法 currentVisibleState 置位 false
// 当父 dispatchChildVisibleState 的时候第二次回调本方法 visible = false 所以此处 visible 将直接返回
if (isSupportVisible == visible) {
return
}
isSupportVisible = visible
if (visible) {
if (mIsFirstVisible) {
mIsFirstVisible = false
onFragmentFirstVisible()
}
onFragmentResume()
dispatchChildVisibleState(true)
} else {
dispatchChildVisibleState(false)
onFragmentPause()
}
}
/**
* 当前 Fragment 是 child 时候 作为缓存 Fragment 的子 fragment 的唯一或者嵌套 VP 的第一 fragment 时 getUserVisibleHint = true
* 但是由于父 Fragment 还未进入可见状态所以自身也是不可见的, 这个方法可以存在是因为庆幸的是 父 fragment 的生命周期回调总是先于子 Fragment
* 所以在父 fragment 设置完成当前不可见状态后,需要通知子 Fragment 我不可见,你也不可见,
*
*
* 因为 dispatchUserVisibleHint 中判断了 isParentInvisible 所以当 子 fragment 走到了 onActivityCreated 的时候直接 return 掉了
*
*
* 当真正的外部 Fragment 可见的时候,走 setVisibleHint (VP 中)或者 onActivityCreated (hide show) 的时候
* 从对应的生命周期入口调用 dispatchChildVisibleState 通知子 Fragment 可见状态
*
* @param visible
*/
private fun dispatchChildVisibleState(visible: Boolean) {
val childFragmentManager = childFragmentManager
val fragments = childFragmentManager.fragments
if (!fragments.isEmpty()) {
for (child in fragments) {
if (child is BaseLazyFragment && !child.isHidden() && child.getUserVisibleHint()) {
child.dispatchUserVisibleHint(visible)
}
}
}
}
open fun onFragmentFirstVisible() {
//ULog.e("对用户第一次可见")
}
open fun onFragmentResume() {
//ULog.e("对用户可见")
}
open fun onFragmentPause() {
//ULog.e("对用户不可见")
}
override fun onDestroyView() {
super.onDestroyView()
isViewCreated = false
mIsFirstVisible = true
}
}

View File

@ -49,7 +49,7 @@ class DefaultJsApi(var context: Context) {
@JavascriptInterface
fun getUserToken(msg: Any): String {
return UserManager.getInstance().loginTokenEntity.accessToken.value
return if (UserManager.getInstance().isLoggedIn) UserManager.getInstance().loginTokenEntity.accessToken.value else ""
}
@JavascriptInterface

View File

@ -4,6 +4,7 @@ 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 com.gh.common.util.EntranceUtils
@ -12,7 +13,9 @@ import com.gh.gamecenter.LibaoDetailActivity
import com.gh.gamecenter.NewsDetailActivity
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.entity.CommunityEntity
import com.gh.gamecenter.entity.VideoLinkEntity
import com.gh.gamecenter.subject.SubjectActivity
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
object DefaultWebViewUrlHandler {
@ -107,10 +110,24 @@ object DefaultWebViewUrlHandler {
entrance, "文章链接")
}
}
EntranceUtils.HOST_UPLOAD_VIDEO -> {
val titleParameter = uri.getQueryParameter("title")
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)
}
CheckLoginUtils.checkLogin(context, EntranceUtils.ENTRANCE_BROWSER) {
DirectUtils.directToVideoManager(context, linkEntity, EntranceUtils.ENTRANCE_BROWSER, "")
}
}
else -> DialogUtils.showLowVersionDialog(context)
}
return true
}
if ("http" != uri.scheme && "https" != uri.scheme) return true
return false
}
}

View File

@ -9,15 +9,25 @@ import androidx.annotation.Nullable;
import com.gh.common.util.GsonUtils;
import com.gh.common.util.PackageHelper;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.SPUtils;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.SuggestionActivity;
import com.gh.gamecenter.entity.NewsEntity;
import com.gh.gamecenter.entity.SettingsEntity;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.Utils;
import org.greenrobot.eventbus.EventBus;
import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class Config {
public static final String API_HOST = BuildConfig.API_HOST;
@ -169,6 +179,9 @@ public class Config {
getPreferences().edit().putString(SETTINGS_KEY, GsonUtils.toJson(settingsEntity)).apply();
mSettingsEntity = settingsEntity;
// 更新 FIX_ARTICLE_KEY 状态
mSettingsEntity.showArticleEntrance();
// 加载完设置后刷新下
PackageHelper.initList();
}
@ -232,4 +245,29 @@ public class Config {
editor.putBoolean(Config.FIX_PLUGIN_KEY, true);
editor.apply();
}
public static void getGhzsSettings() {
String channel = HaloApp.getInstance().getChannel();
RetrofitManager.getInstance(HaloApp.getInstance().getApplication())
.getApi().getSettings(PackageUtils.getVersionName(), channel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<SettingsEntity>() {
@Override
public void onResponse(SettingsEntity response) {
Config.setSettings(response);
// 意见反馈
SharedPreferences.Editor edit = getPreferences().edit();
edit.putString(SuggestionActivity.SUGGESTION_HINT_TYPE,
GsonUtils.toJson(response.getSuggestion()));
edit.apply();
if (!getPreferences().getBoolean(Config.FIX_DOWNLOAD_KEY, false) && Config.isShow()) {
getPreferences().edit().putBoolean(Config.FIX_DOWNLOAD_KEY, true).apply();
}
EventBus.getDefault().post(new EBReuse("Refresh"));
}
});
}
}

View File

@ -1,5 +1,7 @@
package com.gh.common.constant;
import com.gh.common.util.PackageUtils;
public class Constants {
public static final int SEND_NEWS_FEEDBACK = 0x126;
@ -24,16 +26,30 @@ public class Constants {
public static final String GAME_DETAIL_COME_IN = "game_detail_come_in"; // 从游戏详情进入
public static final String XPOSED_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
public static final String EB_QUIT_LOGIN = "quit_login";
// 最近显示的弹窗信息
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 SP_SHOWED_NOTIFICATION_HINT = "show_notification_hint";
//标记安装的游戏为已玩过弹窗最多取消2次
public static final String SP_MARK_INSTALLED_GAME = "mark_installed_game";
//引导设置 “通知管理” 引导弹窗
public static final String SP_SHOWED_NOTIFICATION_LOGIN = "show_notification_login_hint";
public static final String SP_SHOWED_NOTIFICATION_QUESTION = "show_notification_question_hint";
public static final String SP_SHOWED_NOTIFICATION_ANSWER = "show_notification_answer_hint";
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_NEW_VERSION = "show_notification_new_version";
// 今天是否已经触发了 “通知管理” 引导弹窗
public static final String SP_IS_SHOWED_NOTIFICATION_TODAY = "show_is_notification_today";
// 标记安装的游戏为已玩过弹窗最多取消2次 (https://gitlab.ghzs.com/pm/halo-app-issues/issues/722 调整为版本相关) (不是常量了也放这里好像有点奇怪)
public static final String SP_MARK_INSTALLED_GAME = "mark_installed_game" + PackageUtils.getVersionName();
//视频详情滑动引导
public static final String SP_SHOW_SLIDE_GUIDE = "show_slide_guide";
//视频详情点击引导
public static final String SP_SHOW_CLICK_GUIDE = "show_click_guide";
//手机号码匹配规则
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
@ -66,10 +82,15 @@ public class Constants {
public static final int SEARCH_CD = 5 * 60 * 1000;
//评论 cd间隔
public static final int COMMENT_CD = 60 * 1000;
//我的光环功能分组 cd间隔
public static final int ADDONS_CD = 10 * 60 * 1000;
public static final String[] REPORT_LIST = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息", "违法有害信息", "其它"};
public static final String ENTRANCE_UNKNOWN = "(unknown)";
public static final String DEFAULT_TEXT_WRAPPER = "###";
// 触发了安装事件的标记
public static final String MARK_ALREADY_TRIGGERED_INSTALLATION = "triggered_installation";
}

View File

@ -13,12 +13,6 @@ import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.databinding.BindingAdapter;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.base.OnViewClickListener;
import com.gh.common.constant.Config;
@ -34,6 +28,8 @@ import com.gh.common.util.DownloadDialogHelper;
import com.gh.common.util.GameUtils;
import com.gh.common.util.GameViewUtils;
import com.gh.common.util.ImageUtils;
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.PackageUtils;
@ -46,11 +42,13 @@ import com.gh.common.view.DrawableView;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WebActivity;
import com.gh.gamecenter.baselist.LoadStatus;
import com.gh.gamecenter.databinding.KaifuAddItemBinding;
import com.gh.gamecenter.databinding.KaifuDetailItemRowBinding;
import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.LinkEntity;
import com.gh.gamecenter.entity.PluginLocation;
import com.gh.gamecenter.entity.ServerCalendarEntity;
import com.gh.gamecenter.entity.TagStyleEntity;
@ -67,6 +65,12 @@ import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.databinding.BindingAdapter;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
/**
* Created by khy on 12/02/18.
*/
@ -381,16 +385,17 @@ 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.getPath());
PackageUtils.launchSetup(v.getContext(), downloadEntity);
}
}
break;
case RESERVABLE:
CheckLoginUtils.checkLogin(progressBar.getContext(), "", () -> {
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(progressBar.getContext(), () -> {
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
gameEntity,
() -> updateReservation(progressBar, gameEntity));
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(gameEntity, () -> {
LogUtils.logReservation(gameEntity, traceEvent);
updateReservation(progressBar, gameEntity);
});
dialogFragment.show(((AppCompatActivity) progressBar.getContext()).getSupportFragmentManager(), "reserve");
});
});
@ -410,6 +415,12 @@ public class BindingAdapters {
});
}
break;
case H5_GAME:
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.getName());
LinkEntity linkEntity = gameEntity.getH5Link();
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), "play".equals(linkEntity.getType())));
progressBar.getContext().startActivity(i);
break;
}
});
@ -427,13 +438,24 @@ public class BindingAdapters {
// 显示下载按钮状态
if (gameEntity.getApk().isEmpty() || gameEntity.getDownloadOffStatus() != null) {
LinkEntity h5LinkEntity = gameEntity.getH5Link();
String offStatus = gameEntity.getDownloadOffStatus();
if (offStatus != null && "dialog".equals(offStatus)) {
progressBar.setText("查看");
if (h5LinkEntity != null) {
if ("play".equals(h5LinkEntity.getType())) {
progressBar.setText("开始玩");
} else {
progressBar.setText("查看");
}
progressBar.setDownloadType(DownloadProgressBar.DownloadType.H5_GAME);
} else {
progressBar.setText("暂无");
if (offStatus != null && "dialog".equals(offStatus)) {
progressBar.setText("查看");
} else {
progressBar.setText("暂无");
}
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
}
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
} else {
String status = GameUtils.getDownloadBtnText(progressBar.getContext(), gameEntity, PluginLocation.only_game);
switch (status) {
@ -524,9 +546,10 @@ public class BindingAdapters {
String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity.getSize());
if (TextUtils.isEmpty(msg)) {
DataUtils.onGameDownloadEvent(progressBar.getContext(), gameEntity.getName(), apkEntity.getPlatform(), entrance, "下载开始", method);
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, ExposureUtils.DownloadType.DOWNLOAD);
ExposureUtils.DownloadType downloadType = ExposureUtils.getDownloadType(apkEntity, method);
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, downloadType);
DownloadManager.createDownload(progressBar.getContext(),
apkEntity,
gameEntity,

View File

@ -1,9 +1,9 @@
package com.gh.common.exposure
import androidx.room.Entity
import androidx.room.PrimaryKey
import android.os.Parcelable
import androidx.annotation.Keep
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.gh.common.exposure.meta.Meta
import com.gh.common.exposure.meta.MetaUtil
import com.gh.common.exposure.time.TimeUtil
@ -24,7 +24,8 @@ data class ExposureEvent(
@PrimaryKey
val id: String = UUID.randomUUID().toString()) : Parcelable {
companion object {
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>?, event: ExposureType): ExposureEvent {
@JvmStatic
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>? = null, event: ExposureType = ExposureType.EXPOSURE): ExposureEvent {
return ExposureEvent(
payload = ExposureEntity(gameId = gameEntity?.id,
gameName = gameEntity?.name,
@ -34,7 +35,7 @@ data class ExposureEvent(
downloadCompleteType = gameEntity?.downloadCompleteType),
source = source,
eTrace = eTrace,
event = event)
event = event).apply { gameEntity?.exposureEvent = this }
}
}
}

View File

@ -31,10 +31,10 @@ object ExposureManager {
private val loghubHelper = LoghubHelper.getInstance()
// exposureCache 用来过滤掉具有相同 id 的曝光事件,避免重复发送事件
private val exposureCache = FixedSizeLinkedHashSet<String>(100)
private val exposureSet = hashSetOf<ExposureEvent>()
private val exposureDao by lazy { ExposureDatabase.buildDatabase(HaloApp.getInstance().application).logHubEventDao() }
private val exposureExecutor = Executors.newSingleThreadExecutor()
private val exposureCache = FixedSizeLinkedHashSet<String>(300)
private val exposureDao by lazy { ExposureDatabase.buildDatabase(HaloApp.getInstance().application).logHubEventDao() }
@JvmStatic
fun init() {
@ -48,7 +48,7 @@ object ExposureManager {
}
fixedRateTimer(name = "ExposureManager-Store-Checker", initialDelay = 500, period = STORE_FORCE_UPLOAD_PERIOD) {
commitSavedExposureEvent(true)
commitSavedExposureEvents(true)
}
}
@ -57,17 +57,19 @@ object ExposureManager {
*/
fun log(event: ExposureEvent) {
exposureExecutor.execute {
if (!exposureCache.contains(event.id)) {
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
try {
try {
if (!exposureCache.contains(event.id)) {
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
exposureSet.add(event)
exposureDao.insert(event)
exposureCache.add(event.id)
} catch (e: Exception) {
e.printStackTrace()
} else {
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 ${event.id} - ${event.payload.gameName}")
}
} else {
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 ${event.id} - ${event.payload.gameName}")
} catch (e: Exception) {
e.printStackTrace()
}
}
}
@ -78,24 +80,27 @@ object ExposureManager {
fun log(eventList: List<ExposureEvent>) {
exposureExecutor.execute {
for (event in eventList) {
if (!exposureCache.contains(event.id)) {
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
try {
try {
if (!exposureCache.contains(event.id)) {
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
exposureSet.add(event)
exposureDao.insert(event)
exposureCache.add(event.id)
} catch (e: Exception) {
e.printStackTrace()
} else {
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 ${event.id} - ${event.payload.gameName}")
}
} else {
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 ${event.id} - ${event.payload.gameName}")
} catch (e: Exception) {
e.printStackTrace()
}
}
commitSavedExposureEvent()
commitSavedExposureEvents()
}
}
fun commitSavedExposureEvent(forced: Boolean = false) {
/**
* @param forced Ignore all restrictions.
*/
fun commitSavedExposureEvents(forced: Boolean = false) {
exposureExecutor.execute {
if (exposureSet.size < STORE_SIZE && !forced || exposureSet.size == 0) return@execute

View File

@ -6,4 +6,4 @@ import kotlinx.android.parcel.Parcelize
@Keep
@Parcelize
data class ExposureSource(var k: String, var v: String): Parcelable
data class ExposureSource(var k: String, var v: String = ""): Parcelable

View File

@ -1,7 +1,10 @@
package com.gh.common.exposure
import com.gh.common.util.PackageUtils
import com.gh.common.util.toObject
import com.gh.gamecenter.entity.ApkEntity
import com.gh.gamecenter.entity.GameEntity
import com.halo.assistant.HaloApp
import java.util.*
object ExposureUtils {
@ -36,7 +39,31 @@ object ExposureUtils {
eTrace = ExposureTraceUtils.appendTrace(traceEvent),
event = ExposureType.DOWNLOAD_COMPLETE)
ExposureManager.log(exposureEvent)
ExposureManager.commitSavedExposureEvent(forced = true)
ExposureManager.commitSavedExposureEvents(forced = true)
}
@JvmStatic
fun getDownloadType(apkEntity: ApkEntity, method: String) : DownloadType {
return if ("更新" == method) {
if (PackageUtils.isSignature(HaloApp.getInstance().application, apkEntity.packageName)) {
DownloadType.PLUGIN_UPDATE
} else {
DownloadType.UPDATE
}
} else if ("插件化" == method) {
DownloadType.PLUGIN_DOWNLOAD
} else {
DownloadType.DOWNLOAD
}
}
@JvmStatic
fun getUpdateType(apkEntity: ApkEntity) : DownloadType {
return if (PackageUtils.isSignature(HaloApp.getInstance().application, apkEntity.packageName)) {
DownloadType.PLUGIN_UPDATE
} else {
DownloadType.UPDATE
}
}
enum class DownloadType {

View File

@ -17,6 +17,7 @@ data class Meta(
val network: String? = "",
val os: String? = "",
val gid: String? = "",
val oaid: String? = "",
val channel: String? = "",
val appVersion: String? = "",
val userId: String? = "",

View File

@ -35,6 +35,7 @@ object MetaUtil {
network = getNetwork(),
os = getOS(),
gid = HaloApp.getInstance().gid,
oaid = HaloApp.getInstance().oaid,
channel = getChannel(),
appVersion = BuildConfig.VERSION_NAME,
userId = UserManager.getInstance().userId,

View File

@ -7,17 +7,15 @@ import androidx.room.TypeConverters
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.gh.gamecenter.entity.HistoryGameEntity
import com.gh.gamecenter.entity.MyVideoEntity
import com.gh.gamecenter.entity.NewsEntity
import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.qa.entity.ArticleEntity
import com.gh.gamecenter.room.converter.*
import com.gh.gamecenter.room.dao.AnswerHistoryDao
import com.gh.gamecenter.room.dao.ArticleHistoryDao
import com.gh.gamecenter.room.dao.GameDao
import com.gh.gamecenter.room.dao.NewsHistoryDao
import com.gh.gamecenter.room.dao.*
import com.halo.assistant.HaloApp
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class], version = 4, exportSchema = false)
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 5, exportSchema = false)
@TypeConverters(CountConverter::class,
CommunityConverter::class,
TimeConverter::class,
@ -33,6 +31,7 @@ abstract class HistoryDatabase : RoomDatabase() {
abstract fun articleDao(): ArticleHistoryDao
abstract fun newsDao(): NewsHistoryDao
abstract fun gameDao(): GameDao
abstract fun videoHistoryDao(): VideoHistoryDao
companion object {
@ -49,10 +48,17 @@ abstract class HistoryDatabase : RoomDatabase() {
}
}
val MIGRATION_4_5: Migration = object : Migration(4, 5) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE MyVideoEntity(id TEXT NOT NULL PRIMARY KEY,poster TEXT NOT NULL DEFAULT '',url TEXT NOT NULL DEFAULT '',vote INTEGER NOT NULL DEFAULT 0,length INTEGER NOT NULL DEFAULT 0,time INTEGER NOT NULL DEFAULT 0,videoStreamRecord INTEGER NOT NULL DEFAULT 0,status TEXT NOT NULL 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)
.build()
}
}

View File

@ -2,16 +2,12 @@ package com.gh.common.im
import android.app.Activity
import android.content.Context
import android.os.Build
import androidx.core.view.ViewCompat
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.util.TypedValue
import android.view.KeyCharacterMap
import android.view.KeyEvent
import android.view.View
import android.view.ViewConfiguration
import android.widget.RelativeLayout
import androidx.core.view.ViewCompat
import com.gh.common.util.DisplayUtils
import com.gh.gamecenter.R
import kotlinx.android.synthetic.main.view_im_hint.view.*
@ -32,7 +28,7 @@ class ImHintView @JvmOverloads constructor(context: Context, attrs: AttributeSet
val lp = ivContainer.layoutParams as RelativeLayout.LayoutParams
lp.setMargins(0, 0, dp2px(30f), dp2px(106f) + retrieveNavigationHeight())
lp.setMargins(0, 0, dp2px(30f), dp2px(106f) + DisplayUtils.retrieveNavigationHeight(context))
}
fun showDot(show: Boolean) {
@ -46,39 +42,4 @@ class ImHintView @JvmOverloads constructor(context: Context, attrs: AttributeSet
private fun dp2px(dp: Float): Int {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.applicationContext.resources.displayMetrics).toInt()
}
private fun hasSoftKeys(): Boolean {
if (context !is Activity) return false
val hasSoftwareKeys: Boolean
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
val d = (context as Activity).windowManager.defaultDisplay
val realDisplayMetrics = DisplayMetrics()
d.getRealMetrics(realDisplayMetrics)
val realHeight = realDisplayMetrics.heightPixels
val realWidth = realDisplayMetrics.widthPixels
val displayMetrics = DisplayMetrics()
d.getMetrics(displayMetrics)
val displayHeight = displayMetrics.heightPixels
val displayWidth = displayMetrics.widthPixels
hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0
} else {
val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey()
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
hasSoftwareKeys = !hasMenuKey && !hasBackKey
}
return hasSoftwareKeys
}
private fun retrieveNavigationHeight(): Int {
val resources = context.resources
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
return if (resourceId > 0 && hasSoftKeys()) resources.getDimensionPixelSize(resourceId) else 0
}
}

View File

@ -7,9 +7,9 @@ import com.gh.base.CurrentActivityHolder
import com.gh.common.util.SPUtils
import com.gh.common.util.tryWithDefaultCatch
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.HelpAndFeedbackActivity
import com.gh.gamecenter.MainActivity
import com.gh.gamecenter.MessageActivity
import com.gh.gamecenter.SuggestSelectActivity
import com.gh.gamecenter.manager.UserManager
import com.halo.assistant.HaloApp
import com.m7.imkfsdk.KfStartHelper
@ -69,12 +69,12 @@ object ImManager {
}
@JvmStatic
fun startChatActivity(activity: Activity) {
fun startChatActivity(activity: Activity, inputContent: String? = "", requestCode: Int? = null) {
if (!UserManager.getInstance().userId.isNullOrEmpty()) {
try {
SPUtils.setBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId, false)
shouldShowFloatingWindowDot = false
val chatHelper = KfStartHelper(activity, UserManager.getInstance().userInfoEntity.icon)
val chatHelper = KfStartHelper(activity, UserManager.getInstance().userInfoEntity.icon, inputContent, requestCode)
chatHelper.initSdkChat(
ImReceiver.UNIQUE_BROADCAST_ACTION,
IM_KEY,
@ -152,7 +152,7 @@ object ImManager {
private fun isActivityValid(activity: Activity): Boolean {
return when (activity) {
is MainActivity -> true
is SuggestSelectActivity -> true
is HelpAndFeedbackActivity -> true
is MessageActivity -> true
else -> false
}

View File

@ -0,0 +1,21 @@
package com.gh.common.loghub
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(entities = [LoghubEvent::class], version = 1, exportSchema = false)
abstract class LoghubDatabase : RoomDatabase() {
companion object {
private const val DATABASE = "gh_loghub_database"
fun buildDatabase(context: Context): LoghubDatabase {
return Room.databaseBuilder(context, LoghubDatabase::class.java, DATABASE)
.fallbackToDestructiveMigration()
.build()
}
}
abstract fun logHubEventDao(): LoghubEventDao
}

View File

@ -0,0 +1,17 @@
package com.gh.common.loghub
import android.os.Parcelable
import androidx.annotation.Keep
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.android.parcel.Parcelize
import java.util.*
@Keep
@Parcelize
@Entity(tableName = "loghubEvent")
data class LoghubEvent(@PrimaryKey
val id: String = UUID.randomUUID().toString(),
var time: String,
var content: String,
var logStore: String) : Parcelable

View File

@ -0,0 +1,18 @@
package com.gh.common.loghub
import androidx.room.*
@Dao
interface LoghubEventDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertMany(eventList: List<LoghubEvent>)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(event: LoghubEvent)
@Query("SELECT * FROM LoghubEvent")
fun getAll(): List<LoghubEvent>
@Delete
fun deleteMany(eventList: List<LoghubEvent>)
}

View File

@ -0,0 +1,88 @@
package com.gh.common.loghub
import android.app.Application
import com.aliyun.sls.android.sdk.model.Log
import com.aliyun.sls.android.sdk.model.LogGroup
import com.gh.loghub.LoghubHelper
import org.json.JSONObject
import java.util.concurrent.Executors
import kotlin.concurrent.fixedRateTimer
object LoghubUtils {
private const val STORE_SIZE = 100
private const val STORE_FORCE_UPLOAD_INTERVAL = 120 * 1000L
private lateinit var mApplication: Application
private val loghubEventSet = hashSetOf<LoghubEvent>()
private val loghubEventExecutor by lazy { Executors.newSingleThreadExecutor() }
private val loghubEventDao by lazy { LoghubDatabase.buildDatabase(mApplication).logHubEventDao() }
@JvmStatic
fun init(application: Application) {
mApplication = application
loghubEventExecutor.execute {
val eventList = loghubEventDao.getAll()
loghubEventSet.addAll(eventList)
}
fixedRateTimer(name = "Loghub-Event-Checker", initialDelay = 1000, period = STORE_FORCE_UPLOAD_INTERVAL) {
commitSavedLoghubEvents()
}
}
@JvmStatic
fun log(logJson: JSONObject, logStore: String, forcedUpload: Boolean) {
loghubEventExecutor.execute {
try {
val event = LoghubEvent(time = (System.currentTimeMillis() / 1000L).toString(), content = logJson.toString(), 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)
}
private fun commitSavedLoghubEvents() {
loghubEventExecutor.execute {
if (loghubEventSet.isEmpty()) return@execute
val exposureList = loghubEventSet.toList()
createLogGroupAndUpload()
loghubEventSet.removeAll(exposureList)
loghubEventDao.deleteMany(exposureList)
}
}
private fun createLogGroupAndUpload() {
val logGroupHashMap = hashMapOf<String, LogGroup>()
for (event in loghubEventSet) {
if (!logGroupHashMap.containsKey(event.logStore)) {
logGroupHashMap[event.logStore] = LogGroup("sls android", "no ip")
}
val log = Log()
log.PutContent("current time ", event.time)
log.PutContent("content", event.content)
logGroupHashMap[event.logStore]?.PutLog(log)
}
for ((logStore, logGroup) in logGroupHashMap) {
uploadLogGroup(logGroup, logStore)
}
}
}

View File

@ -1,18 +1,19 @@
package com.gh.common.notifier
import android.animation.*
import android.app.Activity
import android.content.Context
import android.graphics.Path
import android.os.Build
import android.text.TextUtils
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.util.Log
import android.util.TypedValue
import android.view.*
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.view.ViewCompat
import com.gh.common.util.DisplayUtils
import com.gh.common.util.ImageUtils
import com.gh.common.util.doOnEnd
import com.gh.common.util.doOnStart
@ -74,7 +75,7 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
verticalAnimationOffset = dp2px(100F)
navigationHeight = retrieveNavigationHeight()
navigationHeight = DisplayUtils.retrieveNavigationHeight(context)
rightToLeftPath = Path()
leftToRightPath = Path()
@ -290,41 +291,6 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.applicationContext.resources.displayMetrics).toInt()
}
private fun hasSoftKeys(): Boolean {
if (context !is Activity) return false
val hasSoftwareKeys: Boolean
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
val d = (context as Activity).windowManager.defaultDisplay
val realDisplayMetrics = DisplayMetrics()
d.getRealMetrics(realDisplayMetrics)
val realHeight = realDisplayMetrics.heightPixels
val realWidth = realDisplayMetrics.widthPixels
val displayMetrics = DisplayMetrics()
d.getMetrics(displayMetrics)
val displayHeight = displayMetrics.heightPixels
val displayWidth = displayMetrics.widthPixels
hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0
} else {
val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey()
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
hasSoftwareKeys = !hasMenuKey && !hasBackKey
}
return hasSoftwareKeys
}
private fun retrieveNavigationHeight(): Int {
val resources = context.resources
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
return if (resourceId > 0 && hasSoftKeys()) resources.getDimensionPixelSize(resourceId) else 0
}
interface OnShowNotificationListener {
fun onShow()
}

View File

@ -1,7 +1,7 @@
package com.gh.common.util;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import com.gh.gamecenter.LoginActivity;
@ -19,8 +19,12 @@ public class CheckLoginUtils {
if (listener != null) Utils.toast(context, "需要登录");
LogUtils.login("dialog", null, entrance);
LogUtils.login("activity", null, entrance);
Intent intent = LoginActivity.getIntent(context, entrance);
context.startActivity(intent);
// 有可能App未启动
Bundle bundle = new Bundle();
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
bundle.putString(EntranceUtils.KEY_TO, LoginActivity.class.getName());
EntranceUtils.jumpActivity(context, bundle);
} else {
if (listener != null) {
listener.onLogin();

View File

@ -9,6 +9,7 @@ import com.gh.common.view.DownloadProgressBar;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.viewholder.DetailViewHolder;
import com.gh.gamecenter.entity.LinkEntity;
import com.gh.gamecenter.entity.PluginLocation;
import com.gh.gamecenter.manager.PackagesManager;
import com.lightgame.download.DownloadEntity;
@ -47,12 +48,24 @@ public class DetailDownloadUtils {
}
if (viewHolder.gameEntity.getApk().isEmpty() || viewHolder.gameEntity.getDownloadOffStatus() != null) {
if ("dialog".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "查看详情" : viewHolder.downloadOffText);
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE_WITH_HINT);
LinkEntity h5LinkEntity = viewHolder.gameEntity.getH5Link();
if (h5LinkEntity != null) {
if ("play".equals(h5LinkEntity.getType())) {
String defaultString = String.format("开始玩" + "《%s》", viewHolder.gameEntity.getName());
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(h5LinkEntity.getText()) ? defaultString : h5LinkEntity.getText());
} else {
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(h5LinkEntity.getText()) ? "查看" : h5LinkEntity.getText());
}
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.H5_GAME);
} else {
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "暂无下载" : viewHolder.downloadOffText);
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE);
if ("dialog".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "查看详情" : viewHolder.downloadOffText);
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE_WITH_HINT);
} else {
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "暂无下载" : viewHolder.downloadOffText);
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE);
}
}
} else {
String status = GameUtils.getDownloadBtnText(viewHolder.context, viewHolder.gameEntity, PluginLocation.only_game);

View File

@ -5,7 +5,10 @@ import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.preference.PreferenceManager;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
@ -17,26 +20,41 @@ import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
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.recyclerview.widget.RecyclerView;
import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.gh.common.AppExecutor;
import com.gh.common.constant.Config;
import com.gh.common.dialog.TrackableDialog;
import com.gh.common.view.DrawableView;
import com.gh.common.view.FixLinearLayoutManager;
import com.gh.gamecenter.AboutActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WebActivity;
import com.gh.gamecenter.adapter.viewholder.PrivacyPolicyItemViewHolder;
import com.gh.gamecenter.databinding.PrivacyItemBinding;
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
import com.gh.gamecenter.entity.TrackableEntity;
import com.halo.assistant.HaloApp;
import com.halo.assistant.fragment.SettingsFragment;
import com.lightgame.adapter.BaseRecyclerAdapter;
import com.lightgame.utils.AppManager;
import com.lightgame.utils.Utils;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
public class DialogUtils {
public static Dialog showWaitDialog(Context context, String msg) {
@ -144,29 +162,33 @@ public class DialogUtils {
}
// 网络劫持时 打开QQ客户端创建临时会话
public static void showQqSessionDialog(final Context context, final String qq) {
public static void showQqSessionDialog(final Context context) {
String qq = "";
if (Config.getSettings() != null && Config.getSettings().getSupport() != null) {
qq = Config.getSettings().getSupport().getQq();
}
String finalQq = qq;
showWarningDialog(context, "警告", "您当前网络环境异常,下载地址可能被运营商恶意替换(网络劫持)" +
"如多次下载失败请联系客服获取正确的下载地址客服QQ" + qq + ""
, "取消", "前往QQ", () -> DirectUtils.directToQqConversation(context, qq), null);
, "取消", "前往QQ", () -> DirectUtils.directToQqConversation(context, finalQq), null);
}
public static void checkDownload(Context context, String size, CheckDownloadCallBack callBack) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
if (!NetworkUtils.isNetworkConnected(context)) {
showNoConnectionDownloadDialog(context, null,
() -> callBack.onResponse(true));
} else if (NetworkUtils.isWifiConnected(context) || filter4GorSize(context, size)) {
} else if (NetworkUtils.isWifiConnected(context)
|| filter4GorSize(context, size)) {
callBack.onResponse(false);
} else if (!preferences.getBoolean(SettingsFragment.getTrafficDownloadHintKey(), true)) {
AppExecutor.getUiExecutor().executeWithDelay(() -> Utils.toast(context, "当前使用移动网络下载,请注意流量消耗"), 500);
callBack.onResponse(false);
} else {
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "出现弹窗提示");
showDownloadDialog(context,
() -> {
callBack.onResponse(false);
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "立即下载");
},
() -> {
callBack.onResponse(true);
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "连上WiFi后自动下载");
});
() -> callBack.onResponse(false),
() -> callBack.onResponse(true));
}
}
@ -178,7 +200,8 @@ public class DialogUtils {
String mb = size.toUpperCase().replaceAll("MB", "").trim();
Float i = Float.valueOf(mb);
if (NetworkUtils.isWifiOr4GConnected(context) && i <= 50) {
Utils.toast(context, "当前使用移动流量下载");
AppExecutor.getUiExecutor().executeWithDelay(() -> Utils.toast(context, "当前使用移动网络下载,请注意流量消耗"),500);
return true;
}
} catch (Exception e) {
@ -206,14 +229,54 @@ public class DialogUtils {
}
public static void showDownloadDialog(Context context, ConfirmListener listener, CancelListener cancelListener) {
showWarningDialog(context, "下载提示", "当前正在使用移动网络,立即下载会消耗手机流量", "连上WiFi后自动下载", "立即下载", listener, cancelListener);
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_download_traffic, null);
View allowOnce = contentView.findViewById(R.id.allow_once);
View allowAlways = contentView.findViewById(R.id.allow_always);
View wifiAuto = contentView.findViewById(R.id.wifi_auto);
Context finalContext = context;
allowOnce.setOnClickListener(v -> {
AppExecutor.getUiExecutor().executeWithDelay(() -> {
Utils.toast(HaloApp.getInstance().getApplication(), "已使用移动网络下载,请注意流量消耗");
}, 500);
listener.onConfirm();
dialog.dismiss();
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "本次允许");
});
wifiAuto.setOnClickListener(v -> {
cancelListener.onCancel();
dialog.dismiss();
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "连上WiFi后自动下载");
});
allowAlways.setOnClickListener(v -> {
PreferenceManager
.getDefaultSharedPreferences(finalContext)
.edit()
.putBoolean(SettingsFragment.getTrafficDownloadHintKey(), false)
.apply();
AppExecutor.getUiExecutor().executeWithDelay(() -> {
// 显示了弹窗以后,即便下面这个 toast 放在 listener.onConfirm 后调用也是显示 listener.onConfirm 里的 toast
// 喷了,延时包治疑难杂症
Utils.toast(HaloApp.getInstance().getApplication(), "已使用移动网络下载,请注意流量消耗");
}, 500);
listener.onConfirm();
dialog.dismiss();
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "总是允许");
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
public static void showResumeDownloadDialog(Context context, ConfirmListener listener, CancelListener cancelListener) {
showWarningDialog(context, "下载提示", "当前正在使用移动网络,继续下载会消耗手机流量", "连上WiFi后自动下载", "继续下载", listener, cancelListener);
}
public static void showDownloadDialog(Context context, ConfirmListener listener) {
showWarningDialog(context, "下载提示", "您当前使用的网络为2G/3G/4G开始下载将会消耗移动流量确定下载", listener);
}
@ -224,10 +287,30 @@ public class DialogUtils {
}
public static void showPluginDialog(Context context, final ConfirmListener listener) {
Spanned spanned = Html.fromHtml("您将进行插件化安装以实现插件功能,此过程将"
+ "<font color=\"#ff0000\">卸载</font>" + "当前使用的版本并"
+ "<font color=\"#ff0000\">安装插件版本</font>");
showWarningDialog(context, "插件化安装", spanned, listener);
context = checkDialogContext(context);
MtaHelper.onEvent("插件化", "插件化安装弹窗", "出现弹窗提示");
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_plugin, null);
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
negativeTv.setOnClickListener(v -> {
dialog.dismiss();
MtaHelper.onEvent("插件化", "插件化安装弹窗", "取消");
});
positiveTv.setOnClickListener(view -> {
if (listener != null) {
listener.onConfirm();
}
dialog.dismiss();
MtaHelper.onEvent("插件化", "插件化安装弹窗", "确认并开始");
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
/**
@ -786,33 +869,71 @@ public class DialogUtils {
return dialog;
}
public static void showPrivacyPolicyDialog(Context context, String title, String content, EmptyCallback callback) {
public static void showPrivacyPolicyDialog(Context context,
@NonNull PrivacyPolicyEntity entity,
EmptyCallback callback) {
final Context activityContext = checkDialogContext(context);
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
AtomicBoolean isCanceledByClickOutsideOfDialog = new AtomicBoolean(true);
String privacyPolicyContent;
String privacyPolicyTitle = (TextUtils.isEmpty(title)) ? "个人信息保护指引" : title;
if (TextUtils.isEmpty(content)) {
privacyPolicyContent = "光环助手致力于为每位用户提供更安全的互联网环境,我们将依据相关法律法规和技术规范来收集和使用你的个人信息。" +
"<br/>1.为帮助你浏览内容、互动交流、注册认证等,我们需要获取一些必要的信息,以实现完整的功能;" +
"<br/>2.日常使用中,我们可能需要开启 IMEI号码、IMSI号码、定位、相册 等信息的读取权限;" +
"<br/>3.以上信息的读取权限均不会默认开启,只有在运行相关功能或服务时才会明确提示授权,光环助手不会在未经你同意的情况下收集相关信息。";
} else {
privacyPolicyContent = content;
final Dialog dialog = new Dialog(activityContext, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_privacy_policy, null);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
Window window = dialog.getWindow();
if (window != null) {
window.getDecorView().setPadding(0, 0, 0, 0);
window.setBackgroundDrawableResource(android.R.color.transparent);
WindowManager.LayoutParams params = window.getAttributes();
params.horizontalMargin = 0;
params.width = context.getResources().getDisplayMetrics().widthPixels;
params.height = context.getResources().getDisplayMetrics().heightPixels;
window.setAttributes(params);
}
final Dialog dialog = new Dialog(activityContext, R.style.GhAlertDialog);
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_privacy_policy, null);
TextView contentTv = contentView.findViewById(R.id.dialog_content);
TextView titleTv = contentView.findViewById(R.id.dialog_title);
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
TextView skipTv = contentView.findViewById(R.id.dialog_skip);
TextView title = contentView.findViewById(R.id.title);
TextView bottomContent = contentView.findViewById(R.id.bottom_content);
TextView topContent = contentView.findViewById(R.id.top_content);
TextView allowButton = contentView.findViewById(R.id.allow_button);
TextView linkContent = contentView.findViewById(R.id.link_content);
RecyclerView permissions = contentView.findViewById(R.id.permissions_content);
SpannableStringBuilder skipText = new SpannableStringBuilder("你可以查看完整版的 隐私政策");
permissions.setLayoutManager(new FixLinearLayoutManager(context));
permissions.setAdapter(new BaseRecyclerAdapter(context) {
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = mLayoutInflater.inflate(R.layout.privacy_item, parent, false);
return new PrivacyPolicyItemViewHolder(PrivacyItemBinding.bind(view));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof PrivacyPolicyItemViewHolder) {
PrivacyPolicyItemViewHolder viewHolder = (PrivacyPolicyItemViewHolder) holder;
PrivacyItemBinding binding = viewHolder.getBinding();
binding.setData(entity.getPermissions().get(position));
GenericDraweeHierarchy hierarchy = binding.icon.getHierarchy();
if (hierarchy != null) {
if (position == 0) {
hierarchy.setPlaceholderImage(R.drawable.permission_storage);
} else {
hierarchy.setPlaceholderImage(R.drawable.permission_phone_state);
}
}
}
}
@Override
public int getItemCount() {
return entity.getPermissions().size();
}
});
SpannableStringBuilder skipText = new SpannableStringBuilder("查看完整版的隐私政策和用户协议");
skipText.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(@NonNull TextPaint ds) {
@ -827,16 +948,31 @@ public class DialogUtils {
Intent intent = WebActivity.getPrivacyPolicyIntent(activityContext);
activityContext.startActivity(intent);
}
}, skipText.length() - 9, skipText.length() - 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
skipText.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(ContextCompat.getColor(activityContext, R.color.text_1383EB));
ds.setUnderlineText(false);
}
@Override
public void onClick(@NonNull View widget) {
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击用户协议");
activityContext.startActivity(WebActivity.getWebIntent(activityContext));
}
}, skipText.length() - 4, skipText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
title.setText(entity.getTitle());
linkContent.setText(skipText);
linkContent.setMovementMethod(new LinkMovementMethod());
allowButton.setText("我知道了");
topContent.setText(entity.getTopContent());
bottomContent.setText(entity.getBottomContent());
skipTv.setText(skipText);
skipTv.setMovementMethod(new LinkMovementMethod());
contentTv.setText(Html.fromHtml(privacyPolicyContent));
titleTv.setText(privacyPolicyTitle);
positiveTv.setText("我知道了");
positiveTv.setOnClickListener(view -> {
allowButton.setOnClickListener(view -> {
dialog.dismiss();
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击我知道了");
});
@ -844,13 +980,13 @@ public class DialogUtils {
dialog.setOnDismissListener(d -> {
callback.onCallback();
});
dialog.setOnCancelListener(cd -> {
if (isCanceledByClickOutsideOfDialog.get()) {
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击空白");
}
});
dialog.setOnKeyListener((dialog1, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
isCanceledByClickOutsideOfDialog.set(false);
@ -861,8 +997,6 @@ public class DialogUtils {
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "出现弹窗");
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
try {
dialog.show();
} catch (Exception ignored) {
@ -908,6 +1042,59 @@ public class DialogUtils {
return dialog;
}
public static Dialog showTrackableDialog(Context context,
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,
R.style.GhAlertDialog,
trackableEntity.getEvent(),
trackableEntity.getKey(),
trackableEntity.getCancelValue(),
trackableEntity.getKeyBackValue(),
trackableEntity.getLogShowEvent());
View 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);
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
if (message.toString().contains("红包奖励")) {//将红包奖励四个字标红
String str = message.toString().substring(0, message.toString().indexOf("红包奖励")) + "<font color='#FF0000'>红包奖励</font>";
contentTv.setText(Html.fromHtml(str));
} else {
contentTv.setText(message);
}
titleTv.setText(title);
negativeTv.setText(negative);
positiveTv.setText(positive);
negativeTv.setOnClickListener(view -> {
if (clListener != null) {
clListener.onCancel();
}
dialog.dismiss();
});
positiveTv.setOnClickListener(view -> {
if (cmListener != null) {
cmListener.onConfirm();
}
dialog.dismiss();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
return dialog;
}
public static Dialog fixWebViewKeyboardNotWorking(Activity activity) {
final Dialog dialog = new Dialog(activity, R.style.TransparentDialog);
View view = new View(activity);
@ -923,6 +1110,46 @@ public class DialogUtils {
return dialog;
}
public static Dialog showUsageStatsDialog(Context context, final ConfirmListener cmListener, final CancelListener clListener) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_usage_stats, null);
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
negativeTv.setOnClickListener(view -> {
if (clListener != null) {
clListener.onCancel();
}
dialog.dismiss();
});
positiveTv.setOnClickListener(view -> {
if (cmListener != null) {
cmListener.onConfirm();
}
dialog.dismiss();
});
dialog.setOnDismissListener(dialog1 -> {
if (clListener != null) {
clListener.onCancel();
}
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
return dialog;
}
/**
* @param context may be is application context
* @return activity context

View File

@ -9,6 +9,8 @@ import android.text.TextUtils
import com.gh.base.BaseActivity
import com.gh.base.fragment.BaseFragment_TabLayout
import com.gh.common.AppExecutor
import com.gh.common.constant.Config
import com.gh.common.exposure.ExposureEvent
import com.gh.common.util.EntranceUtils.*
import com.gh.gamecenter.*
import com.gh.gamecenter.amway.AmwayActivity
@ -19,6 +21,7 @@ import com.gh.gamecenter.eventbus.EBReuse
import com.gh.gamecenter.eventbus.EBSkip
import com.gh.gamecenter.fragment.MainWrapperFragment
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity
import com.gh.gamecenter.gamedetail.GameDetailFragment
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.mygame.PlayedGameActivity
import com.gh.gamecenter.personalhome.UserHomeActivity
@ -34,6 +37,9 @@ import com.gh.gamecenter.subject.SubjectActivity
import com.gh.gamecenter.suggest.SuggestType
import com.gh.gamecenter.tag.TagsActivity
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.lightgame.utils.Util_System_ClipboardManager
import com.lightgame.utils.Utils
import org.greenrobot.eventbus.EventBus
@ -49,27 +55,27 @@ object DirectUtils {
@JvmStatic
fun directToSpecificPage(context: Context, type: String, link: String, text: String? = "", entrance: String? = null, path: String? = null) {
when (type) {
EntranceUtils.HOST_ARTICLE -> directToArticle(context, id = link, entrance = entrance)
HOST_ARTICLE -> directToArticle(context, id = link, entrance = entrance)
EntranceUtils.HOST_GAME -> directToGameDetail(context, id = link, entrance = entrance)
HOST_GAME -> directToGameDetail(context, id = link, entrance = entrance)
EntranceUtils.HOST_GAME_DOWNLOAD -> directToGameDetail(context, id = link, entrance = entrance, autoDownload = true)
HOST_GAME_DOWNLOAD -> directToGameDetail(context, id = link, entrance = entrance, autoDownload = true)
EntranceUtils.HOST_COLUMN -> directToSubject(context, id = link, subjectName = text, entrance = entrance)
HOST_COLUMN -> directToSubject(context, id = link, subjectName = text, entrance = entrance)
EntranceUtils.HOST_QUESTION -> directToQuestionDetail(context, id = link, entrance = entrance, path = path)
HOST_QUESTION -> directToQuestionDetail(context, id = link, entrance = entrance, path = path)
EntranceUtils.HOST_ANSWER -> directToAnswerDetail(context, id = link, entrance = entrance, path = path)
HOST_ANSWER -> directToAnswerDetail(context, id = link, entrance = entrance, path = path)
EntranceUtils.HOST_WEB -> directToWebView(context, url = link, entrance = entrance)
HOST_WEB -> directToWebView(context, url = link, entrance = entrance)
EntranceUtils.HOST_DOWNLOAD -> directToDownloadManagerAndStartDownload(context, gameId = link, packageName = text, entrance = entrance)
HOST_DOWNLOAD -> directToDownloadManagerAndStartDownload(context, gameId = link, packageName = text, entrance = entrance)
EntranceUtils.HOST_UPDATE -> directToDownloadManagerAndStartUpdate(context, gameId = link, packageName = text, entrance = entrance)
HOST_UPDATE -> directToDownloadManagerAndStartUpdate(context, gameId = link, packageName = text, entrance = entrance)
EntranceUtils.HOST_LIBAO -> directToGiftDetail(context, giftId = link, entrance = entrance)
HOST_LIBAO -> directToGiftDetail(context, giftId = link, entrance = entrance)
EntranceUtils.HOST_COMMUNITY -> directToCommunity(context, CommunityEntity(link, text!!))
HOST_COMMUNITY -> directToCommunity(context, CommunityEntity(link, text!!))
}
}
@ -78,37 +84,80 @@ object DirectUtils {
*/
@JvmStatic
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String) {
directToLinkPage(context, linkEntity, entrance, path, null)
}
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String, exposureEvent: ExposureEvent? = null) {
directToLinkPage(context, linkEntity, entrance, path, exposureEvent, null)
}
// 用于判断是否已经对接相关类型
var directLinkTypes = arrayOf(
"article", "news",
"game",
"column",
"question",
"answer",
"community",
"community_article",
"community_column",
"community_special_column",
"web", "inurl",
"qq", "QQ",
"qqqun",
"tag",
"all_community_article",
"category",
"block",
"column_collection",
"server",
"top_game_comment",
"wechat_bind",
"video")
fun directToLinkPage(context: Context,
linkEntity: LinkEntity,
entrance: String,
path: String,
exposureEvent: ExposureEvent? = null,
unknownCallback: (() -> Unit)?) {
when (linkEntity.type) {
"article", "news" -> {
"article", "news", "文章" -> {
NewsUtils.statNewsViews(context, linkEntity.link) // 统计阅读量
context.startActivity(NewsDetailActivity.getIntentById(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path)))
}
"game" -> GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path))
"game", "游戏" -> {
if (exposureEvent != null) {
GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path), exposureEvent)
} else {
GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path))
}
}
"column" -> SubjectActivity.startSubjectActivity(context, linkEntity.link, linkEntity.text, false, BaseActivity.mergeEntranceAndPath(entrance, path))
"column", "游戏专题" -> SubjectActivity.startSubjectActivity(context, linkEntity.link, linkEntity.text, false, BaseActivity.mergeEntranceAndPath(entrance, path))
"question" -> context.startActivity(QuestionsDetailActivity.getIntent(context, linkEntity.link, entrance, path))
"question", "社区问题" -> context.startActivity(QuestionsDetailActivity.getIntent(context, linkEntity.link, entrance, path))
"answer" -> context.startActivity(AnswerDetailActivity.getIntent(context, linkEntity.link, entrance, path))
"answer", "社区回答" -> context.startActivity(AnswerDetailActivity.getIntent(context, linkEntity.link, entrance, path))
"community" -> directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
"community", "问答社区" -> directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
"community_article" -> context.startActivity(ArticleDetailActivity.getIntent(context, linkEntity.community!!, linkEntity.link!!, entrance, path))
"community_article", "社区文章" -> context.startActivity(ArticleDetailActivity.getIntent(context, linkEntity.community!!, linkEntity.link!!, entrance, path))
"community_column" -> directToCommunityColumn(context, linkEntity.community, linkEntity.link!!, entrance, path)
"community_column", "社区专题" -> directToCommunityColumn(context, linkEntity.community, linkEntity.link!!, entrance, path)
"community_special_column" -> context.startActivity(AskColumnDetailActivity.getIntentByColumnId(context, linkEntity.link, linkEntity.community!!, entrance, path))
"web", "inurl" -> directToWebView(context, url = linkEntity.link!!, entrance = BaseActivity.mergeEntranceAndPath(entrance, path))
"web", "inurl", "web链接" -> directToWebView(context, url = linkEntity.link!!, entrance = BaseActivity.mergeEntranceAndPath(entrance, path))
"qq" -> directToQqConversation(context, linkEntity.link)
"qq", "QQ" -> directToQqConversation(context, linkEntity.link)
"outurl" -> directToExternalBrowser(context, linkEntity.link!!)
"qqqun" -> directToQqGroup(context, linkEntity.link!!)
"qqqun", "QQ群" -> directToQqGroup(context, linkEntity.link!!)
"tag" -> context.startActivity(TagsActivity.getIntent(context, linkEntity.text!!, entrance, path))
"tag" -> context.startActivity(TagsActivity.getIntent(context, linkEntity.text!!, linkEntity.title, entrance, path))
"all_community_article" -> {
context.startActivity(SimpleArticleListActivity.getIntent(
@ -118,11 +167,11 @@ object DirectUtils {
path))
}
"category" -> {
"category", "分类" -> {
context.startActivity(CategoryDirectoryActivity.getIntent(context, linkEntity.link!!, linkEntity.text!!))
}
"block" -> {
"block", "版块" -> {
context.startActivity(BlockActivity.getIntent(context, SubjectRecommendEntity(
link = linkEntity.link,
text = linkEntity.text,
@ -130,7 +179,7 @@ object DirectUtils {
display = linkEntity.display ?: Display())))
}
"column_collection" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
"column_collection", "专题合集" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
"server" -> {
context.startActivity(GameServersActivity.getIntent(context, entrance, path))
@ -140,7 +189,21 @@ object DirectUtils {
"wechat_bind" -> context.startActivity(WebActivity.getBindWechatIntent(context))
else -> DialogUtils.showLowVersionDialog(context)
"video", "video_stream" -> directToVideoDetail(context,
videoId = linkEntity.link!!,
fromLocation = VideoDetailContainerViewModel.Location.VIDEO_CHOICENESS.value,
entrance = entrance,
path = path)
"game_video" -> directToGameVideo(context, linkEntity.link ?: "", entrance, path)
else -> {
if (unknownCallback != null) {
unknownCallback.invoke()
} else {
DialogUtils.showLowVersionDialog(context)
}
}
}
}
@ -192,6 +255,21 @@ object DirectUtils {
jumpActivity(context, bundle)
}
/**
* 跳转视频流-游戏介绍进入
*/
@JvmStatic
fun directToGameDetailVideoStreaming(context: Context, id: String, entrance: String? = null) {
val bundle = Bundle()
bundle.putString(KEY_TO, GameVideoActivity::class.java.name)
bundle.putString(KEY_ENTRANCE, entrance)
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)
}
// 跳转至用户玩过的游戏
fun directToPlayedGame(context: Context, userId: String, entrance: String = "", path: String = "") {
context.startActivity(PlayedGameActivity.getIntent(context, userId, entrance, path))
@ -309,16 +387,16 @@ object DirectUtils {
context.startActivity(browserIntent)
}
// 跳转 QQ
// 跳转 QQqqNumber 为空选择默认客服 QQ
@JvmStatic
fun directToQqConversation(context: Context, qqNumber: String? = null) {
var qq = qqNumber
if (TextUtils.isEmpty(qq)) {
qq = "2586716223"
qq = Config.getSettings()?.support?.qq ?: "3509629529"
}
if (ShareUtils.isQQClientAvailable(context)) {
// 安装了 QQ 直接调用QQ打开手机QQ进行会话 默认 QQ 号:2586716223
// 安装了 QQ 直接调用QQ打开手机QQ进行会话 默认 QQ 号:3509629529
val chatType: String
if (qq!!.startsWith("400") || qq.startsWith("800")) {
chatType = "crm"
@ -380,6 +458,21 @@ object DirectUtils {
}
}
@JvmStatic
fun directToCommunity(context: Context) {
if (MainActivity::class.java.name != RunningUtils.getTopActivity(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))
EventBus.getDefault().post(EBReuse(CommunityFragment.EB_RETRY_PAGE))
}
}
@JvmStatic
fun directToCommunityArticle(context: Context, articleId: String?, communityId: String?, entrance: String?, path: String?) {
val bundle = Bundle()
@ -409,15 +502,17 @@ object DirectUtils {
* @param fromLocation 可见 [VideoDetailContainerViewModel.Location]
*/
@JvmStatic
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, entrance: String? = null, path: String? = "") {
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null, path: String? = "", referer: String = "") {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, VideoDetailActivity::class.java.name)
bundle.putString(KEY_PATH, path)
bundle.putString(KEY_ID, videoId)
bundle.putString(KEY_GAMEID, gameId)
bundle.putString(KEY_LOCATION, fromLocation)
bundle.putBoolean(KEY_SHOW_COMMENT, showComment)
bundle.putString(KEY_REFERER, referer)
jumpActivity(context, bundle)
} else {
DialogUtils.showLowSystemVersionDialog(context)
@ -445,4 +540,31 @@ object DirectUtils {
fun directToBadgeWall(context: Context, userId: String?, name: String?, icon: String?) {
context.startActivity(WebActivity.getBadgeCenterIntent(context, userId, name, icon))
}
/**
* 跳转至上传视频
*/
@JvmStatic
fun directToVideoManager(context: Context, linkEntity: VideoLinkEntity, entrance: String? = null, path: String? = "") {
val bundle = Bundle()
bundle.putString(KEY_PATH, path)
bundle.putParcelable(VideoLinkEntity::class.java.simpleName, linkEntity)
bundle.putString(KEY_TO, VideoManagerActivity::class.java.name)
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
jumpActivity(context, bundle)
}
/**
* 跳转视频合集
*/
@JvmStatic
fun directToGameVideo(context: Context, gameId: String, entrance: String? = null, path: String? = "") {
val bundle = Bundle()
bundle.putString(KEY_PATH, path)
bundle.putString(KEY_TO, GameVideoActivity::class.java.name)
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
bundle.putString(KEY_GAMEID, gameId)
// context.startActivity(GameVideoActivity.getIntent(context, gameId, entrance, path))
jumpActivity(context, bundle)
}
}

View File

@ -1,11 +1,18 @@
package com.gh.common.util;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Build;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
import android.view.WindowManager;
@ -17,7 +24,7 @@ import java.lang.reflect.Method;
import androidx.core.content.ContextCompat;
public class DisplayUtils {
/**
* 根据手机的分辨率从 dip(像素) 的单位 转成为 px
*/
@ -25,7 +32,7 @@ public class DisplayUtils {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dip
*/
@ -33,19 +40,19 @@ public class DisplayUtils {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 根据手机的分辨率从 dip(像素) 的单位 转成为 px
*/
public static int dip2px(float dpValue) {
final float scale = HaloApp.getInstance()
.getApplication()
.getResources()
.getDisplayMetrics().density;
.getApplication()
.getResources()
.getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 将px值转换为sp值保证文字大小不变
*
@ -57,7 +64,7 @@ public class DisplayUtils {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
/**
* 将sp值转换为px值保证文字大小不变
*
@ -69,7 +76,7 @@ public class DisplayUtils {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
/**
* 获取状态栏的高度
*
@ -79,7 +86,7 @@ public class DisplayUtils {
public static int getStatusBarHeight(Resources resources) {
return getInternalDimensionSize(resources, "status_bar_height");
}
public static int getInternalDimensionSize(Resources res, String key) {
int result = 0;
int resourceId = res.getIdentifier(key, "dimen", "android");
@ -88,7 +95,7 @@ public class DisplayUtils {
}
return result;
}
public static void transparentStatusBar(Activity activity) {
//make full transparent statusBar
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
@ -96,15 +103,15 @@ public class DisplayUtils {
}
if (Build.VERSION.SDK_INT >= 19) {
activity.getWindow()
.getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
.getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
if (Build.VERSION.SDK_INT >= 21) {
setWindowFlag(activity, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
}
}
public static void transparentStatusAndNavigation(Activity activity) {
//make full transparent statusBar
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
@ -112,8 +119,8 @@ public class DisplayUtils {
}
if (Build.VERSION.SDK_INT >= 19) {
activity.getWindow()
.getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
.getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
if (Build.VERSION.SDK_INT >= 21) {
setWindowFlag(activity, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, false);
@ -121,7 +128,7 @@ public class DisplayUtils {
activity.getWindow().setNavigationBarColor(Color.TRANSPARENT);
}
}
private static void setWindowFlag(Activity activity, final int bits, boolean on) {
Window win = activity.getWindow();
WindowManager.LayoutParams winParams = win.getAttributes();
@ -132,14 +139,12 @@ public class DisplayUtils {
}
win.setAttributes(winParams);
}
public static void setLightStatusBar(Activity activity, boolean lightStatusBar) {
boolean isMIUI = setMIUIStatusBarStyle(activity, lightStatusBar);
if (!isMIUI) {
public static void setLightStatusBar(Activity activity, boolean lightStatusBar, boolean isKeepLowVersionMiui) {
if (!isMiuiOs()) {
Window window = activity.getWindow();
View decor = window.getDecorView();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (lightStatusBar) {
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
@ -149,46 +154,116 @@ public class DisplayUtils {
} else {
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
} else {
setMIUIStatusBarStyle(activity, lightStatusBar, isKeepLowVersionMiui);
}
}
private static boolean setMIUIStatusBarStyle(Activity activity, boolean lightStatusBar) {
boolean result = false;
Window window = activity.getWindow();
if (window != null) {
Class clazz = window.getClass();
try {
int darkModeFlag = 0;
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
extraFlagField.invoke(window, lightStatusBar ? darkModeFlag : 0, darkModeFlag);//状态栏透明且黑色字体
result = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && lightStatusBar) {
//开发版 7.7.13 及以后版本采用了系统API旧方法无效但不会报错所以两个方式都要加上
activity.getWindow()
.getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
} catch (Exception e) {
// do nothing
}
}
return result;
}
public static void setStatusBarColor(Activity activity, int color, boolean lightStatusBar) {
public static void setLightStatusBar(Activity activity, boolean lightStatusBar) {
setLightStatusBar(activity, lightStatusBar, true);
}
private static void setMIUIStatusBarStyle(Activity activity, boolean lightStatusBar, boolean isKeepLowVersionMiui) {
Window window = activity.getWindow();
if (window != null) {
View decor = window.getDecorView();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (lightStatusBar) {
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
} else {
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
if (isKeepLowVersionMiui) {
Class clazz = window.getClass();
try {
int darkModeFlag = 0;
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
extraFlagField.invoke(window, lightStatusBar ? darkModeFlag : 0, darkModeFlag);//状态栏透明且黑色字体
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && lightStatusBar) {
//开发版 7.7.13 及以后版本采用了系统API旧方法无效但不会报错所以两个方式都要加上
activity.getWindow()
.getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
} catch (Exception e) {
// do nothing
}
}
}
}
public static void setStatusBarColor(Activity activity, int color, boolean lightStatusBar) {
Window window = activity.getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setStatusBarColor(ContextCompat.getColor(activity,color));
window.setStatusBarColor(ContextCompat.getColor(activity, color));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setLightStatusBar(activity,lightStatusBar);
setLightStatusBar(activity, lightStatusBar);
}
}
private static boolean isMiuiOs() {
String property = getSystemProperty("ro.miui.ui.version.name", "");
return !TextUtils.isEmpty(property);
}
private static String getSystemProperty(String key, String defaultValue) {
try {
@SuppressLint("PrivateApi") Class<?> clz = Class.forName("android.os.SystemProperties");
Method method = clz.getMethod("get", String.class, String.class);
return (String) method.invoke(clz, key, defaultValue);
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
public static int retrieveNavigationHeight(Context context) {
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
return (resourceId > 0 && hasSoftKeys(context)) ? resources.getDimensionPixelSize(resourceId) : 0;
}
public static boolean hasSoftKeys(Context context) {
if (!(context instanceof Activity)) return false;
boolean hasSoftwareKeys;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Display d = ((Activity) context).getWindowManager().getDefaultDisplay();
DisplayMetrics realDisplayMetrics = new DisplayMetrics();
d.getRealMetrics(realDisplayMetrics);
int realHeight = realDisplayMetrics.heightPixels;
int realWidth = realDisplayMetrics.widthPixels;
DisplayMetrics displayMetrics = new DisplayMetrics();
d.getMetrics(displayMetrics);
int displayHeight = displayMetrics.heightPixels;
int displayWidth = displayMetrics.widthPixels;
hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0;
} else {
boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
hasSoftwareKeys = !hasMenuKey && !hasBackKey;
}
return hasSoftwareKeys;
}
}

View File

@ -1,18 +1,13 @@
package com.gh.common.util;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Message;
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.ReserveDialogFragment;
import com.gh.common.exposure.ExposureEvent;
@ -22,9 +17,11 @@ import com.gh.common.view.DownloadDialog;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WebActivity;
import com.gh.gamecenter.adapter.viewholder.GameViewHolder;
import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.LinkEntity;
import com.gh.gamecenter.entity.PluginLocation;
import com.gh.gamecenter.manager.PackagesManager;
import com.lightgame.download.DownloadConfig;
@ -35,6 +32,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;
public class DownloadItemUtils {
// 更新下载进度条
@ -167,22 +170,34 @@ public class DownloadItemUtils {
return;
}
if (gameEntity.getApk().isEmpty() || gameEntity.getDownloadOffStatus() != null) {
if (gameEntity.getApk().isEmpty()
|| gameEntity.getDownloadOffStatus() != null) {
LinkEntity h5LinkEntity = gameEntity.getH5Link();
String offStatus = gameEntity.getDownloadOffStatus();
holder.gameDes.setVisibility(View.VISIBLE);
holder.gameProgressbar.setVisibility(View.GONE);
holder.gameInfo.setVisibility(View.GONE);
String offStatus = gameEntity.getDownloadOffStatus();
if ("dialog".equals(offStatus)) {
holder.gameDownloadBtn.setText("查看");
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.white));
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
if (h5LinkEntity != null) {
if ("play".equals(h5LinkEntity.getType())) {
holder.gameDownloadBtn.setText("开始玩");
} else {
holder.gameDownloadBtn.setText("查看");
}
holder.gameDownloadBtn.setClickable(true);
} else {
holder.gameDownloadBtn.setText("暂无");
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.button_gray));
holder.gameDownloadBtn.setBackgroundResource(R.drawable.news_detail_comment);
if ("dialog".equals(offStatus)) {
holder.gameDownloadBtn.setText("查看");
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.white));
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
} else {
holder.gameDownloadBtn.setText("暂无");
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.button_gray));
holder.gameDownloadBtn.setBackgroundResource(R.drawable.news_detail_comment);
}
holder.gameDownloadBtn.setClickable(false);
}
holder.gameDownloadBtn.setClickable(false);
} else if (gameEntity.getApk().size() == 1) {
updateNormalItem(context, holder, gameEntity, isShowPlatform, pluginLocation);
} else {
@ -374,7 +389,10 @@ public class DownloadItemUtils {
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(context, () -> {
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
gameEntity,
() -> adapter.notifyItemChanged(position)
() -> {
LogUtils.logReservation(gameEntity, traceEvent);
adapter.notifyItemChanged(position);
}
);
dialogFragment.show(((AppCompatActivity) context).getSupportFragmentManager(), "reserve");
});
@ -402,8 +420,14 @@ public class DownloadItemUtils {
}
return;
}
if (gameEntity.getApk().size() == 1) {
if (gameEntity.getApk().size() == 0 && gameEntity.getH5Link() != null) {
downloadBtn.setOnClickListener(v -> {
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.getName());
Intent i = WebActivity.getIntentForWebGame(context, gameEntity.getH5Link().getLink(), gameEntity.getName(), "play".equals(gameEntity.getH5Link().getType()));
context.startActivity(i);
});
} else if (gameEntity.getApk().size() == 1) {
downloadBtn.setOnClickListener(v -> {
EmptyCallback clickRunnable = () -> {
if (clickCallback != null) {
@ -512,8 +536,6 @@ public class DownloadItemUtils {
downloadBtn.setText(R.string.downloading);
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
downloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
// DownloadManager.getInstance(context).putStatus(gameEntity.getApk().get(0).getUrl(), "downloading");
} else {
Utils.toast(context, msg);
}
@ -534,8 +556,6 @@ public class DownloadItemUtils {
downloadBtn.setText(R.string.downloading);
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
downloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
// DownloadManager.getInstance(context).putStatus(gameEntity.getApk().get(0).getUrl(), "downloading");
} else {
Utils.toast(context, msg);
}
@ -556,16 +576,20 @@ public class DownloadItemUtils {
}
adapter.notifyItemChanged(position);
} else {
PackageUtils.launchSetup(context, path);
PackageUtils.launchSetup(context, downloadEntity);
}
}
}
//更新
private static void update(Context context, GameEntity gameEntity, String entrance, String location,
boolean isSubscribe, @Nullable ExposureEvent traceEvent) {
DataUtils.onGameUpdateEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), "下载开始");
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, gameEntity.getApk().get(0).getPlatform(), traceEvent, ExposureUtils.DownloadType.UPDATE);
private static void update(Context context, GameEntity gameEntity, String entrance, String location, boolean isSubscribe, @Nullable ExposureEvent traceEvent) {
ApkEntity apkEntity = gameEntity.getApk().get(0);
ExposureUtils.DownloadType downloadType = ExposureUtils.getUpdateType(apkEntity);
DataUtils.onGameUpdateEvent(context, gameEntity.getName(), apkEntity.getPlatform(), "下载开始");
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity
.getPlatform(), traceEvent, downloadType);
DownloadManager.createDownload(context, gameEntity, "更新", entrance, location, isSubscribe, downloadExposureEvent);
}

View File

@ -0,0 +1,161 @@
package com.gh.common.util
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import com.gh.common.AppExecutor
import com.gh.common.constant.Constants
import com.gh.gamecenter.R
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
object DownloadNotificationHelper {
private const val DOWNLOAD_GROUP_KEY = "download_group_key"
private const val DOWNLOAD_CHANNEL_ID = "download"
private const val DOWNLOAD_NOTIFICATION_FOLD_ID = 889
private const val DOWNLOAD_NOTIFICATION_ID = 888
private const val PROGRESS_MAX = 100
const val ACTION_INSTALL = "com.gh.gamecenter.INSTALL"
const val ACTION_DOWNLOAD = "com.gh.gamecenter.DOWNLOAD"
private val mNotifyMap: MutableMap<String, Long> = mutableMapOf()
private fun getNotificationManager(): NotificationManager {
return HaloApp.getInstance().application.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}
@JvmStatic
@Synchronized
fun addOrUpdateDownloadNotification(entity: DownloadEntity) {
var requireUpdateNotificationGroupDelay = false
val notificationManager = getNotificationManager()
val downloadNotificationId = (entity.gameId + entity.packageName).hashCode()
val intent = Intent()
if (entity.status == DownloadStatus.done) {
intent.putExtra(EntranceUtils.KEY_DATA, entity.toJson())
intent.putExtra(EntranceUtils.KEY_PATH, entity.path)
intent.action = ACTION_INSTALL
} else {
intent.action = ACTION_DOWNLOAD
}
val pendingIntent = PendingIntent.getBroadcast(HaloApp.getInstance().application,
downloadNotificationId,
intent,
PendingIntent.FLAG_UPDATE_CURRENT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// importance == IMPORTANCE_DEFAULT 时每次更新都会触发震动
val channel = NotificationChannel(DOWNLOAD_CHANNEL_ID, DOWNLOAD_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
notificationManager.createNotificationChannel(channel)
}
val whenTime = 1000 * 60 * (System.currentTimeMillis() / 1000 / 60)
val builder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
.setContentTitle(entity.name)
.setSmallIcon(R.mipmap.logo)
.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("暂停中")
}
when {
entity.status == DownloadStatus.done -> {
builder.setSortKey("A")
builder.setOngoing(true) // 垃圾华为 sortKey 不起效 priority 也不起效,要将下载完成任务的通知置顶只能设置为 ongoing喷了
}
entity.status == DownloadStatus.downloading -> builder.setSortKey("B")
else -> builder.setSortKey("C")
}
val notification = builder.build()
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
if (entity.status == DownloadStatus.delete
|| entity.status == DownloadStatus.cancel
|| entity.status == DownloadStatus.hijack
|| entity.status == DownloadStatus.notfound
|| entity.status == DownloadStatus.overflow
|| (entity.status == DownloadStatus.done // 触发安装事件以后也 cancel 掉通知
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty())) {
requireUpdateNotificationGroupDelay = true
notificationManager.cancel(entity.path, DOWNLOAD_NOTIFICATION_ID)
} else {
if (entity.status != DownloadStatus.downloading) {
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
} else {
val time = mNotifyMap[entity.path]
val curTime = System.currentTimeMillis()
if (time == null || curTime - time > 2000) {
mNotifyMap[entity.path] = curTime
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
}
}
}
if (requireUpdateNotificationGroupDelay) {
// 虽然运行到这里时 notification 已经被 cancel 了,但在下面的 notificationManager.getActiveNotifications 里它有可能还是 active 状态,
// 这里延时 100 ms 避免出现所有的任务都取消了以后依旧有一条 notification group 常驻
AppExecutor.uiExecutor.executeWithDelay(Runnable { updateNotificationGroup() }, 100)
} else {
updateNotificationGroup()
}
}
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++
}
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)
}
}
}
@JvmStatic
fun initDownloadNotification(downloadTasks: MutableList<DownloadEntity>) {
for (downloadTask in downloadTasks) {
addOrUpdateDownloadNotification(downloadTask)
}
}
}

View File

@ -24,6 +24,12 @@ public class EntranceUtils {
public static final String KEY_URL = "url";
public static final String KEY_GAMENAME = "gameName";
public static final String HOST_ARTICLE = "article";
public static final String HOST_UPLOAD_VIDEO = "upload_video";//上传视频
public static final String HOST_VIDEO_SINGLE = "video_single";//指定视频-不能划动
public static final String HOST_VIDEO_MORE = "video_more";//指定视频-能划动
public static final String HOST_VIDEO_STREAMING_HOME = "video_streaming_home";//视频流-首页
public static final String HOST_VIDEO_STREAMING_DESC = "video_streaming_desc";//视频流-游戏介绍进入
public static final String HOST_VIDEO_COLLECTION = "video_collection";//视频合集
public static final String HOST_VIDEO = "video";
public static final String HOST_COMMUNITY_ARTICLE = "community_article";
public static final String HOST_COMMUNITY_COLUMN = "community_column";
@ -32,6 +38,7 @@ public class EntranceUtils {
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_DOWNLOAD = "download";
public static final String HOST_UPDATE = "update";
public static final String HOST_LIBAO = "libao";
@ -48,6 +55,7 @@ public class EntranceUtils {
public static final String KEY_NAME = "name";
public static final String KEY_POSITION = "position";
public static final String KEY_ENTRANCE = "entrance";
public static final String KEY_ENTRANCE_LINK = "entrance_link";
public static final String KEY_TARGET = "target";
public static final String ENTRANCE_BROWSER = "(浏览器)";
public static final String ENTRANCE_WELCOME = "(启动弹窗)";
@ -125,6 +133,13 @@ public class EntranceUtils {
public static final String KEY_AMWAY = "amway";
public static final String KEY_COLLECTION_ID = "collectionId";
public static final String KEY_NAVIGATION_TITLE = "navigationTitle";
public static final String KEY_IMAGE_CROP_RATIO = "imageCropRatio";
public static final String KEY_OPEN_VIDEO_STREAMING = "openVideoStreaming";
public static final String KEY_REFERER = "referer";
public static final String KEY_UUID = "uuid";
public static final String KEY_IS_HOME_VIDEO = "isHomeVideo";
public static final String KEY_IS_HOME = "isHome";
public static final String KEY_WEB_SHARE = "webShare";
public static void jumpActivity(Context context, Bundle bundle) {

View File

@ -1,6 +1,7 @@
package com.gh.common.util
import android.content.Context
import com.gh.common.constant.Config
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.entity.ErrorEntity
@ -110,9 +111,10 @@ object ErrorHelper {
403016 -> Utils.toast(context, "标签内容可能包含敏感信息,请修改后再提交")
403018 -> Utils.toast(context, R.string.comment_failed_unable)
403070 -> Utils.toast(context, "请勿重复提交~")
403073 -> Utils.toast(context, "标题可能包含敏感词,请修改后再提交")
403073 -> Utils.toast(context, "标题违规,请重新编辑")
403074 -> Utils.toast(context, "该微信号(${errorEntity.data?.nickname})已绑定")
403078 -> Utils.toast(context, "已点赞")
403072 -> Utils.toast(context, R.string.comment_failed_userblocked)
403020 -> if (showHighPriorityHint) {
DialogUtils.showAlertDialog(context,
@ -143,7 +145,7 @@ object ErrorHelper {
val dialogContext = DialogUtils.checkDialogContext(context)
DialogUtils.showAlertDialog(dialogContext,
"提示",
"你因违反《光环助手评论规则》,已被禁言,如有疑问$bannedType请联系客服QQ3467475980",
"你因违反《光环助手评论规则》,已被禁言$bannedType如有疑问,请联系客服QQ${Config.getSettings()?.support?.qq}",
"去看看", "关闭", {
dialogContext.startActivity(WebActivity.getCommentRulesIntent(dialogContext))
}, null)

View File

@ -1,5 +1,6 @@
package com.gh.common.util
import android.animation.Animator
import android.content.ClipboardManager
import android.content.Context
import android.text.Editable
@ -18,6 +19,7 @@ import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.*
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
import com.airbnb.lottie.LottieAnimationView
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.common.constant.Config
import com.gh.common.constant.Constants
@ -26,9 +28,13 @@ import com.gh.gamecenter.R
import com.google.gson.reflect.TypeToken
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import okhttp3.MediaType
import okhttp3.RequestBody
import java.net.URI
import java.util.concurrent.TimeUnit
import kotlin.math.abs
/**
@ -223,6 +229,11 @@ fun String.fromHtml(): Spanned {
return HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
// 将双引号换成单引号避免 JSON 解析异常 ( escape 后会有其它异常,暂时先替换成单引号了)
fun String.eliminateDoubleQuote(): String {
return this.replace("\"", "'")
}
// 去掉文章/答案的插入内容
fun String.removeInsertedContent(): String {
val textRegex = "(?s)<div class=\"gh-internal-content content-right\".*?</div>"
@ -262,6 +273,16 @@ fun Map<String, String>.createRequestBody(): RequestBody {
return RequestBody.create(MediaType.parse("application/json"), json)
}
fun Map<String, Any>.createRequestBodyAny(): RequestBody {
val json = GsonUtils.toJson(this)
return RequestBody.create(MediaType.parse("application/json"), json)
}
fun Any.toRequestBody(): RequestBody {
val json = GsonUtils.toJson(this)
return RequestBody.create(MediaType.parse("application/json"), json)
}
// 对在浏览器(WebView)显示的路径进行转码
fun String.decodeURI(): String {
return URI(null, null, this, null).rawPath
@ -285,8 +306,9 @@ fun Float.px2dip(): Int {
/**
* PopupWindow 自动适配方向
* 弹出与锚点右对齐
*/
fun PopupWindow.showAutoOrientation(anchorView: View, distanceY: Int = 0) {
fun PopupWindow.showAutoOrientation(anchorView: View, distanceY: Int = 0, distanceX: Int = 0) {
val windowPos = IntArray(2)
val anchorLoc = IntArray(2)
// 获取锚点View在屏幕上的左上角坐标位置
@ -294,21 +316,18 @@ fun PopupWindow.showAutoOrientation(anchorView: View, distanceY: Int = 0) {
val anchorHeight = anchorView.height + distanceY
// 获取屏幕的高宽
val screenHeight = anchorView.context.resources.displayMetrics.heightPixels
val screenWidth = anchorView.context.resources.displayMetrics.widthPixels
// 测量contentView
contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
// 计算contentView的高宽
val windowHeight = contentView.measuredHeight
val windowWidth = contentView.measuredWidth
// 判断需要向上弹出还是向下弹出显示
val isNeedShowUp = screenHeight - anchorLoc[1] - anchorHeight < windowHeight
if (isNeedShowUp) {
windowPos[0] = screenWidth - windowWidth
windowPos[1] = anchorLoc[1] - windowHeight
} else {
windowPos[0] = screenWidth - windowWidth
windowPos[1] = anchorLoc[1] + anchorHeight
}
windowPos[1] = if (isNeedShowUp) {
anchorLoc[1] - windowHeight
} else anchorLoc[1] + anchorHeight
windowPos[0] = anchorLoc[0] - windowWidth + anchorView.width - distanceX
animationStyle = R.style.popwindow_option_anim_style
showAtLocation(anchorView, Gravity.TOP or Gravity.START, windowPos[0], windowPos[1])
@ -431,4 +450,76 @@ inline fun testChannelOnly(f: () -> Unit) {
if (HaloApp.getInstance().channel == Config.DEFAULT_CHANNEL) {
f()
}
}
/**
* 倒计时单位s
*/
inline fun countDownTimer(
millisUntilFinish: Long,
crossinline block: (finish: Boolean, millisUntilFinished: Long) -> Unit
): Disposable {
var subscribe: Disposable? = null
subscribe = Observable.interval(0, 1000, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
if (it < millisUntilFinish) {
block.invoke(false, millisUntilFinish - it)
} else {
block.invoke(true, 0)
if (subscribe != null && !subscribe!!.isDisposed) {
subscribe?.dispose()
}
}
}
return subscribe
}
/**
* 正计时
* @start 起始时间
*/
inline fun countUpTimer(
start: Long,
period: Long = 1000,
crossinline block: (millisUntilFinished: Long) -> Unit
): Disposable {
var startTime = start
return Observable.interval(0, period, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
startTime += period
block.invoke(startTime)
}
}
/**
* 计时器(注意不需要的时候要取消订阅)
*/
inline fun rxTimer(interval: Long, crossinline block: (times: Long) -> Unit): Disposable {
return Observable.interval(0, interval, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
block.invoke(it)
}
}
fun LottieAnimationView.doOnAnimationEnd(action: () -> Unit) {
this.addAnimatorListener(object : Animator.AnimatorListener {
override fun onAnimationRepeat(animation: Animator?) {
}
override fun onAnimationEnd(animation: Animator?) {
action.invoke()
}
override fun onAnimationCancel(animation: Animator?) {
}
override fun onAnimationStart(animation: Animator?) {
}
})
}

View File

@ -2,10 +2,11 @@ package com.gh.common.util;
import android.content.Context;
import android.graphics.Color;
import androidx.core.content.ContextCompat;
import android.text.TextUtils;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import com.gh.common.constant.Config;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.R;
@ -148,6 +149,7 @@ public class GameUtils {
gameUpdateEntity.setBrief(gameEntity.getBrief());
gameUpdateEntity.setPlugin(apkEntity.getPlugin());
gameUpdateEntity.setDownload(gameEntity.getDownload());
gameUpdateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
return gameUpdateEntity;
}

View File

@ -3,7 +3,6 @@ package com.gh.common.util;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import androidx.core.content.ContextCompat;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.View;
@ -22,6 +21,8 @@ import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import androidx.core.content.ContextCompat;
/**
* @author 温冠超
* @email 294299195@qq.com
@ -53,6 +54,28 @@ public class GameViewUtils {
}
}
public static void setLabelList(Context context, LinearLayout labelLayout, String tagType, List<TagStyleEntity> tagStyle) {
labelLayout.removeAllViews();
if (tagStyle == null || tagStyle.isEmpty()) {
labelLayout.addView(getGameTagView(context, "官方版", 0, tagType, null));
} else {
for (int i = 0; i < tagStyle.size() - 1; i++) {
View view;
if (i == tagStyle.size() - 1) {
view = getGameTagView(context, tagStyle.get(i).getName(), 0, tagType, tagStyle.size() > i ? tagStyle.get(i) : null);
} else {
view = getGameTagView(context, tagStyle.get(i).getName(), DisplayUtils.dip2px(context, 8), tagType, tagStyle.size() > i ? tagStyle.get(i) : null);
}
if (view != null) {
labelLayout.addView(view);
}
if (labelLayout.getChildCount() == 3) {
break;
}
}
}
}
private static TextView getGameTagView(Context context, String tagStr, int rightMargin, String tagType, TagStyleEntity tagEntity) {
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

View File

@ -15,7 +15,7 @@ class GhMatisseVideoFilter : Filter() {
override fun filter(context: Context, item: Item): IncapableCause? {
if (!needFiltering(context, item)) return null
if (item.mimeType != MimeType.MP4.toString()) {
return IncapableCause(IncapableCause.TOAST, "请把视频格式转换为Mp4后再上传")
return IncapableCause(IncapableCause.TOAST, "请把视频格式转换为MP4后再上传")
}
if (item.size > 500 * 1024 * 1024) {

View File

@ -0,0 +1,38 @@
package com.gh.common.util
import com.gh.gamecenter.entity.Display
import com.gh.gamecenter.entity.SubjectRecommendEntity
import com.halo.assistant.HaloApp
object HomeBottomBarHelper {
private const val GAME_BAR_KEY = "game_bar_key"
@JvmStatic
fun getDefaultGameBarData(): SubjectRecommendEntity {
try {
val json = SPUtils.getString(GAME_BAR_KEY)
if (json.isNotEmpty()) {
return GsonUtils.fromJson(json, SubjectRecommendEntity::class.java)
}
} catch (ignore: Exception) {
}
val animationCode = HaloApp.getInstance().application.assets
.open("lottie/tab_game.json")
.bufferedReader().use { it.readText() }
return SubjectRecommendEntity(link = "5de21b5d75e6fa054f784882",
type = "block",
text = "游戏库",
name = "游戏库",
iconSelect = "https://resource.ghzs.com/image/game/library/entrance/5e183202913fbd002c75f247.png",
iconUnselect = "https://resource.ghzs.com/image/game/library/entrance/5e1831fd913fbd003024641e.png",
animationCode = animationCode,
default = false,
display = Display())
}
@JvmStatic
fun updateDefaultGameBarData(data: SubjectRecommendEntity) {
SPUtils.setString(GAME_BAR_KEY, data.toJson())
}
}

View File

@ -259,7 +259,8 @@ object ImageUtils {
}
// Wifi/4G:x2 traffic:x1
private fun getTransformLimitUrl(url: String?, width: Int?, context: Context?): String? {
@JvmStatic
fun getTransformLimitUrl(url: String?, width: Int?, context: Context?): String? {
var transformUrl: String? = url
if (width != null && width > 0) {
val transformUrlX2 = addLimitWidth(url, width * 2)

View File

@ -6,24 +6,102 @@ import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
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.gamecenter.BuildConfig;
import com.gh.gamecenter.entity.CommunityEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.SpecialColumn;
import com.gh.gamecenter.manager.UserManager;
import com.gh.gamecenter.qa.entity.Questions;
import com.gh.loghub.LogHubUtils;
import com.halo.assistant.HaloApp;
import com.lightgame.download.DownloadEntity;
import com.lightgame.utils.Util_System_Phone_State;
import com.lightgame.utils.Utils;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.Nullable;
/**
* Created by khy on 2/01/18.
*/
public class LogUtils {
public static void logVideoStreamingUpload(String action, String entrance, String entranceDetail, String videoId) {
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
try {
object.put("event", "UPLOAD_VIDEO_STEAMING");
object.put("action", action);
payloadObject.put("entrance", entrance);
payloadObject.put("entrance_detail", entranceDetail);
payloadObject.put("video_id", videoId);
object.put("payload", payloadObject);
} catch (JSONException e) {
e.printStackTrace();
}
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 {
@ -48,10 +126,10 @@ public class LogUtils {
} catch (JSONException e) {
e.printStackTrace();
}
upload(object);
uploadToCommunity(object);
}
public static void uploadDevice(LunchType launchType) {
JSONObject object = new JSONObject();
Application application = HaloApp.getInstance().getApplication();
@ -63,10 +141,10 @@ public class LogUtils {
} catch (JSONException e) {
e.printStackTrace();
}
upload(object);
uploadToCommunity(object, true);
}
public static void uploadAnswerReadTime(String tracers, int readTime, String answerId, Questions questions, String communityId, String CommunityName, SpecialColumn specialColumn) {
JSONObject object = new JSONObject();
try {
@ -92,10 +170,10 @@ public class LogUtils {
} catch (JSONException e) {
e.printStackTrace();
}
upload(object);
uploadToCommunity(object);
}
public static void uploadQuestionReadTime(String tracers, int readTime, Questions questions, String communityId, String communityName, SpecialColumn specialColumn) {
JSONObject object = new JSONObject();
try {
@ -120,13 +198,13 @@ public class LogUtils {
} catch (JSONException e) {
e.printStackTrace();
}
upload(object);
uploadToCommunity(object);
}
public static void uploadSearch(String searchKey) {
if (TextUtils.isEmpty(searchKey)) return;
JSONObject object = new JSONObject();
try {
object.put("community_id", UserManager.getInstance().getCommunity().getId());
@ -136,11 +214,10 @@ public class LogUtils {
} catch (JSONException e) {
e.printStackTrace();
}
upload(object);
uploadToCommunity(object);
}
public static void communityRefresh(int dataCount, boolean manualRefresh) {
JSONObject object = new JSONObject();
try {
@ -152,10 +229,10 @@ public class LogUtils {
} catch (JSONException e) {
e.printStackTrace();
}
upload(object);
uploadToCommunity(object);
}
public static void login(String loginStep, String loginType, String entrance) {
JSONObject object = new JSONObject();
try {
@ -166,10 +243,10 @@ public class LogUtils {
} catch (JSONException e) {
e.printStackTrace();
}
upload(object);
uploadToCommunity(object, true);
}
public static void qaAccess(String access, CommunityEntity communityEntity) {
JSONObject object = new JSONObject();
try {
@ -180,15 +257,42 @@ public class LogUtils {
} catch (JSONException e) {
e.printStackTrace();
}
upload(object);
uploadToCommunity(object);
}
public static void logReservation(GameEntity gameEntity, @Nullable ExposureEvent event) {
JSONObject object = new JSONObject();
List<ExposureSource> exposureSourceList;
if (event == null) {
exposureSourceList = new ArrayList<>();
exposureSourceList.add(new ExposureSource("其它", ""));
} else {
exposureSourceList = event.getSource();
}
try {
object.put("source", GsonUtils.toJson(exposureSourceList));
object.put("game_name", gameEntity.getName());
object.put("game_id", gameEntity.getId());
object.put("game_platform", gameEntity.getPlatform());
} catch (JSONException e) {
e.printStackTrace();
}
uploadToReservation(object);
}
private static void upload(JSONObject object) {
private static void uploadToCommunity(JSONObject object) {
uploadToCommunity(object, false);
}
private static void uploadToCommunity(JSONObject object, boolean forcedUpload) {
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
Context context = HaloApp.getInstance().getApplication();
try {
object.put("version", PackageUtils.getVersionName());
@ -200,13 +304,119 @@ public class LogUtils {
object.put("device_system", android.os.Build.VERSION.RELEASE);
object.put("device_model", android.os.Build.MODEL);
object.put("imei", Util_System_Phone_State.getImei(HaloApp.getInstance()
.getApplication()));
.getApplication()));
object.put("G_ID", UserManager.getInstance().getDeviceId());
} catch (JSONException e) {
e.printStackTrace();
}
// 暂时除了曝光外的数据都是扔到 community 这个库的,要是不是这个这个库的话这里要改一下
LogHubUtils.uploadLog(DeviceUtils.getIPAddress(context), object, "community");
LoghubUtils.log(object, "community", forcedUpload);
}
/**
* 上传数据到“预约”的 logStore
*/
private static void uploadToReservation(JSONObject object) {
Context context = HaloApp.getInstance().getApplication();
try {
object.put("version", PackageUtils.getVersionName());
object.put("channel", HaloApp.getInstance().getChannel());
object.put("android_id", Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID));
object.put("time", Utils.getTime(context));
object.put("network", DeviceUtils.getNetwork(context));
object.put("user_id", UserManager.getInstance().getUserId());
object.put("device_system", android.os.Build.VERSION.RELEASE);
object.put("device_model", android.os.Build.MODEL);
object.put("imei", Util_System_Phone_State.getImei(HaloApp.getInstance()
.getApplication()));
object.put("G_ID", UserManager.getInstance().getDeviceId());
} catch (JSONException e) {
e.printStackTrace();
}
LoghubUtils.log(object, "appointment", false);
}
private static void uploadVideoStreaming(JSONObject object) {
Meta meta = MetaUtil.INSTANCE.getMeta();
JSONObject metaObject = new JSONObject();
try {
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", meta.getNetwork());
metaObject.put("os", meta.getOs());
metaObject.put("userId", meta.getUserId());
object.put("meta", metaObject);
object.put("timestamp", System.currentTimeMillis() / 1000);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "video_streaming", false);
}
public static void uploadVideoStreamingEnter(String entrance, String entranceDetail, String videoId, String streamingId) {
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
try {
object.put("event", "ENTERING_VIDEO_STEAMING");
payloadObject.put("entrance", entrance);
if (!TextUtils.isEmpty(entranceDetail)) {
payloadObject.put("entrance_detail", entranceDetail);
}
payloadObject.put("video_id", videoId);
payloadObject.put("streaming_id", streamingId);
object.put("payload", payloadObject);
} catch (JSONException e) {
e.printStackTrace();
}
uploadVideoStreaming(object);
}
public static void uploadVideoStreamingPlaying(String action, String msg, String entrance, String entranceDetail, String videoId, String streamingId, double videoSize, int videoTotalTime, int progress, String videoPlayStatus) {
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
try {
object.put("event", "VIDEO_PLAYING");
object.put("action", action);
if (!TextUtils.isEmpty(msg)) {
object.put("msg", msg);
}
payloadObject.put("entrance", entrance);
if (!TextUtils.isEmpty(entranceDetail)) {
payloadObject.put("entrance_detail", entranceDetail);
}
payloadObject.put("video_id", videoId);
payloadObject.put("streaming_id", streamingId);
if (videoSize > 0) {
payloadObject.put("video_size", videoSize);
}
if (videoTotalTime > 0) {
payloadObject.put("video_total_time", videoTotalTime);
}
payloadObject.put("progress", progress);
payloadObject.put("video_play_status", videoPlayStatus);
object.put("payload", payloadObject);
} catch (JSONException e) {
e.printStackTrace();
}
uploadVideoStreaming(object);
}
}

View File

@ -264,6 +264,12 @@ public class LoginUtils {
case 400212:
Utils.toast(context, "请输入正确的手机号");
break;
case 400010:
Utils.toast(context, "身份证无效,请重新输入");
break;
case 400011:
Utils.toast(context, "请输入正确的身份信息");
break;
default:
Utils.toast(context, code + "");
break;

View File

@ -1,22 +1,122 @@
package com.gh.common.util
import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NotificationManagerCompat
import com.gh.common.constant.Constants
import com.gh.common.dialog.NotificationHintDialogFragment
import com.gh.gamecenter.entity.NotificationHint
import com.gh.gamecenter.entity.NotificationUgc
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.AppManager
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
object NotificationHelper {
@JvmStatic
fun showNotificationHintDialog(ugc: NotificationUgc) {
val showedNewVersion = SPUtils.getInt(Constants.SP_SHOWED_NOTIFICATION_NEW_VERSION, 0)
val currentVersion = PackageUtils.getVersionCode()
// 版本升级后重置数据
if (currentVersion > showedNewVersion) {
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, false)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, false)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ANSWER, false)
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.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, "")
SPUtils.setInt(Constants.SP_SHOWED_NOTIFICATION_NEW_VERSION, currentVersion)
}
val isShowedToday = SPUtils.getString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, "")
// 每天最多只需提示一次
if (isShowedToday == TimeUtils.getToday()) return
val isShowedLogin = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, false)
val isShowedQuestion = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, false)
val isShowedAnswer = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_ANSWER, false)
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)
if (isShowedLogin && isShowedQuestion && isShowedAnswer && isShowedArticle && isShowedVideo && isShowedRating) return
when (ugc) {
NotificationUgc.LOGIN -> {
if (!isShowedLogin) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, true)
// 设置今天的时间,表示今天已经触发过了
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
}
}
NotificationUgc.QUESTION -> {
if (!isShowedQuestion) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
}
}
NotificationUgc.ANSWER -> {
if (!isShowedAnswer) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ANSWER, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
}
}
NotificationUgc.ARTICLE -> {
if (!isShowedArticle) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ARTICLE, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
}
}
NotificationUgc.VIDEO -> {
if (!isShowedVideo) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_VIDEO, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
}
}
NotificationUgc.RATING -> {
if (!isShowedRating) {
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_RATING, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
}
}
}
}
@SuppressLint("CheckResult")
private fun show(activity: AppCompatActivity?) {
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) {
}
}
})
}
@JvmStatic
fun showEnableNotificationDialogIfItsDisabled(activity: AppCompatActivity, notificationHint: NotificationHint) {
if (notificationIsEnable()) {
Utils.log("notification is enable")
} else {
NotificationHintDialogFragment.getInstance(notificationHint).show(activity.supportFragmentManager, "notification")
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_HINT, true)
}
}

View File

@ -16,4 +16,13 @@ object NumberUtils {
}
return s
}
@JvmStatic
fun transSimpleUsageTime(second: Long): String {
val totalMinute = second / 60
if (totalMinute < 60) return ((if (totalMinute == 0L) 1 else totalMinute).toString() + "分钟")
val hour = Math.round((totalMinute / 60).toFloat())
val minute = Math.round((totalMinute - hour * 60).toFloat())
return hour.toString() + "小时" + if (minute == 0) "" else minute.toString() + "分钟"
}
}

View File

@ -13,14 +13,14 @@ import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import androidx.core.content.FileProvider;
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.halo.assistant.HaloApp;
import com.lightgame.download.DownloadEntity;
import com.lightgame.utils.Utils;
import org.json.JSONArray;
@ -35,6 +35,8 @@ import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import androidx.core.content.FileProvider;
public class PackageUtils {
public static final String publicKey = "OpenSSLRSAPublicKey{modulus=a8c4bb5748fec8d5c35db1a7a182d41ba4721a91131a417330af79ef4ddb43f9fa0ff4907b0a613bfe152de0ed8fc1b2e6f94a908aa98a5f7adc1ce814ba7ec919d75d9910bdfd8649b4789da6a90ffb61f0d23ac4f828a78fcd0d6f6120c1c43c1f87f7498a89eb40ca8e32dfc2f9d5c10d612b95192870223674e241e53305abf320d7eed76ded398778576e4db7b17b3bc6a792f13de5e43a6a5fae4276c73e6990ce97f68dff0ec16fc9594f175c8d49cd0d7877340d9de60942ca0efc737e50b6c295dfe0713e4532b4e810e1ea11b702b4a27753e41559cbceb247e7f044ec4e3ab2e8bccd8b9fd71286e63307550bcde86deee95adb8133076269135b,publicExponent=10001}";
@ -73,6 +75,7 @@ public class PackageUtils {
updateEntity.setTag(gameEntity.getTag());
updateEntity.setTagStyle(gameEntity.getTagStyle());
updateEntity.setDownload(gameEntity.getDownload());
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
updateList.add(updateEntity);
}
}
@ -108,6 +111,7 @@ public class PackageUtils {
updateEntity.setBrief(gameEntity.getBrief());
updateEntity.setTag(gameEntity.getTag());
updateEntity.setTagStyle(gameEntity.getTagStyle());
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
updateList.add(updateEntity);
}
}
@ -188,11 +192,18 @@ public class PackageUtils {
}
return ret;
}
/*
* 启动安装应用程序
*/
public static void launchSetup(final Context context, final String path) {
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));
@ -237,6 +248,10 @@ public class PackageUtils {
* 根据路径,获取安装游戏的意图
*/
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)) {
@ -249,6 +264,10 @@ public class PackageUtils {
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
if (isInAppUpdate) {
// 应用内更新不加 FLAG_ACTIVITY_NEW_TASK 在模拟器上会出现安装完成后安装界面也一并消失的类似闪退的表现
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
}
InstallUtils.getInstance(context).addInstall(getPackageNameByPath(context, path));

View File

@ -4,6 +4,8 @@ import android.util.Patterns;
import java.util.regex.Matcher;
import kotlin.text.Regex;
/**
* @author CsHeng
* @Date 17/05/2017
@ -32,6 +34,25 @@ public class PatternUtils {
Matcher matcher = Patterns.PHONE.matcher(phone);
return matcher.matches();
}
/**
* 判断字符串中是否有连续2个以上的空格 忽略 \t \r \n
*/
public static boolean isHasSpace(String text) {
String pattern = "[\\s|\\t|\\r|\\n]{2,}";
Regex regex = new Regex(pattern);
return regex.find(text, 0) != null;
}
/**
* 替换字符串中连续2个以上的空格为一个空格 忽略 \t \r \n
*/
public static String replaceSpace(String text) {
String pattern = "[\\s|\\t|\\r|\\n]{2,}";
String newText = text;
if (isHasSpace(text)) {
newText = text.replaceAll(pattern, " ");
}
return newText;
}
}

View File

@ -52,6 +52,7 @@ import java.util.List;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import kotlin.jvm.functions.Function0;
import static com.gh.common.util.LoginHelper.WEIBO_SCOPE;
@ -148,6 +149,79 @@ public class ShareUtils {
return false;
}
public void showShareWindowsCancelCallback(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareType shareType, Function0 function) {
if (activity.isFinishing()) return;
this.mActivity = new WeakReference<>(activity);
this.shareIcon = icon;
this.shareUrl = url;
this.mSummary = shareSummary;
this.mTitle = shareTitle;
this.mShareType = shareType;
View contentView = View.inflate(activity, R.layout.share_popup_layout, null);
contentView.setFocusable(true);
contentView.setFocusableInTouchMode(true);
RecyclerView shareRecyclerView = contentView.findViewById(R.id.share_rv);
shareRecyclerView.setPadding(DisplayUtils.dip2px(mContext, 20), DisplayUtils.dip2px(mContext, 10), DisplayUtils.dip2px(mContext, 20), 0);
//RecyclerView禁止滑动
GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, 4) {
@Override
public boolean canScrollVertically() {
return false;
}
};
shareRecyclerView.setLayoutManager(gridLayoutManager);
ShareRecyclerViewAdapter shareRecyclerViewAdapter = new ShareRecyclerViewAdapter();
shareRecyclerView.setAdapter(shareRecyclerViewAdapter);
shareRecyclerViewAdapter.setOnItemClickListener(position -> {
if ("取消".equals(arrLabel[position])) {
function.invoke();
}
});
if (mShareType == ShareType.shareGh) {
RelativeLayout layout = (RelativeLayout) view;
layout.addView(contentView);
arrLabel[6] = "邮件";
arrLogo[6] = R.drawable.share_email_logo;
arrLabel[7] = "复制链接";
arrLogo[7] = R.drawable.share_copyfont_logo;
return;
} else {
arrLabel[6] = "复制链接";
arrLogo[6] = R.drawable.share_copyfont_logo;
arrLabel[7] = "取消";
arrLogo[7] = R.drawable.share_cancel_logo;
}
popupWindow = new PopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT
, LinearLayout.LayoutParams.MATCH_PARENT, true);
popupWindow.setAnimationStyle(R.style.mypopwindow_anim_style);
//解决PopupWindow无法覆盖状态栏
popupWindow.setClippingEnabled(false);
try {
popupWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);
} catch (Exception e) {
e.printStackTrace();
}
contentView.setOnClickListener(v -> popupWindow.dismiss());
contentView.setOnKeyListener((v, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.getRepeatCount() == 0
&& popupWindow != null
&& popupWindow.isShowing()) {
function.invoke();
popupWindow.dismiss();
}
return false;
});
}
public void showShareWindows(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareType shareType) {
if (activity.isFinishing()) return;
@ -298,7 +372,7 @@ public class ShareUtils {
int dimension = Math.min(bitmap.getWidth(), bitmap.getHeight());
bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension);
}
Bitmap compressBp = compressBitmap(bitmap);
if (mShareType == ShareType.askNormal || mShareType == ShareType.askInvite) {
msg.thumbData = ImageUtils.bmpToByteArray(compressBp, true);
@ -520,37 +594,56 @@ public class ShareUtils {
private class ShareRecyclerViewAdapter extends RecyclerView.Adapter<ShareRecyclerViewAdapter.ViewHolder> {
private OnItemClickListener listener;
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.share_popup_item, parent, false);
return new ViewHolder(view);
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.shareLogo.setImageResource(arrLogo[position]);
holder.shareLabel.setText(arrLabel[position]);
holder.itemView.setOnClickListener(v -> {
if (mShareType == ShareUtils.ShareType.shareGh) {
MtaHelper.onEvent("我的光环_新", "分享光环", arrLabel[position]);
}
if (listener != null) {
listener.onItemClick(holder.getAdapterPosition());
}
switch (holder.getPosition()) {
case 0:
MtaHelper.onEvent("内容分享", "微信好友", mTitle);
wechatShare();
break;
case 1:
MtaHelper.onEvent("内容分享", "微信朋友圈", mTitle);
wechatMomentsShare();
break;
case 2:
MtaHelper.onEvent("内容分享", "QQ好友", mTitle);
qqShare();
break;
case 3:
MtaHelper.onEvent("内容分享", "QQ空间", mTitle);
qZoneShare();
break;
case 4:
MtaHelper.onEvent("内容分享", "新浪微博", mTitle);
sinaWeiboShare();
break;
case 5:
MtaHelper.onEvent("内容分享", "短信", mTitle);
shortMessageShare();
break;
case 6:
MtaHelper.onEvent("内容分享", "复制链接", mTitle);
if (mShareType == ShareType.askInvite) {
copyLink(mTitle + " - 光环助手" + shareUrl);
} else if (mShareType == ShareType.askNormal) {
@ -597,4 +690,8 @@ public class ShareUtils {
}
}
interface OnItemClickListener {
void onItemClick(int position);
}
}

View File

@ -0,0 +1,42 @@
package com.gh.common.util;
import com.github.piasy.biv.loader.ImageLoader;
import java.io.File;
public class SimpleImageLoader implements ImageLoader.Callback {
@Override
public void onCacheHit(int imageType, File image) {
}
@Override
public void onCacheMiss(int imageType, File image) {
}
@Override
public void onStart() {
}
@Override
public void onProgress(int progress) {
}
@Override
public void onFinish() {
}
@Override
public void onSuccess(File image) {
}
@Override
public void onFail(Exception error) {
}
}

View File

@ -83,6 +83,16 @@ object SPUtils {
}
}
@JvmStatic
fun setStringSet(key: String, values: Set<String>) {
sp.edit().putStringSet(key, values).apply()
}
@JvmStatic
fun getStringSet(key: String): Set<String> {
return sp.getStringSet(key, HashSet())?: HashSet()
}
@JvmStatic
fun remove(key: String) {
val editor = sp.edit()

View File

@ -1,36 +1,39 @@
package com.gh.common.util
import android.content.Context
import com.ss.android.common.applog.TeaAgent
import com.ss.android.common.applog.TeaConfigBuilder
import com.ss.android.common.lib.EventUtils
import com.bytedance.applog.AppLog
import com.bytedance.applog.GameReportHelper
import com.bytedance.applog.InitConfig
import com.bytedance.applog.util.UriConfig
import com.gh.common.exposure.meta.MetaUtil
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
/**
* 今日头条的激活统计 SDK https://gitlab.ghzs.com/pm/halo-app-issues/issues/567
*
* 更新 SDK https://gitlab.ghzs.com/pm/halo-app-issues/issues/743
*/
object TeaHelper {
@JvmStatic
fun init(context: Context, channel: String) {
TeaAgent.init(TeaConfigBuilder.create(context)
.setAppName("guanghuan1")
.setChannel(channel)
.setAid(163824)
.createTeaConfig()
)
val config = InitConfig("163824", channel)
config.setUriConfig(UriConfig.DEFAULT)
config.appName = "guanghuan1"
config.setEnablePlay(true)
AppLog.setEnableLog(false)
AppLog.init(context, config)
EventUtils.setRegister("mobile", true)
EventUtils.setPurchase(null, null, null, 0, null, null, true, 1)
}
AppLog.setOaidObserver {
HaloApp.getInstance().oaid = it.id
Utils.log("oaid is $it.id")
MetaUtil.refreshMeta()
}
@JvmStatic
fun onResume(context: Context) {
TeaAgent.onResume(context)
}
@JvmStatic
fun onPause(context: Context) {
TeaAgent.onPause(context)
// gameReportHelper ?!
GameReportHelper.onEventRegister("wechat", true)
GameReportHelper.onEventPurchase("gift", "flower", "008", 1, "wechat", "¥", true, 1)
}
}

View File

@ -62,6 +62,34 @@ object TextHelper {
}
}
//限制最大长度(空格不算入字数判断)-Toast弹窗提示
@JvmStatic
fun getFilterIgnoreBlank(maxLength: Int, msg: String): InputFilter {
return InputFilter { source, start, end, dest, dstart, dend ->
val newMaxLength = maxLength + getBlankCount(source.toString()) + getBlankCount(dest.toString())
val keep = newMaxLength - (dest.length - (dend - dstart))
if (keep < end - start) {
ToastUtils.showToast(msg)
}
when {
keep <= 0 -> ""
keep >= end - start -> null
else -> source.subSequence(start, start + keep)
}
}
}
private fun getBlankCount(text: String): Int {
var blankCount = 0
val toCharArray = text.toCharArray()
toCharArray.forEach {
if (it == ' ') {
blankCount++
}
}
return blankCount
}
@JvmStatic
fun highlightTextThatIsWrappedInsideWrapperByDefault(textView: TextView, text: String) {
textView.text = getHighlightedSpannableStringThatIsWrappedInsideWrapper(textView.context, text, "###", R.color.theme, object : SimpleCallback<String> {
@ -156,7 +184,6 @@ object TextHelper {
* [amwayStyle] 是否为安利墙列表样式,安利墙列表样式与其它地方略有不同
*/
fun getCommentLabelSpannableStringBuilder(comment: CharSequence,
lineFeed: String = "\n",
amwayStyle: Boolean = false,
tagStrokeColor: String = "#FFDAA2",
tagTextColor: String = "#FF9B06"): SpannableStringBuilder {
@ -166,13 +193,14 @@ object TextHelper {
splits.forEachIndexed { index, s ->
if (index != 0) {
val item = "<tag>$s"
val pattern = Pattern.compile("<tag>(\\S+)</tag>(\\S+)")
val pattern = Pattern.compile("<tag>(\\S+)</tag>([\\S,\n]+)")
val matcher = pattern.matcher(item)
if (matcher.find()) {
val label = matcher.group(1)
val content = matcher.group(2)
// val content = matcher.group(2) //不知为什么这里正则不能匹配颜文字,所以就用字符串裁剪。。。
var content = item.substring(item.indexOf("</tag>") + 6)
if (index == splits.size - 1) content += " "
val newLabel = " $label "
val newContent = if (index != splits.size - 1) "$content$lineFeed" else content
contents.append(newLabel)
contents.setSpan(RelativeSizeSpan(0.8f), count, count + newLabel.length - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
contents.setSpan(
@ -181,9 +209,12 @@ object TextHelper {
count + newLabel.length - 1,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
count += newLabel.length
contents.append(newContent)
count += newContent.length
contents.append(content)
count += content.length
}
} else {
contents.append(s)
count += s.length
}
}
return contents

View File

@ -0,0 +1,22 @@
package com.gh.common.util
import java.text.SimpleDateFormat
import java.util.*
object TimeUtils {
/**
* 获取今天日期
*/
@JvmStatic
fun getToday(): String {
var date = Date()
val calendar = GregorianCalendar()
calendar.time = date
//把日期往后增加一天.整数往后推,负数往前移动
calendar.add(GregorianCalendar.DATE, 0)
date = calendar.time
val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
return formatter.format(date)
}
}

View File

@ -1,7 +1,5 @@
package com.gh.common.util;
import androidx.collection.ArrayMap;
import android.text.TextUtils;
import com.gh.common.constant.Constants;
@ -10,6 +8,8 @@ import com.halo.assistant.HaloApp;
import java.util.regex.Pattern;
import androidx.collection.ArrayMap;
public class TimestampUtils {
// 基准时间
@ -29,6 +29,7 @@ public class TimestampUtils {
intervalMap.put(".*columns.*", 10);
intervalMap.put(".*games.*", 15);
intervalMap.put(".*articles.*", 20);
intervalMap.put(".*halo_addons.*", 10);
}
private static void initCDMap() {
@ -37,6 +38,7 @@ public class TimestampUtils {
cdMap.put(".*columns.*", Constants.GAME_CD);
cdMap.put(".*games.*", Constants.GAME_CD);
cdMap.put(".*articles.*", Constants.NEWS_CD);
cdMap.put(".*halo_addons.*", Constants.ADDONS_CD);
}
/*

View File

@ -18,6 +18,7 @@ import okhttp3.MultipartBody
import okhttp3.ResponseBody
import org.json.JSONObject
import java.io.File
import java.net.URLEncoder
import java.util.*
@ -185,14 +186,14 @@ object UploadImageUtils {
* 上传图片,每成功一个就回调
*/
@SuppressLint("CheckResult")
fun uploadImageListOneByOne(type: UploadType, imgs: List<String>, compressGif: Boolean, listener: OnUploadImageListCountListener):Disposable?{
fun uploadImageListOneByOne(type: UploadType, imgs: List<String>, compressGif: Boolean, listener: OnUploadImageListCountListener): Disposable? {
var subscription: Disposable? = null
Observable.create(ObservableOnSubscribe<Map<String, String>> {
//val compressList = compressImageList(imgs, compressGif)
for (img in imgs) {
if (subscription?.isDisposed == true) return@ObservableOnSubscribe
val file=File(img)
val file = File(img)
val requestBody = FileRequestBody(file, object : RetrofitCallback<ResponseBody>() {
override fun onProgress(total: Long, progress: Long) {
@ -274,7 +275,7 @@ object UploadImageUtils {
if (options.outMimeType.contains("gif") && !file.name.toLowerCase().contains(".gif".toLowerCase())) {
return System.currentTimeMillis().toString() + ".gif"
}
return file.name
return URLEncoder.encode(file.name, "utf-8")
}
interface OnUploadImageListener {
@ -288,8 +289,9 @@ object UploadImageUtils {
fun onError() // 全部上传失败时回调
fun onProgress(total: Long, progress: Long)
}
interface OnUploadImageListCountListener{
fun onSuccess(map:Map<String, String>)//上传成功一个回调
interface OnUploadImageListCountListener {
fun onSuccess(map: Map<String, String>)//上传成功一个回调
fun onFinish()//全部上传成功回调
fun onError() // 全部上传失败时回调
}

View File

@ -0,0 +1,269 @@
@file:Suppress("DEPRECATED_IDENTITY_EQUALS")
package com.gh.common.util
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Activity
import android.app.AppOpsManager
import android.app.AppOpsManager.MODE_ALLOWED
import android.app.AppOpsManager.OPSTR_GET_USAGE_STATS
import android.app.usage.UsageEvents
import android.app.usage.UsageStatsManager
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Process
import android.preference.PreferenceManager
import android.provider.Settings
import androidx.annotation.RequiresApi
import com.gh.common.util.UsageStatsHelper.getDataByUsageEvents
import com.gh.common.util.UsageStatsHelper.getDataByUsageStats
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.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import okhttp3.ResponseBody
import org.json.JSONArray
import org.json.JSONObject
import java.util.*
/**
* 参考资料: https://developer.android.com/reference/android/app/usage/UsageStatsManager
*
* queryUsageStats 无法准确获取设定时间内的使用情况,所以以下统计有两个策略(但依然无法解决queryUsageStats初始取值问题)
*
* [getDataByUsageStats]:用于获取时间跨度较大的数据(至少跨度一天)
* [getDataByUsageEvents]:用于获取时间跨度较小的数据(只用于获取当天数据)
*
* 详情可见https://stackoverflow.com/questions/36238481/android-usagestatsmanager-not-returning-correct-daily-results
*
*/
object UsageStatsHelper {
const val USAGE_STATUS_REQUEST_CODE = 233
const val USAGE_STATUS_SP_KEY = "usage_status_sp_key"
private val mApi = RetrofitManager.getInstance(HaloApp.getInstance().application).api
private val mPreference = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().application)
/**
* 一般用于获取时间跨度较大的数据
*
* 当天数据获取是有问题的
* 例如: 设置起始时间为上午10点当时返回的数据还是包括更前的数据例如9点
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
private fun getDataByUsageStats(lastPostTime: Long): JSONArray? {
val usageStatsManager = HaloApp
.getInstance().application
.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
val usageStatsMap = usageStatsManager.queryAndAggregateUsageStats(
lastPostTime,
System.currentTimeMillis()) ?: return null
val postBody = JSONArray()
for (entry in usageStatsMap) {
if (entry.value.totalTimeInForeground != 0L) {
val jsonObject = JSONObject()
jsonObject.put("package", entry.key)
jsonObject.put("duration", (entry.value.totalTimeInForeground / 1000))
postBody.put(jsonObject)
debugOnly {
Utils.log("UsageStats post log==>" + entry.key + ":" + (entry.value.totalTimeInForeground / 1000))
}
}
}
return postBody
}
/**
* 一般用于获取时间跨度较小的数据
* 在此功能只用来获取当天数据(queryEvents 获取的数据只保留几天内的数据)
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
private fun getDataByUsageEvents(startTime: Long): JSONArray? {
val mUsageStatsManager = HaloApp
.getInstance()
.application
.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
val usageEvents = mUsageStatsManager.queryEvents(startTime, System.currentTimeMillis())
val allEvents = ArrayList<UsageEvents.Event>()
var currentEvent: UsageEvents.Event
while (usageEvents.hasNextEvent()) {
currentEvent = UsageEvents.Event()
usageEvents.getNextEvent(currentEvent)
if (currentEvent.eventType == UsageEvents.Event.MOVE_TO_FOREGROUND
|| currentEvent.eventType == UsageEvents.Event.MOVE_TO_BACKGROUND) {
allEvents.add(currentEvent)
}
}
val pakAndTime = HashMap<String, Long>()
for (i in 0 until allEvents.size - 1) {
val curEvent = allEvents[i]
val nextEvent = allEvents[i + 1]
if (curEvent.eventType == UsageEvents.Event.MOVE_TO_FOREGROUND
&& nextEvent.eventType == UsageEvents.Event.MOVE_TO_BACKGROUND
&& curEvent.className == nextEvent.className) {
val diff = nextEvent.timeStamp - curEvent.timeStamp
if (pakAndTime[curEvent.packageName] == null) {
pakAndTime[curEvent.packageName] = diff
} else {
pakAndTime[curEvent.packageName] = pakAndTime[curEvent.packageName]!! + diff
}
}
}
val postBody = JSONArray()
for (pkg in pakAndTime.keys) {
val totalTime = pakAndTime[pkg] ?: return null
val jsonObject = JSONObject()
jsonObject.put("package", pkg)
jsonObject.put("duration", (totalTime / 1000))
postBody.put(jsonObject)
Utils.log("UsageStats getDataByUsageEvents->" + pkg + " :" + (totalTime / 1000))
}
return postBody
}
/**
* 第一次统计默认起始时间
*/
private fun getDefaultBeginTime(): Long {
val calendar = Calendar.getInstance()
calendar.add(Calendar.YEAR, -5)
return calendar.timeInMillis
}
@SuppressLint("CheckResult")
@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
private fun postUsageStats(beginTime: Long) {
debugOnly {
Utils.log("UsageStats->beginTime:$beginTime endTime:" + System.currentTimeMillis())
}
val postBody = if (isSameDay(beginTime, System.currentTimeMillis())) {
getDataByUsageEvents(beginTime)
} else {
getDataByUsageStats(beginTime)
}
if (postBody == null || postBody.length() == 0) {
debugOnly {
Utils.log("UsageStats: 没有可上传的数据")
}
return
}
val body = RequestBody.create(MediaType.parse("application/json"), postBody.toString())
mApi.postUsageStatus(body, UserManager.getInstance().userId)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
debugOnly {
Utils.log("UsageStats: 数据上传成功")
}
}
})
}
@JvmStatic
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
fun checkForPermission(): Boolean {
val appOps = HaloApp
.getInstance().application
.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
val mode = appOps.checkOpNoThrow(
OPSTR_GET_USAGE_STATS,
Process.myUid(),
HaloApp.getInstance().application.packageName)
return mode == MODE_ALLOWED
}
@JvmStatic
@SuppressLint("CheckResult")
fun checkAndPostUsageStats() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
debugOnly {
Utils.log("UsageStats checkAndPostUsageStats Android 版本小于22")
}
return
}
if (!checkForPermission()) {
debugOnly {
Utils.log("UsageStats checkAndPostUsageStats 没有授予权限")
}
return
}
if (!mPreference.getBoolean(USAGE_STATUS_SP_KEY, true)) {
debugOnly {
Utils.log("UsageStats checkAndPostUsageStats 有权限,但用户在设置关闭统计")
}
return
}
mApi.getUsageStatusUpdateTime(HaloApp.getInstance().gid)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
val body = JSONObject(data.string())
val lastPostTime = body.getLong("update_time") * 1000
val beginTime = if (lastPostTime == 0L) {
getDefaultBeginTime()
} else {
lastPostTime
}
postUsageStats(beginTime)
}
})
}
private fun isSameDay(timeA: Long, timeB: Long): Boolean {
if (timeA == timeB) {
return true
}
val calendarB = Calendar.getInstance()
calendarB.time = Date(timeB)
val calendarA = Calendar.getInstance()
calendarA.time = Date(timeA)
return (calendarB.get(Calendar.YEAR) === calendarA.get(Calendar.YEAR)
&& calendarB.get(Calendar.MONTH) === calendarA.get(Calendar.MONTH)
&& calendarB.get(Calendar.DATE) === calendarA.get(Calendar.DATE))
}
@JvmStatic
fun skipToUsageStats(context: Context, requestCode: Int = -1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (context is Activity && requestCode != -1) {
context.startActivityForResult(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS), requestCode)
} else {
context.startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS))
}
} else {
Utils.toast(context, "当前设备不支持查看应用使用情况")
}
}
}

View File

@ -0,0 +1,154 @@
package com.gh.common.view;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.animation.Animation;
import android.view.animation.CycleInterpolator;
import android.view.animation.TranslateAnimation;
import com.gh.gamecenter.R;
public class ClearEditTextNormal extends androidx.appcompat.widget.AppCompatEditText implements OnFocusChangeListener, TextWatcher {
/**
* 删除按钮的引用
*/
private Drawable mClearDrawable;
/**
* 控件是否有焦点
*/
private boolean hasFoucs;
public ClearEditTextNormal(Context context) {
this(context, null);
}
public ClearEditTextNormal(Context context, AttributeSet attrs) {
//这里构造方法也很重要不加这个很多属性不能再XML里面定义
this(context, attrs, android.R.attr.editTextStyle);
}
public ClearEditTextNormal(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
@SuppressWarnings("deprecation")
private void init() {
//获取EditText的DrawableRight,假如没有设置我们就使用默认的图片
mClearDrawable = getCompoundDrawables()[2];
if (mClearDrawable == null) {
// throw new NullPointerException("You can add drawableRight attribute in XML");
mClearDrawable = getResources().getDrawable(R.drawable.icon_close);
}
mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
//默认设置隐藏图标
setClearIconVisible(false);
//设置焦点改变的监听
setOnFocusChangeListener(this);
//设置输入框里面内容发生改变的监听
addTextChangedListener(this);
}
/**
* 因为我们不能直接给EditText设置点击事件所以我们用记住我们按下的位置来模拟点击事件
* 当我们按下的位置 在 EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 和
* EditText的宽度 - 图标到控件右边的间距之间我们就算点击了图标,竖直方向就没有考虑
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (getCompoundDrawables()[2] != null) {
boolean touchable = event.getX() > (getWidth() - getTotalPaddingRight())
&& (event.getX() < ((getWidth() - getPaddingRight())));
if (touchable) {
this.setText("");
}
}
}
return super.onTouchEvent(event);
}
/**
* 当ClearEditText焦点发生变化的时候判断里面字符串长度设置清除图标的显示与隐藏
*/
@Override
public void onFocusChange(View v, boolean hasFocus) {
this.hasFoucs = hasFocus;
if (hasFocus) {
setClearIconVisible(getText().length() > 0);
} else {
setClearIconVisible(false);
}
}
/**
* 设置清除图标的显示与隐藏调用setCompoundDrawables为EditText绘制上去
*
* @param visible
*/
public void setClearIconVisible(boolean visible) {
Drawable right = visible ? mClearDrawable : null;
setCompoundDrawables(getCompoundDrawables()[0],
getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
}
/**
* 当输入框里面内容发生变化的时候回调的方法
*/
@Override
public void onTextChanged(CharSequence s, int start, int count,
int after) {
if (hasFoucs) {
setClearIconVisible(s.length() > 0);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
/**
* 设置晃动动画
*/
public void setShakeAnimation() {
this.setAnimation(shakeAnimation(5));
}
/**
* 晃动动画
*
* @param counts 1秒钟晃动多少下
* @return
*/
public static Animation shakeAnimation(int counts) {
Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);
translateAnimation.setInterpolator(new CycleInterpolator(counts));
translateAnimation.setDuration(1000);
return translateAnimation;
}
}

View File

@ -30,6 +30,8 @@ public class CropImageBorderView extends View {
private Paint mPaint, mPaintRect;
private float mRatio = 1; // 宽高比
public CropImageBorderView(Context context) {
this(context, null);
}
@ -64,7 +66,8 @@ public class CropImageBorderView extends View {
// 计算矩形区域的宽度
mWidth = getWidth() - 2 * mHorizontalPadding;
// 计算距离屏幕垂直边界 的边距
mVerticalPadding = (getHeight() - mWidth) / 2;
mVerticalPadding = (getHeight() - (int) (mWidth * mRatio)) / 2;
// 绘制左边
canvas.drawRect(0, 0, mHorizontalPadding, getHeight()
@ -81,13 +84,12 @@ public class CropImageBorderView extends View {
// 绘制边框
canvas.drawRect(mHorizontalPadding, mVerticalPadding,
mHorizontalPadding + mWidth, mVerticalPadding + mWidth, mPaint);
mHorizontalPadding + mWidth, getHeight() - mVerticalPadding, mPaint);
}
public void setHorizontalPadding(int mHorizontalPadding) {
public void setHorizontalPadding(int mHorizontalPadding, float ratio) {
this.mHorizontalPadding = mHorizontalPadding;
this.mRatio = ratio;
}
}

View File

@ -8,8 +8,6 @@ import android.util.TypedValue;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.lightgame.utils.Utils;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
@ -21,6 +19,8 @@ public class CropImageCustom extends RelativeLayout {
private int mHorizontalPadding = 20;
private float mRatio = 1F; // 裁剪比例
public CropImageCustom(Context context, AttributeSet attrs) {
super(context, attrs);
@ -38,17 +38,15 @@ public class CropImageCustom extends RelativeLayout {
mHorizontalPadding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, mHorizontalPadding, getResources()
.getDisplayMetrics());
mZoomImageView.setHorizontalPadding(mHorizontalPadding);
mClipImageView.setHorizontalPadding(mHorizontalPadding);
mZoomImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
mClipImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
}
/**
* 对外公布设置边距的方法,单位为dp
*
* @param mHorizontalPadding
*/
public void setHorizontalPadding(int mHorizontalPadding) {
this.mHorizontalPadding = mHorizontalPadding;
public void setCropRatio(float ratio) {
this.mRatio = ratio;
mZoomImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
mClipImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
}
/**
@ -60,6 +58,7 @@ public class CropImageCustom extends RelativeLayout {
return mZoomImageView.clip();
}
// 用户头像压缩规则
public boolean savePicture(String path) {
float limitSize = 900;
int quality = 90;

View File

@ -6,7 +6,6 @@ import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import androidx.appcompat.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
@ -17,6 +16,8 @@ import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver;
import androidx.appcompat.widget.AppCompatImageView;
@SuppressWarnings("deprecation")
public class CropImageZoomView extends AppCompatImageView implements
OnScaleGestureListener, OnTouchListener,
@ -60,6 +61,10 @@ public class CropImageZoomView extends AppCompatImageView implements
*/
private int mVerticalPadding;// ——屏幕顶部离截图区的高度
private float mRatio = 1; // 宽高比
private int mWidth;
public CropImageZoomView(Context context) {
this(context, null);
}
@ -290,8 +295,10 @@ public class CropImageZoomView extends AppCompatImageView implements
Drawable d = getDrawable();
if (d == null)
return;
mWidth = getWidth() - 2 * mHorizontalPadding;
// 垂直方向的边距
mVerticalPadding = (getHeight() - (getWidth() - 2 * mHorizontalPadding)) / 2;
mVerticalPadding = (getHeight() - (int) (mWidth * mRatio)) / 2;
int width = getWidth();
int height = getHeight();
@ -339,13 +346,16 @@ public class CropImageZoomView extends AppCompatImageView implements
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
draw(canvas);
return Bitmap.createBitmap(bitmap, mHorizontalPadding,
mVerticalPadding, getWidth() - 2 * mHorizontalPadding,
getWidth() - 2 * mHorizontalPadding);
return Bitmap.createBitmap(bitmap,
mHorizontalPadding,
mVerticalPadding,
mWidth,
(getHeight() - mVerticalPadding * 2));
}
public void setHorizontalPadding(int mHorizontalPadding) {
public void setHorizontalPadding(int mHorizontalPadding, float ratio) {
this.mHorizontalPadding = mHorizontalPadding;
this.mRatio = ratio;
}
/**

View File

@ -15,12 +15,12 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ProgressBar;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import com.gh.common.util.DisplayUtils;
import com.gh.gamecenter.R;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
public class DownloadProgressBar extends ProgressBar {
public static final int MAX_LENGTH = 1000;
public static final int DOWNLOAD_NORMAL_STYLE = 0;
@ -39,7 +39,8 @@ public class DownloadProgressBar extends ProgressBar {
DOWNLOADING_NORMAL,
DOWNLOADING_PLUGIN,
RESERVABLE,
RESERVED
RESERVED,
H5_GAME
}
private PorterDuffXfermode mDuffXFerMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
@ -165,6 +166,7 @@ public class DownloadProgressBar extends ProgressBar {
case NORMAL:
case NONE_WITH_HINT:
case INSTALL_NORMAL:
case H5_GAME:
switch (mDownloadStyle) {
case DOWNLOAD_RECT_STYLE:
setProgressDrawable(getResources().getDrawable(R.drawable.detail_download_normal_rect_style));

View File

@ -0,0 +1,142 @@
package com.gh.common.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
import androidx.annotation.ColorRes;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
public class GridSpacingItemColorDecoration extends RecyclerView.ItemDecoration {
private int dividerWidth;
private int dividerHeight;
private int dividerWidthTop;
private int dividerWidthBot;
private Paint dividerPaint;
/**
* @param dividerDp 分割块宽高,单位:dp
* @param dividerColor 分割块颜色
*/
public GridSpacingItemColorDecoration(Context context, int dividerDp, @ColorRes int dividerColor) {
this(context, dividerDp, dividerDp, dividerColor);
}
/**
* @param dividerWidthDp 分割块宽,单位:dp
* @param dividerHeightDp 分割块高,单位:dp
* @param dividerColor 分割块颜色
*/
public GridSpacingItemColorDecoration(Context context, int dividerWidthDp, int dividerHeightDp, @ColorRes int dividerColor) {
this.dividerPaint = new Paint();
this.dividerPaint.setColor(ContextCompat.getColor(context, dividerColor));
this.dividerWidth = dip2px(context, dividerWidthDp);
this.dividerHeight = dip2px(context, dividerHeightDp);
this.dividerWidthTop = dividerHeight / 2;
this.dividerWidthBot = dividerHeight - dividerWidthTop;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
drawHorizontal(c, parent);
drawVertical(c, parent);
}
private void drawHorizontal(Canvas c, RecyclerView parent) {
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
if (!isLastRaw(parent, i, getSpanCount(parent), childCount)) {//最后一行不设置颜色
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getLeft() - params.leftMargin;
final int right = !isLastColum(parent, i, getSpanCount(parent)) ? child.getRight() + params.rightMargin
+ dividerWidth : child.getRight() + params.rightMargin;
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + dividerHeight;
c.drawRect(left, top, right, bottom, dividerPaint);
}
}
}
private void drawVertical(Canvas c, RecyclerView parent) {
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
if (!isLastColum(parent, i, getSpanCount(parent)) && i != childCount - 1) {//最后一列和最后个item后面不设置颜色
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getTop() - params.topMargin;
final int bottom = child.getBottom() + params.bottomMargin;
final int left = child.getRight() + params.rightMargin;
final int right = left + dividerWidth;
c.drawRect(left, top, right, bottom, dividerPaint);
}
}
}
@Override
public void getItemOffsets(Rect outRect, View child, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, child, parent, state);
int spanCount = getSpanCount(parent);
int pos = parent.getChildAdapterPosition(child);
int childCount = parent.getAdapter().getItemCount();
int column = (pos) % spanCount;// 计算这个child 处于第几列
outRect.top = isFirstRaw(parent, pos, spanCount) ? 0 : dividerWidthTop;
outRect.bottom = isLastRaw(parent, pos, spanCount, childCount) ? 0 : dividerWidthBot;
outRect.left = (column * dividerWidth / spanCount);
outRect.right = dividerWidth - (column + 1) * dividerWidth / spanCount;
}
private boolean isLastColum(RecyclerView parent, int pos, int spanCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
return layoutManager instanceof GridLayoutManager && (pos + 1) % spanCount == 0;
}
private boolean isFirstRaw(RecyclerView parent, int pos, int spanCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
return layoutManager instanceof GridLayoutManager && pos < spanCount;
}
private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
int childCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
int rawChildCount = childCount - childCount % spanCount;
if (rawChildCount == childCount) {
return pos >= rawChildCount - spanCount;
}
return pos >= rawChildCount;
}
return false;
}
private int getSpanCount(RecyclerView parent) {
// 列数
int spanCount = -1;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
spanCount = ((StaggeredGridLayoutManager) layoutManager)
.getSpanCount();
}
return spanCount;
}
private int dip2px(Context context, float dpValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}

View File

@ -0,0 +1,82 @@
package com.gh.common.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import com.gh.gamecenter.R;
import androidx.annotation.Nullable;
public class LongPressView extends View {
private int mLastMotionX, mLastMotionY;
// 是否移动了
private boolean isMoved;
// 是否释放了
private boolean isReleased;
// 计数器防止多次点击导致最后一次形成longpress的时间变短
private int mCounter;
// 长按的runnable
private Runnable mLongPressRunnable;
// 移动的阈值
private static final int TOUCH_SLOP = 60;
private int longPressTimeout = ViewConfiguration.getLongPressTimeout();
public LongPressView(Context context) {
super(context);
}
public LongPressView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public LongPressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LongPressViewStyle);
longPressTimeout = ta.getInteger(R.styleable.LongPressViewStyle_timeout, longPressTimeout);
ta.recycle();
}
mLongPressRunnable = () -> {
mCounter--;
if (mCounter > 0 || isReleased || isMoved)
return;
performLongClick();// 回调长按事件
};
}
public boolean dispatchTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastMotionX = x;
mLastMotionY = y;
mCounter++;
isReleased = false;
isMoved = false;
postDelayed(mLongPressRunnable, longPressTimeout);
break;
case MotionEvent.ACTION_MOVE:
if (isMoved)
break;
if (Math.abs(mLastMotionX - x) > TOUCH_SLOP
|| Math.abs(mLastMotionY - y) > TOUCH_SLOP) {
isMoved = true;
}
break;
case MotionEvent.ACTION_UP:
isReleased = true;
break;
}
return true;
}
}

View File

@ -1,10 +1,8 @@
package com.gh.common.view
import android.annotation.TargetApi
import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.view.WindowInsets
import android.widget.FrameLayout
class MaterializedFrameLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
@ -13,13 +11,18 @@ class MaterializedFrameLayout @JvmOverloads constructor(context: Context, attrs:
/**
* 将 windowInsets 传递给子 view [https://medium.com/androiddevelopers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec#.raoa9t506]
*/
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
val childCount = childCount
for (index in 0 until childCount) {
getChildAt(index).dispatchApplyWindowInsets(insets)
override fun onAttachedToWindow() {
super.onAttachedToWindow()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setOnApplyWindowInsetsListener { _, insets ->
val childCount = childCount
for (index in 0 until childCount) {
getChildAt(index).dispatchApplyWindowInsets(insets)
}
insets
}
}
return insets
}
}

View File

@ -1,10 +1,8 @@
package com.gh.common.view
import android.annotation.TargetApi
import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.view.WindowInsets
import android.widget.RelativeLayout
class MaterializedRelativeLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
@ -13,13 +11,18 @@ class MaterializedRelativeLayout @JvmOverloads constructor(context: Context, att
/**
* 将 windowInsets 传递给子 view [https://medium.com/androiddevelopers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec#.raoa9t506]
*/
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
val childCount = childCount
for (index in 0 until childCount) {
getChildAt(index).dispatchApplyWindowInsets(insets)
override fun onAttachedToWindow() {
super.onAttachedToWindow()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setOnApplyWindowInsetsListener { _, insets ->
val childCount = childCount
for (index in 0 until childCount) {
getChildAt(index).dispatchApplyWindowInsets(insets)
}
insets
}
}
return insets
}
}

View File

@ -1,14 +1,10 @@
package com.gh.common.view
import android.app.Activity
import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.view.KeyCharacterMap
import android.view.KeyEvent
import android.view.View
import android.view.ViewConfiguration
import com.gh.common.util.DisplayUtils
/**
* 导航栏占位 View
@ -18,44 +14,8 @@ class NavigationBarView @JvmOverloads constructor(context: Context?, attrs: Attr
val height = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
0
} else {
retrieveNavigationHeight()
DisplayUtils.retrieveNavigationHeight(context)
}
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height)
}
// TODO 将这部分移到通用方法去
private fun hasSoftKeys(): Boolean {
if (context !is Activity) return false
val hasSoftwareKeys: Boolean
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
val d = (context as Activity).windowManager.defaultDisplay
val realDisplayMetrics = DisplayMetrics()
d.getRealMetrics(realDisplayMetrics)
val realHeight = realDisplayMetrics.heightPixels
val realWidth = realDisplayMetrics.widthPixels
val displayMetrics = DisplayMetrics()
d.getMetrics(displayMetrics)
val displayHeight = displayMetrics.heightPixels
val displayWidth = displayMetrics.widthPixels
hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0
} else {
val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey()
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
hasSoftwareKeys = !hasMenuKey && !hasBackKey
}
return hasSoftwareKeys
}
private fun retrieveNavigationHeight(): Int {
val resources = context.resources
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
return if (resourceId > 0 && hasSoftKeys()) resources.getDimensionPixelSize(resourceId) else 0
}
}

View File

@ -0,0 +1,82 @@
package com.gh.common.view
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.base.BaseRecyclerViewHolder
import com.gh.base.fragment.BaseDialogFragment
import com.gh.common.util.fromHtml
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.DialogReserveBinding
import com.gh.gamecenter.databinding.DialogReserveItemBinding
import com.gh.gamecenter.entity.SimpleGameEntity
import com.gh.gamecenter.mygame.MyGameActivity
import com.lightgame.adapter.BaseRecyclerAdapter
class ReserveDialog : BaseDialogFragment() {
private lateinit var mReserveList: List<SimpleGameEntity>
private var mDismissListener: (() -> Unit)? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding: DialogReserveBinding = DataBindingUtil.inflate(inflater, R.layout.dialog_reserve, container, false)
binding.title.text = resources.getString(R.string.dialog_reserve_title, mReserveList.size).fromHtml()
binding.more.visibility = if (mReserveList.size > 4) {
View.VISIBLE
} else View.GONE
binding.more.setOnClickListener {
val intent = MyGameActivity.getIntentWithConfig(requireContext(), 2)
startActivity(intent)
dismiss()
}
binding.recyclerView.layoutManager = if (mReserveList.size > 4) {
GridLayoutManager(context, 4)
} else {
FixLinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
}
binding.recyclerView.adapter = object : BaseRecyclerAdapter<ReserveDialogItemViewHolder>(context) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ReserveDialogItemViewHolder {
val inflate = mLayoutInflater.inflate(R.layout.dialog_reserve_item, parent, false)
return ReserveDialogItemViewHolder(DialogReserveItemBinding.bind(inflate))
}
override fun getItemCount(): Int {
return if (mReserveList.size > 4) 4 else mReserveList.size
}
override fun onBindViewHolder(holder: ReserveDialogItemViewHolder, position: Int) {
val entity = mReserveList[position]
holder.binding.game = entity
holder.itemView.setOnClickListener {
GameDetailActivity.startGameDetailActivity(mContext, entity.id, "(预约弹窗)")
dismiss()
}
}
}
dialog?.setCanceledOnTouchOutside(true)
return binding.root
}
fun setOnDismissListener(dismissListener: () -> Unit) {
mDismissListener = dismissListener
}
override fun onDestroy() {
super.onDestroy()
mDismissListener?.invoke()
}
companion object {
@JvmStatic
fun getInstance(reserveList: List<SimpleGameEntity>) = ReserveDialog().apply { mReserveList = reserveList }
}
}
class ReserveDialogItemViewHolder(val binding: DialogReserveItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)

View File

@ -56,6 +56,9 @@ public class RichEditor extends WebView {
public static String IMAGE_FLAG_DEFAULT = ",default";
public static String IMAGE_FLAG_THUMBNAIL = ",thumbnail";
private boolean mContentOwner;
private boolean mInputEnabled;
private int mDefaultImageWidth;
private int mThumbnailImageWidth;
@ -227,7 +230,7 @@ public class RichEditor extends WebView {
// getSettings().setBlockNetworkImage(true); // 先不加载网络图片,因为后面有资源替换操作防止流量无故丢失
try {
exec("javascript:RE.setHtml('" + URLEncoder.encode(contents, "UTF-8") + "');");
exec("javascript:RE.setHtmlByVideoStatus('" + URLEncoder.encode(contents, "UTF-8") + "');");
if (isLoadTbImage) {
if (!NetworkUtils.isWifiOr4GConnected(getContext())) {
@ -259,8 +262,8 @@ public class RichEditor extends WebView {
// 转译
String brief = entity.getBrief();
String title = entity.getTitle();
brief = TextUtils.isEmpty(brief) ? "" : brief.replaceAll("[\\x00-\\x1F\\x7F]", "");
title = TextUtils.isEmpty(title) ? "" : title.replaceAll("[\\x00-\\x1F\\x7F]", "");
brief = TextUtils.isEmpty(brief) ? "" : brief.replaceAll("[\\x00-\\x1F\\x7F]", "").replace("\\", "");
title = TextUtils.isEmpty(title) ? "" : title.replaceAll("[\\x00-\\x1F\\x7F]", "").replace("\\", "");
entity.setBrief(TextUtils.htmlEncode(brief));
entity.setTitle(TextUtils.htmlEncode(title));
@ -273,15 +276,16 @@ public class RichEditor extends WebView {
JSONObject object = new JSONObject();
object.put("poster", entity.getPoster());
object.put("url", entity.getUrl());
object.put("duration", formatDuration(entity.getLength()));
object.put("duration", formatVideoDuration(entity.getLength()));
object.put("id", entity.getId());
object.put("status", entity.getStatus());
exec("javascript:RE.insertCustomVideo('" + object.toString() + "');");
} catch (Exception e) {
e.printStackTrace();
}
}
private String formatDuration(long seconds) {
public static String formatVideoDuration(long seconds) {
long absSeconds = Math.abs(seconds);
@SuppressLint("DefaultLocale") String positive = String.format(
"%02d:%02d",
@ -415,6 +419,7 @@ public class RichEditor extends WebView {
}
public void setInputEnabled(Boolean inputEnabled) {
mInputEnabled = inputEnabled;
exec("javascript:RE.setInputEnabled(" + inputEnabled + ")");
}
@ -574,6 +579,9 @@ public class RichEditor extends WebView {
}
}
public void setContentOwner(boolean contentOwner) {
this.mContentOwner = contentOwner;
}
public interface WebChromeClientListener {
void onPageFinished(WebView view, String url);
@ -583,9 +591,29 @@ public class RichEditor extends WebView {
class NativeCallBack {
/**
* true:测试接口
* false:正式接口
*/
@JavascriptInterface
public boolean isNativeBuildDebug() {
return "internal".equals(BuildConfig.FLAVOR);
}
/**
* 只在插入HTML之后才有效
*/
@JavascriptInterface
public boolean isContentOwner() {
return mContentOwner;
}
/**
* 当前页面是不是编辑状态
*/
@JavascriptInterface
public boolean isInputEnabled() {
return mInputEnabled;
}
}
}

View File

@ -1,11 +1,11 @@
package com.gh.common.view
import androidx.databinding.DataBindingUtil
import android.os.Bundle
import android.preference.PreferenceManager
import android.view.LayoutInflater
import android.view.View
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.SP_LAST_OPENING_ID
@ -30,6 +30,8 @@ class WelcomeDialog : BaseDialogFragment() {
lateinit var binding: DialogWelcomeBinding
private var mDismissListener: (() -> Unit)? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mTimeHelper = TimeElapsedHelper(this)
@ -93,6 +95,10 @@ class WelcomeDialog : BaseDialogFragment() {
}
}
fun setOnDismissListener(dismissListener: () -> Unit) {
mDismissListener = dismissListener
}
override fun onDestroy() {
val type = if (mDismissByClickImage) {
"点击图片"
@ -108,6 +114,8 @@ class WelcomeDialog : BaseDialogFragment() {
putString(SP_LAST_OPENING_ID, mWelcomeEntity?.id)
putLong(SP_LAST_OPENING_TIME, mWelcomeEntity?.time!!)
}
mDismissListener?.invoke()
super.onDestroy()
}

View File

@ -1,296 +0,0 @@
package com.gh.common.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.net.Uri;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.gamecenter.eventbus.EBReuse;
import org.greenrobot.eventbus.EventBus;
/**
* Created by khy on 2016/10/26.
*/
public class ZoomSimpleDraweeView extends SimpleDraweeView {
private final float[] matrixValues = new float[9];
private ScaleGestureDetector mScaleDetector;
private GestureDetector mGestureDetector;
private float mCurrentScale = 1f;
private Matrix mCurrentMatrix;
private setOnSingleClickListener mClickListener;
private setOnLongClickListener mLongClickListener;
private float imgagePro = -1; // 图片宽高比
public ZoomSimpleDraweeView(Context context) {
super(context);
init();
}
private void init() {
mCurrentMatrix = new Matrix();
ScaleGestureDetector.OnScaleGestureListener scaleListener = new ScaleGestureDetector
.SimpleOnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scaleFactor = detector.getScaleFactor();
if (mCurrentScale < 4f || detector.getScaleFactor() < 1f) {
mCurrentScale *= scaleFactor;
mCurrentMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
invalidate();
}
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
super.onScaleEnd(detector);
if (mCurrentScale < 1f) {
reset();
}
checkBorder();
}
};
mScaleDetector = new ScaleGestureDetector(getContext(), scaleListener);
GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return super.onSingleTapUp(e);
}
@Override
public void onLongPress(MotionEvent e) {
super.onLongPress(e);
if (mLongClickListener != null) {
mLongClickListener.onLongClick();
}
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (mCurrentScale > 1f) {
mCurrentMatrix.postTranslate(-distanceX, -distanceY);
invalidate();
checkBorder();
}
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
final float x = e.getX();
final float y = e.getY();
float scaleSize; //扩大或缩小的倍数
if (mCurrentScale > 1.5f) { //缩小时直接回到原画大小
scaleSize = 0.5f;
ZoomSimpleDraweeView.this.post(new AutoScaleRunnable(mCurrentScale * scaleSize, getWidth() / 2f, getHeight() / 2f, false));
} else {
scaleSize = 2.0f;
ZoomSimpleDraweeView.this.post(new AutoScaleRunnable(mCurrentScale * scaleSize, x, y, true));
}
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (mClickListener != null) {
mClickListener.onClick();
}
return true;
}
};
mGestureDetector = new GestureDetector(getContext(), gestureListener);
}
/**
* 重置图片
*/
public void reset() {
mCurrentMatrix.reset();
mCurrentScale = 1f;
invalidate();
EventBus.getDefault().post(new EBReuse("isStopMove"));
}
/**
* 检查图片边界是否移到view以内
* 目的是让图片边缘不要移动到view里面
*/
private void checkBorder() {
RectF rectF = getDisplayRect(mCurrentMatrix);
boolean reset = false;
float dx = 0;
float dy = 0;
if (rectF.left > 0) {
dx = getLeft() - rectF.left;
reset = true;
}
if (rectF.top > 0) {
dy = getTop() - rectF.top;
reset = true;
}
if (rectF.right < getRight()) {
dx = getRight() - rectF.right;
reset = true;
}
if (rectF.bottom < getHeight()) {
dy = getHeight() - rectF.bottom;
reset = true;
}
if (reset) {
mCurrentMatrix.postTranslate(dx, dy);
invalidate();
}
if (dy == 0 && reset || mCurrentScale == 1f) {
EventBus.getDefault().post(new EBReuse("isStopMove"));
} else {
EventBus.getDefault().post(new EBReuse("isStartove"));
}
}
/**
* Helper method that maps the supplied Matrix to the current Drawable
*
* @param matrix - Matrix to map Drawable against
* @return RectF - Displayed Rectangle
*/
private RectF getDisplayRect(Matrix matrix) {
// int bottom;
// if (imgagePro != -1){
// bottom = (int) (getRight()*imgagePro);
// } else {
// bottom = getBottom();
// }
RectF rectF = new RectF(getLeft(), getTop(), getRight(), getBottom());
matrix.mapRect(rectF);
return rectF;
}
public ZoomSimpleDraweeView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ZoomSimpleDraweeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
@Override
public void setImageURI(Uri uri) {
reset();
super.setImageURI(uri);
}
@Override
protected void onDraw(Canvas canvas) {
int saveCount = canvas.save();
canvas.concat(mCurrentMatrix);
super.onDraw(canvas);
canvas.restoreToCount(saveCount);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mScaleDetector.onTouchEvent(event);
if (!mScaleDetector.isInProgress()) {
mGestureDetector.onTouchEvent(event);
}
return true;
}
public final float getScale() {
mCurrentMatrix.getValues(matrixValues);
return matrixValues[Matrix.MSCALE_X];
}
//图片宽高比例
public void setImagePro(float imgPro) {
this.imgagePro = imgPro;
}
public void setOnSingleClickListener(setOnSingleClickListener listener) {
mClickListener = listener;
}
public void setOnLongClickListener(setOnLongClickListener listener) {
mLongClickListener = listener;
}
public interface setOnLongClickListener {
void onLongClick();
}
public interface setOnSingleClickListener {
void onClick();
}
/**
* 自动缩放的任务
*/
private class AutoScaleRunnable implements Runnable {
static final float BIGGER = 1.07f;
static final float SMALLER = 0.96f;
private float mTargetScale;
private boolean isExp;
/**
* 缩放的中心
*/
private float x;
private float y;
/**
* @param isExp :判断是否是放大
*/
public AutoScaleRunnable(float targetScale, float x, float y, boolean isExp) {
this.mTargetScale = targetScale;
this.x = x;
this.y = y;
this.isExp = isExp;
}
@Override
public void run() {
if (isExp) { //放大
mCurrentMatrix.postScale(BIGGER, BIGGER, x, y);
invalidate();
if (mCurrentScale < mTargetScale && mCurrentScale <= 4) {
ZoomSimpleDraweeView.this.postDelayed(this, 10);
mCurrentScale = mCurrentScale * BIGGER;
} else {
checkBorder();
mCurrentScale = getScale();
}
} else {//缩小
mCurrentMatrix.postScale(SMALLER, SMALLER, x, y);
invalidate();
checkBorder();
if (getScale() > 1.01) {
ZoomSimpleDraweeView.this.postDelayed(this, 1);
mCurrentScale = mCurrentScale * SMALLER;
} else {
reset();
}
}
}
}
}

View File

@ -12,8 +12,6 @@ import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.TintTypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@ -22,6 +20,9 @@ import android.widget.RatingBar;
import com.gh.common.view.materialratingbar.internal.DrawableCompat;
import com.gh.gamecenter.R;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.TintTypedArray;
// AppCompatRatingBar will add undesired measuring behavior.
@SuppressLint("AppCompatCustomView")
@ -154,6 +155,12 @@ public class MaterialRatingBar extends RatingBar {
@Nullable
@Override
public ColorStateList getProgressTintList() {
// Samsung Android 10 might call this in super class constructor.
// Base on this PR: https://github.com/zhanghai/MaterialRatingBar/pull/62
if (mProgressTintInfo == null) {
return null;
}
logRatingBarTintWarning();
return getSupportProgressTintList();
}
@ -301,9 +308,6 @@ public class MaterialRatingBar extends RatingBar {
}
private void logRatingBarTintWarning() {
if (getContext().getApplicationInfo().minSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
return;
}
Log.w(TAG, "Non-support version of tint method called, this is error-prone and will crash" +
" below Lollipop if you are calling it as a method of RatingBar instead of" +
" MaterialRatingBar");

View File

@ -37,41 +37,42 @@ public class PagerLayoutManager extends LinearLayoutManager {
* 初始化操作
*/
private void init() {
switch (mOrientation){
switch (mOrientation) {
case HORIZONTAL:
mPagerSnapHelper = new ScrollPageHelper(Gravity.START,false);
mPagerSnapHelper = new ScrollPageHelper(Gravity.START, false);
break;
case VERTICAL:
mPagerSnapHelper = new ScrollPageHelper(Gravity.TOP,false);
mPagerSnapHelper = new ScrollPageHelper(Gravity.TOP, false);
break;
default:
mPagerSnapHelper = new ScrollPageHelper(Gravity.TOP,false);
mPagerSnapHelper = new ScrollPageHelper(Gravity.TOP, false);
break;
}
}
/**
* attach到window窗口时该方法必须调用
* @param recyclerView recyclerView
*
* @param recyclerView recyclerView
*/
@Override
public void onAttachedToWindow(RecyclerView recyclerView){
public void onAttachedToWindow(RecyclerView recyclerView) {
if (recyclerView == null) {
throw new IllegalArgumentException("The attach RecycleView must not null!!");
}
super.onAttachedToWindow(recyclerView);
this.mRecyclerView = recyclerView;
if (mPagerSnapHelper==null){
if (mPagerSnapHelper == null) {
init();
}
try {
//attachToRecyclerView源码上的方法可能会抛出IllegalStateException异常这里手动捕获一下
RecyclerView.OnFlingListener onFlingListener = mRecyclerView.getOnFlingListener();
//源码中判断了如果onFlingListener已经存在的话再次设置就直接抛出异常那么这里可以判断一下
if (onFlingListener==null){
if (onFlingListener == null) {
mPagerSnapHelper.attachToRecyclerView(mRecyclerView);
}
} catch (IllegalStateException e){
} catch (IllegalStateException e) {
e.printStackTrace();
}
mRecyclerView.addOnChildAttachStateChangeListener(mChildAttachStateChangeListener);
@ -79,13 +80,14 @@ public class PagerLayoutManager extends LinearLayoutManager {
/**
* 销毁的时候调用该方法,需要移除监听事件
* @param view view
* @param recycler recycler
*
* @param view view
* @param recycler recycler
*/
@Override
public void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) {
super.onDetachedFromWindow(view, recycler);
if (mRecyclerView!=null){
if (mRecyclerView != null) {
mRecyclerView.removeOnChildAttachStateChangeListener(mChildAttachStateChangeListener);
}
}
@ -100,7 +102,8 @@ public class PagerLayoutManager extends LinearLayoutManager {
* 缓慢拖拽-> SCROLL_STATE_DRAGGING
* 快速滚动-> SCROLL_STATE_SETTLING
* 空闲状态-> SCROLL_STATE_IDLE
* @param state 状态
*
* @param state 状态
*/
@Override
public void onScrollStateChanged(int state) {
@ -134,13 +137,15 @@ public class PagerLayoutManager extends LinearLayoutManager {
}
}
double speedRatio = 0.8;
/**
* 监听竖直方向的相对偏移量
* @param dy y轴滚动值
* @param recycler recycler
* @param state state滚动状态
* @return int值
*
* @param dy y轴滚动值
* @param recycler recycler
* @param state state滚动状态
* @return int值
*/
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
@ -155,10 +160,11 @@ public class PagerLayoutManager extends LinearLayoutManager {
/**
* 监听水平方向的相对偏移量
* @param dx x轴滚动值
* @param recycler recycler
* @param state state滚动状态
* @return int值
*
* @param dx x轴滚动值
* @param recycler recycler
* @param state state滚动状态
* @return int值
*/
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler,
@ -172,9 +178,10 @@ public class PagerLayoutManager extends LinearLayoutManager {
/**
* 设置监听
* @param listener listener
*
* @param listener listener
*/
public void setOnViewPagerListener(OnPagerListener listener){
public void setOnViewPagerListener(OnPagerListener listener) {
this.mOnViewPagerListener = listener;
}
@ -197,13 +204,13 @@ public class PagerLayoutManager extends LinearLayoutManager {
*/
@Override
public void onChildViewDetachedFromWindow(@NonNull View view) {
if (mDrift >= 0){
if (mDrift >= 0) {
if (mOnViewPagerListener != null) {
mOnViewPagerListener.onPageRelease(true , getPosition(view));
mOnViewPagerListener.onPageRelease(true, getPosition(view));
}
}else {
} else {
if (mOnViewPagerListener != null) {
mOnViewPagerListener.onPageRelease(false , getPosition(view));
mOnViewPagerListener.onPageRelease(false, getPosition(view));
}
}
}

View File

@ -0,0 +1,56 @@
package com.gh.download
import android.content.pm.PackageManager
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
object DownloadDataHelper {
const val DOWNLOAD_RESUME_WAY = "download_resume_way"
const val DOWNLOAD_RESUME_MANUAL = "manual"
const val DOWNLOAD_RESUME_AUTO = "auto"
const val DOWNLOAD_CANCEL_WAY = "download_cancel_way"
const val DOWNLOAD_CANCEL_MANUAL = "manual"
const val DOWNLOAD_CANCEL_AUTO = "auto"
@JvmStatic
fun getDownloadStatusAlias(downloadEntity: DownloadEntity): String {
val status = downloadEntity.status
return if (status == DownloadStatus.add) {
"开始下载"
} else if (status == DownloadStatus.pause) {
"暂停下载"
} else if (status == DownloadStatus.resume) {
if (downloadEntity.meta[DOWNLOAD_RESUME_WAY] == DOWNLOAD_RESUME_AUTO) {
"自动恢复下载"
} else {
"继续下载"
}
} else if (status == DownloadStatus.waiting) {
"暂停下载-等待中"
} else if (status == DownloadStatus.subscribe || status == DownloadStatus.neterror || status == DownloadStatus.timeout) {
"暂停下载-连上WiFi自动下载"
} else if (status == DownloadStatus.done) {
val pm = HaloApp.getInstance().application.applicationContext.packageManager
val packageInfo = pm.getPackageArchiveInfo(downloadEntity.path, PackageManager.GET_ACTIVITIES)
if (packageInfo == null) {
"解析包错误"
} else {
"下载完成"
}
} else if (status == DownloadStatus.delete || status == DownloadStatus.cancel) {
if (downloadEntity.meta[DOWNLOAD_CANCEL_WAY] == DOWNLOAD_CANCEL_AUTO) {
"自动删除任务"
} else {
"删除任务"
}
} else if (status == DownloadStatus.overflow) {
"解析包错误-下载过程中"
} else if (status == DownloadStatus.hijack || status == DownloadStatus.notfound) {
"下载失败"
} else {
"未知状态"
}
}
}

View File

@ -10,21 +10,25 @@ import android.os.Message;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import com.gh.common.AppExecutor;
import com.gh.common.exposure.ExposureEvent;
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.GdtHelper;
import com.gh.common.util.MD5Utils;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.NetworkUtils;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.SPUtils;
import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.GameUpdateEntity;
import com.gh.gamecenter.entity.PluginLocation;
import com.gh.gamecenter.eventbus.EBDownloadStatus;
import com.gh.gamecenter.manager.PackagesManager;
import com.gh.gamecenter.packagehelper.PackageRepository;
import com.google.gson.Gson;
import com.halo.assistant.HaloApp;
import com.lightgame.config.CommonDebug;
@ -46,7 +50,9 @@ import org.greenrobot.eventbus.EventBus;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import androidx.annotation.Nullable;
@ -58,6 +64,7 @@ public class DownloadManager implements DownloadStatusListener {
private static DownloadManager mInstance;
private static Gson gson = new Gson();
private static final String HINT_MARK = "hint_mark";
private Context mContext;
private Handler mHandler;
@ -71,6 +78,8 @@ public class DownloadManager implements DownloadStatusListener {
private DownloadDao mDownloadDao;
private Set<String> mUpdateMarks;
@Override
public void onTaskCancelled(DownloadEntity entity) {
EBDownloadStatus status = new EBDownloadStatus("delete", entity.getName(),
@ -78,8 +87,6 @@ public class DownloadManager implements DownloadStatusListener {
status.setPluggable(entity.isPluggable());
EventBus.getDefault().post(status);
DownloadNotification.showDownloadingNotification(mContext);
DownloadManager.getInstance(mContext).putStatus(entity.getUrl(), DownloadStatus.delete);
downloadingMap.remove(entity.getUrl());
@ -87,11 +94,9 @@ public class DownloadManager implements DownloadStatusListener {
@Override
public void onTaskAdded(DownloadEntity entity) {
EventBus.getDefault().post(new EBDownloadStatus("download",entity.getName(),
EventBus.getDefault().post(new EBDownloadStatus("download", entity.getName(),
entity.getPlatform(), entity.getUrl(), entity.getPackageName(), entity.getGameId()));
DownloadNotification.showDownloadingNotification(mContext);
downloadingMap.put(entity.getUrl(), entity);
DownloadWorkManager.addWorker();
@ -103,7 +108,6 @@ public class DownloadManager implements DownloadStatusListener {
if (entity.getStatus() == DownloadStatus.overflow) {
MtaHelper.onEventWithBasicDeviceInfo("下载无法完成", "游戏", entity.getName());
} else {
DownloadNotification.showDownloadingNotification(mContext);
downloadingMap.remove(entity.getUrl());
}
}
@ -115,8 +119,6 @@ public class DownloadManager implements DownloadStatusListener {
@Override
public void onTaskDone(DownloadEntity entity) {
DownloadNotification.showDownloadingNotification(mContext);
DownloadNotification.showDownloadDoneNotification(mContext, entity);
downloadingMap.remove(entity.getUrl());
if (downloadingMap.isEmpty()) {
@ -133,6 +135,8 @@ public class DownloadManager implements DownloadStatusListener {
mContext = context.getApplicationContext();
mDownloadDao = DownloadDao.getInstance(mContext);
mUpdateMarks = SPUtils.getStringSet(HINT_MARK);
//TODO unregister this
DownloadStatusManager.getInstance().registerTaskStatusListener(this);
@ -153,9 +157,12 @@ public class DownloadManager implements DownloadStatusListener {
String url = (String) msg.obj;
switch (msg.what) {
case DownloadConfig.CONTINUE_DOWNLOAD_TASK:
case DownloadConfig.CONTINUE_DOWNLOAD_AUTO_TASK:
if (lastTimeMap.get(url) != null && System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) {
DownloadEntity downloadEntity = getDownloadEntityByUrl(url);
if (downloadEntity != null) add(downloadEntity);
if (downloadEntity != null) {
resume(downloadEntity, msg.what == DownloadConfig.CONTINUE_DOWNLOAD_AUTO_TASK);
}
}
break;
case DownloadConfig.PAUSE_DOWNLOAD_TASK:
@ -305,6 +312,42 @@ public class DownloadManager implements DownloadStatusListener {
Utils.log(DownloadManager.class.getSimpleName(), "add");
}
/**
* 继续下载任务
*
* @param downloadEntity
* @param automatic 是否是自动下载
*/
public void resume(DownloadEntity downloadEntity, boolean automatic) {
if (downloadEntity != null) {
String url = downloadEntity.getUrl();
checkDownloadEntryRecordValidate(url);
if (isFileCompleted(url)) {
downloadEntity.setStatus(DownloadStatus.done);
DataChanger.INSTANCE.notifyDataChanged(downloadEntity);
} else if (!isTaskDownloading(url)) {
DownloadEntity daoEntity = mDownloadDao.get(downloadEntity.getUrl());
if (automatic) {
if (daoEntity != null) {
daoEntity.getMeta().put(DownloadDataHelper.DOWNLOAD_RESUME_WAY, DownloadDataHelper.DOWNLOAD_RESUME_AUTO);
mDownloadDao.newOrUpdate(daoEntity);
}
downloadEntity.getMeta().put(DownloadDataHelper.DOWNLOAD_RESUME_WAY, DownloadDataHelper.DOWNLOAD_RESUME_AUTO);
} else {
if (daoEntity != null) {
daoEntity.getMeta().put(DownloadDataHelper.DOWNLOAD_RESUME_WAY, DownloadDataHelper.DOWNLOAD_RESUME_MANUAL);
mDownloadDao.newOrUpdate(daoEntity);
}
downloadEntity.getMeta().put(DownloadDataHelper.DOWNLOAD_RESUME_WAY, DownloadDataHelper.DOWNLOAD_RESUME_MANUAL);
}
startDownloadService(downloadEntity, DownloadStatus.resume);
}
put(url, System.currentTimeMillis());
putStatus(url, DownloadStatus.downloading);
}
Utils.log(DownloadManager.class.getSimpleName(), "resume");
}
/**
* 添加一个下载任务(WiFi时自动下载)
*
@ -478,10 +521,16 @@ public class DownloadManager implements DownloadStatusListener {
* @param url
*/
public void cancel(String url) {
cancel(url, true);
cancel(url, true, false);
}
public void cancel(String url, boolean isDeleteFile) {
/**
* 根据url取消下载并删除已下载的文件
*
* @param url
* @param automatic 是否是安装完自动删除
*/
public void cancel(String url, boolean isDeleteFile, boolean automatic) {
DownloadEntity entry = mDownloadDao.get(url);
if (entry != null) {
if (isDeleteFile) {
@ -491,6 +540,11 @@ public class DownloadManager implements DownloadStatusListener {
Utils.log(DownloadManager.class.getSimpleName(), "cancel==>file and record were deleted!");
}
if (entry != null) {
if (automatic) {
entry.getMeta().put(DownloadDataHelper.DOWNLOAD_CANCEL_WAY, DownloadDataHelper.DOWNLOAD_CANCEL_AUTO);
} else {
entry.getMeta().put(DownloadDataHelper.DOWNLOAD_CANCEL_WAY, DownloadDataHelper.DOWNLOAD_CANCEL_MANUAL);
}
entry.setStatus(DownloadStatus.cancel);
startDownloadService(entry, DownloadStatus.cancel);
Utils.log(DownloadManager.class.getSimpleName(), "cancel");
@ -502,7 +556,7 @@ public class DownloadManager implements DownloadStatusListener {
*/
public void cancelAll() {
for (DownloadEntity entry : DataChanger.INSTANCE.getDownloadEntries().values()) {
cancel(entry.getUrl(), true);
cancel(entry.getUrl(), true, false);
}
Utils.log(DownloadManager.class.getSimpleName(), "cancel all");
}
@ -567,9 +621,8 @@ public class DownloadManager implements DownloadStatusListener {
}
}
// 开启下载服务
startDownloadServiceInBackground();
DownloadNotification.showDownloadingNotification(mContext);
// 开启下载服务, Fuck me, 即便是在启动页调用的方法,依然有可能触发 `unable is in background`
startDownloadService();
}
public void addObserver(DataWatcher dataWatcher) {
@ -582,11 +635,30 @@ public class DownloadManager implements DownloadStatusListener {
DataChanger.INSTANCE.deleteObserver(dataWatcher);
}
public void startDownloadServiceInBackground() {
mContext.startService(new Intent(mContext, DownloadService.class));
private void startDownloadService() {
Intent serviceIntent = new Intent(mContext, DownloadService.class);
// 当满足系统版本大于 8.0 、应用在后台运行时以前台服务开启
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
&& !HaloApp.getInstance().isRunningForeground) {
serviceIntent.putExtra(DownloadService.KEY_SERVICE_ACTION, DownloadService.START_FOREGROUND);
mContext.startForegroundService(serviceIntent);
} else {
mContext.startService(serviceIntent);
}
}
public void startDownloadService(DownloadEntity downloadEntity, DownloadStatus status) {
private void startDownloadService(DownloadEntity downloadEntity, DownloadStatus status) {
// 在启动服务时添加该条下载的网络状态
if (status == DownloadStatus.add || status == DownloadStatus.resume) {
String network = DeviceUtils.getNetwork(mContext);
DownloadEntity daoEntity = mDownloadDao.get(downloadEntity.getUrl());
if (daoEntity != null) {
daoEntity.getMeta().put(DownloadEntity.NETWORK_STATUS_KEY, network);
mDownloadDao.newOrUpdate(daoEntity);
}
downloadEntity.getMeta().put(DownloadEntity.NETWORK_STATUS_KEY, network);
}
Intent serviceIntent = getIntent(downloadEntity, status);
// 当满足系统版本大于 8.0 、应用在后台运行时以前台服务开启
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
@ -598,6 +670,14 @@ public class DownloadManager implements DownloadStatusListener {
}
}
public void disableDownloadSpeedLimit() {
// DownloadSpeedController.disableSpeedLimit();
}
public void updateSpeedLimitationReleaseDelay(int delay) {
// DownloadSpeedController.updateLimitationReleaseDelay(delay);
}
public void checkRetryDownload() {
if (!NetworkUtils.isWifiConnected(mContext)) return;
@ -607,7 +687,7 @@ public class DownloadManager implements DownloadStatusListener {
DownloadStatus.subscribe.equals(downloadEntity.getStatus())) {
DownloadManager.getInstance(mContext).put(downloadEntity.getUrl(), System.currentTimeMillis());
Message msg = Message.obtain();
msg.what = DownloadConfig.CONTINUE_DOWNLOAD_TASK;
msg.what = DownloadConfig.CONTINUE_DOWNLOAD_AUTO_TASK;
msg.obj = downloadEntity.getUrl();
DownloadManager.getInstance(mContext).sendMessageDelayed(msg, 1000);
}
@ -615,19 +695,104 @@ public class DownloadManager implements DownloadStatusListener {
}
}
public int getDownloadOrUpdateCount(List<GameUpdateEntity> updateList) {
int downloadSize = getAll().size();
if (downloadSize != 0) {
return downloadSize;
}
/**
* @param updateList 更新/插件化数据
* @return null: 不显示小红点
*/
@Nullable
public String getDownloadOrUpdateCount(List<GameUpdateEntity> updateList) {
boolean showRedPoint = false;
int downloadingSize = 0;
int updateSize = 0;
if (updateList != null) {
for (GameUpdateEntity updateEntity : updateList) {
if (updateEntity.isShowPlugin(PluginLocation.only_index)) updateSize++;
for (DownloadEntity downloadEntity : getAll()) {
if (DownloadStatus.done.equals(downloadEntity.getStatus())) {
String mark = downloadEntity.getMeta().get(HINT_MARK);
if (TextUtils.isEmpty(mark)) showRedPoint = true;
} else {
downloadingSize++;
}
}
return updateSize;
if (downloadingSize != 0) return String.valueOf(downloadingSize);
if (showRedPoint) return "";
if (updateList != null) {
for (GameUpdateEntity updateEntity : updateList) {
if (updateEntity.isShowPlugin(PluginLocation.only_index)
&& !mUpdateMarks.contains(updateEntity.getId() + updateEntity.getPackageName())) {
return "";
}
}
}
return null;
}
/**
* 标记下载已完成的任务为已读 (用于下载管理页入口的 toolbar 红点显示)
*/
public void markDownloadedTaskAsRead() {
AppExecutor.getIoExecutor().execute(() -> {
boolean markHasChanged = false;
List<DownloadEntity> all = getAll();
for (DownloadEntity downloadEntity : all) {
DownloadStatus status = downloadEntity.getStatus();
if (status == DownloadStatus.done) {
String mark = downloadEntity.getMeta().get(HINT_MARK);
if (TextUtils.isEmpty(mark)) {
downloadEntity.getMeta().put(HINT_MARK, HINT_MARK);
mDownloadDao.newOrUpdate(downloadEntity);
if (!markHasChanged) markHasChanged = true;
}
}
}
if (markHasChanged) {
EventBus.getDefault().post(new EBDownloadStatus("download", "", "", "", "", ""));
}
});
}
/**
* 标记可用更新为已读 (用于下载管理页入口的 toolbar 红点显示)
*/
public void markUpdatableTaskAsRead() {
AppExecutor.getIoExecutor().execute(() -> {
boolean markHasChanged = false;
ArrayList<GameUpdateEntity> updates = PackageRepository.INSTANCE.getGameUpdate();
for (GameUpdateEntity update : updates) {
String mark = update.getId() + update.getPackageName();
if (!mUpdateMarks.contains(mark)) {
mUpdateMarks.add(mark);
if (!markHasChanged) markHasChanged = true;
}
}
if (markHasChanged) {
saveUpdateMarkToStorage();
EventBus.getDefault().post(new EBDownloadStatus("download", "", "", "", "", ""));
}
});
}
/**
* 将可用更新标记为已读的事件
*/
public void saveUpdateMarkToStorage() {
ArrayList<GameUpdateEntity> updates = PackageRepository.INSTANCE.getGameUpdate();
if (updates.size() == mUpdateMarks.size()) {
SPUtils.setStringSet(HINT_MARK, mUpdateMarks);
return;
}
Set<String> marks = new HashSet<>();
for (GameUpdateEntity update : updates) {
String mark = update.getId() + update.getPackageName();
marks.add(mark);
}
SPUtils.setStringSet(HINT_MARK, marks);
}
}

View File

@ -1,146 +0,0 @@
package com.gh.download;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import com.gh.common.util.AppDebugConfig;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.PlatformUtils;
import com.gh.gamecenter.R;
import com.lightgame.download.DownloadEntity;
import com.lightgame.download.DownloadStatus;
import java.util.List;
/**
* @author CsHeng
* @Date 26/06/2017
* @Time 6:01 PM
*/
public class DownloadNotification {
public static final String ACTION_INSTALL = "com.gh.gamecenter.INSTALL";
public static final String ACTION_DOWNLOAD = "com.gh.gamecenter.DOWNLOAD";
public static final int ICON = R.mipmap.logo;
public static final int NOTIFY_ID = 0x123;
public static final int WAIT_NOTIFY_ID = 0x124;
private static final String CHANNEL_ID = "Halo_Download";
private static NotificationManager getNotificationManager(Context context) {
return (NotificationManager) context.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
}
//TODO 下载重构
public static void showDownloadDoneNotification(Context context, DownloadEntity downloadEntity) {
final NotificationManager manager = getNotificationManager(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
manager.createNotificationChannel(channel);
}
Intent intent = new Intent();
intent.putExtra(EntranceUtils.KEY_PATH, downloadEntity.getPath());
intent.setAction(ACTION_INSTALL);
final int requestCode = downloadEntity.getPackageName().hashCode();
final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
String text;
String title;
if (downloadEntity.isPluggable()) {
title = "下载完成,点击继续插件化";
text = downloadEntity.getName() + " - "
+ PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
} else {
if (downloadEntity.isPlugin()) {
text = downloadEntity.getName()
+ " - " + PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
} else {
text = downloadEntity.getName();
}
title = "下载完成,点击立即安装";
}
final Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.mipmap.logo)
.setTicker(title)
.setContentTitle(text)
.setContentText(title)
.setContentIntent(pendingIntent).build();
// notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音
notification.flags |= Notification.FLAG_AUTO_CANCEL; // // FLAG_AUTO_CANCEL表明当通知被用户点击时通知将被清除。
manager.notify(requestCode, notification);
}
public static void showDownloadingNotification(Context context) {
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodWithParams(DownloadNotification.class, context);
}
int downloadingSize = 0;
final List<DownloadEntity> list = DownloadManager.getInstance(context).getAll();
if (list == null) return;
for (DownloadEntity entity : list) {
if (entity.getStatus().equals(DownloadStatus.downloading)
|| entity.getStatus().equals(DownloadStatus.waiting)
|| entity.getStatus().equals(DownloadStatus.pause)
|| entity.getStatus().equals(DownloadStatus.timeout)
|| entity.getStatus().equals(DownloadStatus.neterror)) {
downloadingSize++;
}
}
NotificationManager nManager = getNotificationManager(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
nManager.createNotificationChannel(channel);
}
if (downloadingSize == 0) {
nManager.cancel(NOTIFY_ID);
} else {
Intent intent = new Intent();
intent.setAction(ACTION_DOWNLOAD);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, NOTIFY_ID,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(ICON)
.setTicker("点击查看")
.setContentTitle("正在下载" + downloadingSize + "个游戏")
.setContentText("点击查看")
.setContentIntent(pendingIntent).build();
// notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音
notification.flags |= Notification.FLAG_NO_CLEAR; // 通知无法手动清除
nManager.notify(NOTIFY_ID, notification);
}
}
public static void showWaitingNotification(Context context) {
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodWithParams(DownloadNotification.class, context);
}
NotificationManager nManager = getNotificationManager(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
nManager.createNotificationChannel(channel);
}
Intent intent = new Intent();
intent.setAction(ACTION_DOWNLOAD);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, NOTIFY_ID,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(ICON)
.setTicker("连接WiFi后自动恢复下载")
.setContentTitle("下载已暂停")
.setContentText("连接WiFi后自动恢复下载")
.setContentIntent(pendingIntent).build();
notification.flags = Notification.FLAG_AUTO_CANCEL;
if (nManager != null) nManager.notify(WAIT_NOTIFY_ID, notification);
}
}

View File

@ -0,0 +1,41 @@
package com.gh.download.cache;
public class CacheInfo {
public static final long TOTAL_ERROR = -1;//获取进度失败
private String url;
private long total;
private long progress;
private String fileName;
public CacheInfo(String url) {
this.url = url;
}
public String getUrl() {
return url;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
public long getProgress() {
return progress;
}
public void setProgress(long progress) {
this.progress = progress;
}
}

View File

@ -0,0 +1,236 @@
package com.gh.download.cache;
import com.danikula.videocache.file.FileNameGenerator;
import com.danikula.videocache.file.Md5FileNameGenerator;
import com.gh.common.AppExecutor;
import com.halo.assistant.HaloApp;
import com.shuyu.gsyvideoplayer.utils.StorageUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class CacheManager {
private static final AtomicReference<CacheManager> INSTANCE = new AtomicReference<>();
private volatile HashMap<String, Call> downCalls;
private OkHttpClient mClient;
private File cacheDirectory = StorageUtils.getIndividualCacheDirectory(HaloApp.getInstance().getApplication());
private FileNameGenerator generator = new Md5FileNameGenerator();
private final String TEMP_POSTFIX = ".download";
// private final int preLength = 5 * 1024 * 1024;//预加载大小
public static CacheManager getInstance() {
for (; ; ) {
CacheManager current = INSTANCE.get();
if (current != null) {
return current;
}
current = new CacheManager();
if (INSTANCE.compareAndSet(null, current)) {
return current;
}
}
}
private CacheManager() {
downCalls = new HashMap<>();
mClient = new OkHttpClient.Builder().build();
}
private synchronized HashMap<String, Call> getDownCalls() {
return downCalls;
}
public void download(String url, CacheObserver cacheObserver) {
//当前url已下载完成则不再下载
for (File file : getAllFile()) {
if (file.getName().equals(generator.generate(url))) {
return;
}
}
Observable.just(url)
.filter(s -> !getDownCalls().containsKey(s))//call的map已经有了,就证明正在下载,则这次不下载
.flatMap(s -> Observable.just(createDownInfo(s)))
.map(this::getRealFileName)
.flatMap(cacheInfo -> Observable.create(new DownloadSubscribe(cacheInfo)))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(cacheObserver);
}
public void cancel(String url) {
Call call = getDownCalls().get(url);
if (call != null) {
call.cancel();
}
getDownCalls().remove(url);
}
/**
* 创建DownInfo
*
* @param url 请求网址
* @return DownInfo
*/
private CacheInfo createDownInfo(String url) {
CacheInfo cacheInfo = new CacheInfo(url);
long contentLength = getContentLength(url);//获得文件大小
cacheInfo.setTotal(contentLength);
String fileName = generator.generate(url) + TEMP_POSTFIX;
cacheInfo.setFileName(fileName);
return cacheInfo;
}
private CacheInfo getRealFileName(CacheInfo cacheInfo) {
String fileName = cacheInfo.getFileName();
long downloadLength = 0;
if (!cacheDirectory.exists()) {
cacheDirectory.mkdir();
}
File file = new File(cacheDirectory, fileName);
if (file.exists()) {
//找到了文件,代表已经下载过,则获取其长度
downloadLength = file.length();
}
//设置改变过的文件名/大小
cacheInfo.setProgress(downloadLength);
cacheInfo.setFileName(file.getName());
return cacheInfo;
}
private class DownloadSubscribe implements ObservableOnSubscribe<CacheInfo> {
private CacheInfo cacheInfo;
public DownloadSubscribe(CacheInfo cacheInfo) {
this.cacheInfo = cacheInfo;
}
@Override
public void subscribe(ObservableEmitter<CacheInfo> e) throws Exception {
String url = cacheInfo.getUrl();
final long[] downloadLength = {cacheInfo.getProgress()};//已经下载好的长度
long contentLength = cacheInfo.getTotal();//文件的总长度
// if (downloadLength[0] >= preLength) {
if (downloadLength[0] >= contentLength) {
e.onComplete();
return;
}
e.onNext(cacheInfo);
Request request = new Request.Builder()
// .addHeader("RANGE", "bytes=" + downloadLength[0] + "-" + (contentLength > preLength ? preLength : contentLength))
.addHeader("RANGE", "bytes=" + downloadLength[0] + "-" + contentLength)
.url(url)
.build();
Call call = mClient.newCall(request);
getDownCalls().put(url, call);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
File file = new File(cacheDirectory, cacheInfo.getFileName());
InputStream is = null;
FileOutputStream fileOutputStream = null;
try {
is = response.body().byteStream();
fileOutputStream = new FileOutputStream(file, true);
byte[] buffer = new byte[2048];
int len;
while (downCalls.get(url) != null && !call.isCanceled() && (len = is.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, len);
downloadLength[0] += len;
cacheInfo.setProgress(downloadLength[0]);
e.onNext(cacheInfo);
}
fileOutputStream.flush();
getDownCalls().remove(url);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (is != null) {
is.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
}
if (file.length() == contentLength) {
file.renameTo(new File(file.getPath().substring(0, file.getPath().lastIndexOf(TEMP_POSTFIX))));
}
e.onComplete();
}
});
}
}
/**
* 获取下载长度
*
* @param downloadUrl
* @return
*/
public long getContentLength(String downloadUrl) {
long contentLength = CacheInfo.TOTAL_ERROR;
Request request = new Request.Builder()
.url(downloadUrl)
.build();
Response response = null;
try {
response = mClient.newCall(request).execute();
if (response.isSuccessful() && response.body() != null) {
long length = response.body().contentLength();
contentLength = length == 0 ? CacheInfo.TOTAL_ERROR : length;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (response != null) {
response.close();
}
}
return contentLength;
}
public void removeAllCall() {
AppExecutor.getIoExecutor().execute(() -> {
for (Map.Entry<String, Call> entry : getDownCalls().entrySet()) {
entry.getValue().cancel();
}
AppExecutor.getUiExecutor().execute(() -> getDownCalls().clear());
});
}
private List<File> getAllFile() {
if (cacheDirectory.exists()) {
File[] files = cacheDirectory.listFiles();
return Arrays.asList(files);
}
return new ArrayList<>();
}
}

View File

@ -0,0 +1,35 @@
package com.gh.download.cache;
import com.gh.gamecenter.BuildConfig;
import com.lightgame.utils.Utils;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
public abstract class CacheObserver implements Observer<CacheInfo> {
protected Disposable d;//可以用于取消注册的监听者
protected CacheInfo cacheInfo;
@Override
public void onSubscribe(Disposable d) {
this.d = d;
}
@Override
public void onNext(CacheInfo cacheInfo) {
this.cacheInfo = cacheInfo;
if (BuildConfig.DEBUG) {
Utils.log(cacheInfo.getProgress() + "-" + cacheInfo.getTotal());
}
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onComplete() {
}
}

View File

@ -4,6 +4,7 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.gh.common.util.EntranceUtils
import com.gh.download.DownloadManager
import com.gh.gamecenter.entity.SubjectRecommendEntity
import com.gh.gamecenter.game.GameFragment
@ -20,6 +21,8 @@ class BlockActivity : NormalActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setToolbarMenu(R.menu.menu_download)
DownloadManager.getInstance(this).updateSpeedLimitationReleaseDelay(10)
}
override fun showDownloadMenu(): Boolean {

View File

@ -2,74 +2,40 @@ package com.gh.gamecenter;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Message;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.view.MenuItem;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import com.gh.base.ToolBarActivity;
import com.gh.base.fragment.WaitingDialogFragment;
import com.gh.common.util.BitmapUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.UploadImageUtils;
import com.gh.common.view.CropImageCustom;
import com.gh.gamecenter.retrofit.Response;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.json.JSONObject;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import butterknife.BindView;
import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.schedulers.Schedulers;
import retrofit2.HttpException;
public class CropImageActivity extends ToolBarActivity {
@BindView(R.id.cropimage_custom)
CropImageCustom mCropimageCustom;
public CropImageCustom mCropImageCustom;
public static final String RESULT_CLIP_PATH = "result_clip_path";
private SoftReference<Bitmap> reference;
private SharedPreferences sp;
@Override
protected void handleMessage(Message msg) {
switch (msg.what) {
case 0:
toast("上传成功");
break;
case 1:
toast("上传失败");
break;
case 2:
toast("修改太频繁,请稍后再试");
break;
case 3:
toast("图片违规");
break;
}
}
@NonNull
public static Intent getIntent(Context context, String picturePath, String entrance) {
public static Intent getIntent(Context context, String picturePath, float cropRatio, String entrance) {
Intent intent = new Intent(context, CropImageActivity.class);
intent.putExtra(EntranceUtils.KEY_PATH, picturePath);
intent.putExtra(EntranceUtils.KEY_ENTRANCE, entrance);
intent.putExtra(EntranceUtils.KEY_IMAGE_CROP_RATIO, cropRatio);
return intent;
}
@ -84,108 +50,28 @@ public class CropImageActivity extends ToolBarActivity {
setNavigationTitle(getString(R.string.title_crop_image));
setToolbarMenu(R.menu.menu_positive);
sp = PreferenceManager.getDefaultSharedPreferences(this);
float ratio = getIntent().getFloatExtra(EntranceUtils.KEY_IMAGE_CROP_RATIO, 1F);
mCropImageCustom.setCropRatio(ratio);
}
@Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.layout_menu_positive) {
final WaitingDialogFragment postDialog = WaitingDialogFragment.newInstance(getString(R.string.post_img));
postDialog.show(getSupportFragmentManager(), null);
final String path = getCacheDir() + File.separator + System.currentTimeMillis() + ".jpg";
Observable.create((ObservableOnSubscribe<String>) emitter -> {
boolean isSuccess = mCropimageCustom.savePicture(path);
if (isSuccess) {
UploadImageUtils.INSTANCE.uploadImage(UploadImageUtils.UploadType.icon, path, new UploadImageUtils.OnUploadImageListener() {
@Override
public void onSuccess(@NotNull String imageUrl) {
emitter.onNext(imageUrl);
emitter.onComplete();
}
Intent data = new Intent();
Bitmap clip = mCropImageCustom.clip();
String clipPath = getCacheDir().getAbsolutePath() + File.separator + System.currentTimeMillis() + ".jpg";
try {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(clipPath)));
clip.compress(Bitmap.CompressFormat.WEBP, 100, bos);
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
@Override
public void onError(@Nullable Throwable e) {
if (e != null) {
emitter.onError(e);
} else {
emitter.onError(new IllegalStateException("upload image error"));
}
}
@Override
public void onProgress(long total, long progress) {
int percent = (int) (100 * (progress / (float) total));
if (percent >= 100) percent = 99;
if (postDialog != null) {
postDialog.uploadWaitingHint("图片上传中 " + percent + "%");
}
}
});
}
}).subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new Response<String>() {
@Override
public void onResponse(String url) {
try {
if (postDialog != null) postDialog.dismissAllowingStateLoss();
mBaseHandler.sendEmptyMessage(0);
String iconCount = sp.getString("updateIconCount", null);
long l = System.currentTimeMillis();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.CHINA);
String time = format.format(new Date(l));
JSONObject jsonObject = new JSONObject();
jsonObject.put("time", time);
if (TextUtils.isEmpty(iconCount)) {
jsonObject.put("count", 1);
} else {
JSONObject json = new JSONObject(iconCount);
String lastTime = json.getString("time");
if (lastTime.equals(time)) {
jsonObject.put("count", json.getInt("count") + 1);
} else {
jsonObject.put("count", 1);
}
}
sp.edit().putString("updateIconCount", jsonObject.toString()).apply();
Intent data = new Intent();
data.putExtra(EntranceUtils.KEY_URL, url);
setResult(RESULT_OK, data);
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(HttpException e) {
if (postDialog != null) postDialog.dismissAllowingStateLoss();
try {
if (e != null && e.code() == HttpURLConnection.HTTP_FORBIDDEN && e.response().errorBody() != null) {
JSONObject object = new JSONObject(e.response().errorBody().string());
String detail = object.getString("detail");
if ("too frequent".equals(detail)) {
mBaseHandler.sendEmptyMessage(2);
} else if ("INVALID PICTURE".equals(detail)) {
mBaseHandler.sendEmptyMessage(3);
} else {
mBaseHandler.sendEmptyMessage(1);
}
} else {
mBaseHandler.sendEmptyMessage(1);
}
} catch (Exception e1) {
e1.printStackTrace();
mBaseHandler.sendEmptyMessage(1);
}
}
});
data.putExtra(RESULT_CLIP_PATH, clipPath);
setResult(RESULT_OK, data);
finish();
}
return super.onMenuItemClick(item);
}
@ -202,7 +88,7 @@ public class CropImageActivity extends ToolBarActivity {
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus && (reference == null || reference.get() == null)) {
ImageView imageView = mCropimageCustom.getCropImageZoomView();
ImageView imageView = mCropImageCustom.getCropImageZoomView();
Bitmap bitmap = BitmapUtils.getBitmapByFile(getIntent().getStringExtra(EntranceUtils.KEY_PATH),
imageView.getWidth(), imageView.getHeight());
if (bitmap != null) {

View File

@ -6,6 +6,7 @@ import android.os.Bundle;
import com.gh.base.fragment.BaseFragment_TabLayout;
import com.gh.common.util.EntranceUtils;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.download.DownloadFragment;
/**
@ -48,4 +49,11 @@ public class DownloadManagerActivity extends NormalActivity {
bundle.putString(EntranceUtils.KEY_PACKAGENAME, packageName);
return getTargetIntent(context, DownloadManagerActivity.class, DownloadFragment.class, bundle);
}
@Override
protected void onResume() {
super.onResume();
DownloadManager.getInstance(this).disableDownloadSpeedLimit();
}
}

View File

@ -12,6 +12,7 @@ import com.gh.common.exposure.ExposureType;
import com.gh.common.util.DataUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.gamedetail.GameDetailFragment;
import com.halo.assistant.HaloApp;
@ -19,28 +20,30 @@ import com.halo.assistant.HaloApp;
import static com.gh.common.constant.Constants.GAME_DETAIL_COME_IN;
/**
* TODO 合并构建 intent 的重复代码
* Created by khy on 2017/3/24.
* 游戏详情适配器
*/
public class GameDetailActivity extends NormalActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DownloadManager.getInstance(this).updateSpeedLimitationReleaseDelay(10);
DisplayUtils.transparentStatusBar(this);
}
@Override
protected Intent provideNormalIntent() {
return getTargetIntent(this, GameDetailActivity.class, GameDetailFragment.class);
}
@Override
protected int getLayoutId() {
return R.layout.activity_game_detail;
}
/**
* 启动游戏详情页面
*/
@ -66,51 +69,88 @@ public class GameDetailActivity extends NormalActivity {
* 启动游戏详情页面 with 曝光事件
*/
public static void startGameDetailActivity(Context context, GameEntity gameEntity, String entrance, ExposureEvent traceEvent) {
startGameDetailActivity(context, gameEntity, entrance, -1, traceEvent);
}
public static void startGameDetailActivity(Context context, GameEntity gameEntity, String entrance, int defaultTab, ExposureEvent traceEvent) {
DataUtils.onMtaEvent(context, "详情页面", "游戏详情", gameEntity != null ? gameEntity.getName() : "");
Bundle bundle = new Bundle();
// TODO TraceEvent 为空时不该调用此方法才对
if (BuildConfig.DEBUG) {
if (traceEvent == null) {
throw new IllegalArgumentException("没有曝光的 TraceEvent 不要调用这个方法");
}
}
if (traceEvent != null) {
ExposureEvent clickEvent = ExposureEvent.Companion.createEvent(gameEntity, traceEvent.getSource(), ExposureTraceUtils.INSTANCE
.appendTrace(traceEvent), ExposureType.CLICK);
ExposureManager.INSTANCE.log(clickEvent);
bundle.putParcelable(EntranceUtils.KEY_TRACE_EVENT, clickEvent);
}
if (gameEntity != null
&& traceEvent != null
&& gameEntity.getId() != null
&& !gameEntity.getId().equals(traceEvent.getPayload().getGameId())) {
&& traceEvent != null
&& gameEntity.getId() != null
&& !gameEntity.getId().equals(traceEvent.getPayload().getGameId())) {
// 当游戏 ID 跟曝光 traceEvent 的游戏ID 不一样的时候更新 traceEvent 的游戏ID
ExposureEvent forNewPayload = ExposureEvent.Companion.createEvent(gameEntity,
traceEvent.getSource(),
ExposureTraceUtils.INSTANCE.appendTrace(traceEvent),
ExposureType.EXPOSURE);
traceEvent.getSource(),
ExposureTraceUtils.INSTANCE.appendTrace(traceEvent),
ExposureType.EXPOSURE);
traceEvent.setPayload(forNewPayload.getPayload());
}
ExposureEvent clickEvent = ExposureEvent.Companion.createEvent(gameEntity, traceEvent.getSource(), ExposureTraceUtils.INSTANCE.appendTrace(traceEvent), ExposureType.CLICK);
ExposureManager.INSTANCE.log(clickEvent);
Bundle bundle = new Bundle();
if (defaultTab != -1) {
bundle.putInt(EntranceUtils.KEY_TARGET, defaultTab);
}
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
bundle.putParcelable(GameEntity.TAG, gameEntity);
bundle.putParcelable(EntranceUtils.KEY_TRACE_EVENT, clickEvent);
context.startActivity(getTargetIntent(context, GameDetailActivity.class, GameDetailFragment.class, bundle));
}
/**
* 启动游戏详情页面 with 曝光事件
*/
public static void startGameDetailActivity(Context context, String gameId, String entrance, ExposureEvent traceEvent) {
startGameDetailActivity(context, gameId, entrance, -1, traceEvent);
}
public static void startGameDetailActivity(Context context, String gameId, String entrance, int defaultTab, ExposureEvent traceEvent) {
Bundle bundle = new Bundle();
// TODO TraceEvent 为空时不该调用此方法才对
if (BuildConfig.DEBUG) {
if (traceEvent == null) {
throw new IllegalArgumentException("没有曝光的 TraceEvent 不要调用这个方法");
}
}
if (traceEvent != null) {
ExposureEvent clickEvent = ExposureEvent.Companion.createEvent(new GameEntity(gameId), traceEvent.getSource(), ExposureTraceUtils.INSTANCE.appendTrace(traceEvent), ExposureType.CLICK);
ExposureManager.INSTANCE.log(clickEvent);
bundle.putParcelable(EntranceUtils.KEY_TRACE_EVENT, clickEvent);
}
if (traceEvent != null
&& !gameId.equals(traceEvent.getPayload().getGameId())) {
&& !gameId.equals(traceEvent.getPayload().getGameId())) {
// 当游戏 ID 跟曝光 traceEvent 的游戏ID 不一样的时候更新 traceEvent 的游戏ID
ExposureEvent forNewPayload = ExposureEvent.Companion.createEvent(new GameEntity(gameId),
traceEvent.getSource(),
ExposureTraceUtils.INSTANCE.appendTrace(traceEvent),
ExposureType.EXPOSURE);
traceEvent.getSource(),
ExposureTraceUtils.INSTANCE.appendTrace(traceEvent),
ExposureType.EXPOSURE);
traceEvent.setPayload(forNewPayload.getPayload());
}
ExposureEvent clickEvent = ExposureEvent.Companion.createEvent(new GameEntity(gameId), traceEvent.getSource(), ExposureTraceUtils.INSTANCE.appendTrace(traceEvent), ExposureType.CLICK);
ExposureManager.INSTANCE.log(clickEvent);
Bundle bundle = new Bundle();
if (defaultTab != -1) {
bundle.putInt(EntranceUtils.KEY_TARGET, defaultTab);
}
bundle.putString(EntranceUtils.KEY_GAMEID, gameId);
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
bundle.putParcelable(EntranceUtils.KEY_TRACE_EVENT, clickEvent);
context.startActivity(getTargetIntent(context, GameDetailActivity.class, GameDetailFragment.class, bundle));
}
@ -147,6 +187,18 @@ public class GameDetailActivity extends NormalActivity {
context.startActivity(getTargetIntent(context, GameDetailActivity.class, GameDetailFragment.class, bundle));
}
/**
* 启动游戏详情页面并定位到 介绍tab并打开视频流
*/
public static void startGameDetailToVideoStreaming(Context context, String gameId, String entrance) {
Bundle bundle = new Bundle();
bundle.putString(EntranceUtils.KEY_GAMEID, gameId);
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
bundle.putBoolean(EntranceUtils.KEY_OPEN_VIDEO_STREAMING, true);
bundle.putInt(EntranceUtils.KEY_TARGET, GameDetailFragment.INDEX_DESC);
context.startActivity(getTargetIntent(context, GameDetailActivity.class, GameDetailFragment.class, bundle));
}
/**
* 如果存在多个游戏平台则打开
*/
@ -173,7 +225,7 @@ public class GameDetailActivity extends NormalActivity {
super.onDestroy();
HaloApp.remove(GAME_DETAIL_COME_IN);
}
@Override
public String getActivityNameInChinese() {
return "游戏详情";

View File

@ -0,0 +1,63 @@
package com.gh.gamecenter
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import com.gh.base.BaseActivity_TabLayout
import com.gh.gamecenter.help.HelpContainerFragment
import com.gh.gamecenter.suggest.SuggestSelectFragment
import com.lightgame.utils.Util_System_Keyboard
class HelpAndFeedbackActivity : BaseActivity_TabLayout() {
override fun getLayoutId(): Int {
return R.layout.activity_help_and_feedback
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == SuggestSelectFragment.SUGGEST_TYPE_REQUEST
&& resultCode == SuggestSelectFragment.SUGGEST_TYPE_REQUEST) {
finish()
}
}
override fun initFragmentList(fragments: MutableList<Fragment>) {
fragments.add(HelpContainerFragment())
fragments.add(SuggestSelectFragment())
}
override fun initTabTitleList(tabTitleList: MutableList<String>) {
tabTitleList.add("使用帮助")
tabTitleList.add("意见反馈")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setNavigationTitle("帮助与反馈")
mTabIndicatorView.setIndicatorWidth(88)
}
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
if (position == SUGGESTION_ITEM) {
Util_System_Keyboard.hideSoftKeyboard(this)
}
}
fun setCurrentItem(position: Int) {
mViewPager.currentItem = position
}
companion object {
const val HELP_ITEM = 0
const val SUGGESTION_ITEM = 1
@JvmStatic
fun getIntent(context: Context): Intent {
return Intent(context, HelpAndFeedbackActivity::class.java)
}
}
}

View File

@ -2,7 +2,9 @@ package com.gh.gamecenter;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.gh.common.util.EntranceUtils;
@ -14,10 +16,23 @@ import com.gh.gamecenter.fragment.LoginFragment;
public class LoginActivity extends NormalActivity {
@Override
protected Intent provideNormalIntent() {
return getTargetIntent(this, LoginActivity.class, LoginFragment.class);
}
@NonNull
public static Intent getIntent(Context context, String entrance) {
Bundle bundle = new Bundle();
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
return getTargetIntent(context, LoginActivity.class, LoginFragment.class, bundle);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTitleTv.setText("登录光环助手");
mTitleTv.setTextSize(18);
mTitleTv.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
}
}

View File

@ -48,8 +48,8 @@ import com.gh.common.util.DeviceTokenUtils;
import com.gh.common.util.DeviceUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DirectUtils;
import com.gh.common.util.DownloadNotificationHelper;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.GsonUtils;
import com.gh.common.util.LogUtils;
import com.gh.common.util.LunchType;
import com.gh.common.util.MtaHelper;
@ -59,17 +59,19 @@ import com.gh.common.util.PlatformUtils;
import com.gh.common.util.PushHelper;
import com.gh.common.util.SPUtils;
import com.gh.common.util.ShareUtils;
import com.gh.common.util.StringUtils;
import com.gh.common.util.ThirdPartyPackageHelper;
import com.gh.common.util.UrlFilterUtils;
import com.gh.download.DownloadManager;
import com.gh.download.DownloadNotification;
import com.gh.gamecenter.download.DownloadFragment;
import com.gh.gamecenter.entity.CommunityEntity;
import com.gh.gamecenter.entity.GameDigestEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.InnerMetaInfoEntity;
import com.gh.gamecenter.entity.NotificationHint;
import com.gh.gamecenter.entity.SettingsEntity;
import com.gh.gamecenter.entity.NotificationUgc;
import com.gh.gamecenter.entity.SimpleGameEntity;
import com.gh.gamecenter.eventbus.EBDownloadStatus;
import com.gh.gamecenter.eventbus.EBNetworkState;
import com.gh.gamecenter.eventbus.EBPackage;
import com.gh.gamecenter.eventbus.EBReuse;
@ -87,10 +89,12 @@ import com.gh.gamecenter.retrofit.BiResponse;
import com.gh.gamecenter.retrofit.EmptyResponse;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.gh.gamecenter.suggest.SuggestSelectFragment;
import com.gh.gamecenter.suggest.SuggestType;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.halo.assistant.HaloApp;
import com.halo.assistant.fragment.SettingsFragment;
import com.lightgame.config.CommonDebug;
import com.lightgame.download.DataWatcher;
import com.lightgame.download.DownloadEntity;
@ -98,15 +102,18 @@ import com.lightgame.download.DownloadStatus;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.AppManager;
import com.lightgame.utils.Util_System_Phone_State;
import com.shuyu.gsyvideoplayer.utils.StorageUtils;
import com.tencent.bugly.beta.tinker.TinkerManager;
import com.tencent.bugly.crashreport.CrashReport;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -119,6 +126,7 @@ import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@ -128,7 +136,13 @@ import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import static com.gh.common.util.EntranceUtils.ENTRANCE_BROWSER;
import static com.gh.common.util.EntranceUtils.HOST_QQ;
import static com.gh.common.util.EntranceUtils.HOST_QQ_GROUP;
import static com.gh.common.util.EntranceUtils.HOST_WEB;
import static com.gh.common.util.EntranceUtils.KEY_DATA;
import static com.gh.common.util.EntranceUtils.KEY_TO;
import static com.gh.common.util.EntranceUtils.KEY_TYPE;
import static com.gh.gamecenter.fragment.MainWrapperFragment.INDEX_PERSONAL;
import static com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG;
import static com.gh.gamecenter.personal.PersonalFragment.LOGOUT_TAG;
@ -138,6 +152,7 @@ public class MainActivity extends BaseActivity {
public final static String EB_SKIP_MAIN = "MainActivity";
public final static String SHOULD_INIT_IM = "should_init_im";
public final static String SWITCH_TO_COMMUNITY = "switch_to_community";
public final static String SWITCH_TO_VIDEO = "switch_to_video";
private final static String IS_SKIPPED = "is_skipped";
@ -151,12 +166,19 @@ public class MainActivity extends BaseActivity {
private boolean isSkipped = false;
public static boolean isNewFirstLaunch;
public String uuid = UUID.randomUUID().toString();
private Handler handler = new Handler();
// todo 全局监听可能不应该放这里, MainActivity 销毁后此处无法工作
// 黄壮华 添加观察者 修改2015/8/15
private DataWatcher dataWatcher = new DataWatcher() {
@Override
public void onDataChanged(DownloadEntity downloadEntity) {
if (downloadEntity.getStatus() != DownloadStatus.downloading) {
LogUtils.uploadDownloadEvent(downloadEntity);
}
if (DownloadStatus.hijack.equals(downloadEntity.getStatus())) {
// 链接被劫持
processHijack(downloadEntity);
@ -171,16 +193,22 @@ public class MainActivity extends BaseActivity {
DownloadManager.getInstance(getApplicationContext()).cancel(downloadEntity.getUrl());
toast("该链接已失效!请联系管理员。");
EventBus.getDefault().post(new EBShowDialog(DOWNLOAD_NOT_FOUND, downloadEntity.getName()));
MtaHelper.onEventWithBasicDeviceInfo("下载失败弹窗",
"游戏", downloadEntity.getName(),
"平台", downloadEntity.getPlatform());
DialogUtils.showAlertDialog(AppManager.getInstance().currentActivity()
, "下载失败"
, "下载链接已失效,建议提交反馈"
, "立即反馈", "取消"
, () -> SuggestionActivity.startSuggestionActivity(AppManager.getInstance().currentActivity(),
SuggestType.gameQuestion, "notfound",
StringUtils.buildString(downloadEntity.getName(), ",问题反馈:下载链接失效"),
new SimpleGameEntity(downloadEntity.getGameId(), downloadEntity.getName(), "")), null);
return;
} else if (DownloadStatus.neterror.equals(downloadEntity.getStatus())
|| DownloadStatus.timeout.equals(downloadEntity.getStatus())) {
DownloadNotification.showWaitingNotification(MainActivity.this); // 系统通知
toast("网络不稳定,下载任务已暂停");
DataLogUtils.uploadNeterrorLog(MainActivity.this, downloadEntity);
@ -191,7 +219,7 @@ public class MainActivity extends BaseActivity {
if (DownloadStatus.done.equals(downloadEntity.getStatus())) {
if (downloadEntity.getName().contains(getString(R.string.app_name))) {
DataUtils.onEvent(MainActivity.this, "软件更新", "下载完成");
startActivity(PackageUtils.getInstallIntent(MainActivity.this, downloadEntity.getPath()));
startActivity(PackageUtils.getInstallIntent(MainActivity.this, downloadEntity.getPath(), true));
DataLogUtils.uploadUpgradeLog(MainActivity.this, "install"); //上传更新安装数据
} else {
statDoneEvent(downloadEntity);
@ -212,12 +240,13 @@ public class MainActivity extends BaseActivity {
}
if (!downloadEntity.isPluggable()) {
// 是否是自动安装
if (mSp.getBoolean("autoinstall", true)) {
if (mSp.getBoolean(SettingsFragment.AUTO_INSTALL_SP_KEY, true)) {
if (FileUtils.isEmptyFile(downloadEntity.getPath())) {
toast(R.string.install_failure_hint);
DownloadManager.getInstance(MainActivity.this).cancel(downloadEntity.getUrl());
} else {
if (PackageUtils.isCanLaunchSetup(getApplicationContext(), downloadEntity.getPath())) {
downloadEntity.getMeta().put(Constants.MARK_ALREADY_TRIGGERED_INSTALLATION, "YES");
startActivity(PackageUtils.getInstallIntent(MainActivity.this, downloadEntity.getPath()));
} else {
// 弹出卸载提示框
@ -244,13 +273,19 @@ public class MainActivity extends BaseActivity {
"游戏", downloadEntity.getName() + ":" + PlatformUtils.getInstance(getApplicationContext()).getPlatformName(downloadEntity.getPlatform()));
}
}
if (downloadEntity.getStatus() == DownloadStatus.done) {
EventBus.getDefault().post(new EBDownloadStatus("done", "", "", "", "", ""));
}
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStatusBarColor(Color.WHITE);
setStatusBarColor(Color.TRANSPARENT);
mSp = PreferenceManager.getDefaultSharedPreferences(this);
@ -328,6 +363,9 @@ public class MainActivity extends BaseActivity {
if (getIntent().getBooleanExtra(SWITCH_TO_COMMUNITY, false)) {
handler.postDelayed(this::switchToCommunityTabAndRefresh, 800);
}
if (getIntent().getBooleanExtra(SWITCH_TO_VIDEO, false)) {
handler.postDelayed(() -> mMainWrapperFragment.setCurrentItem(2), 800);
}
// 跳转至其它页面
if (getIntent() != null && getIntent().getExtras() != null && !isSkipped) {
@ -343,18 +381,42 @@ public class MainActivity extends BaseActivity {
// 上传数据
DataCollectionManager.getInstance(getApplicationContext()).upload();
// 获取默认配置
getGhzsSettings();
Config.getGhzsSettings();
// 检查助手更新
UpdateManager.getInstance(this).checkUpdate(true, null);
// 初始化PlatformUtils
PlatformUtils.getInstance(getApplicationContext());
});
//启动app删除视频缓存文件
AppExecutor.getIoExecutor().execute(() -> {
File cacheFileDirectory = StorageUtils.getIndividualCacheDirectory(this);
if (cacheFileDirectory.exists() && cacheFileDirectory.isDirectory()) {
for (File file : cacheFileDirectory.listFiles()) {
FileUtils.deleteFile(file.getPath());
}
}
//创建nomedia文件
File noMediaFile = new File(cacheFileDirectory.getParent(), ".nomedia");
if (!cacheFileDirectory.exists()) {
cacheFileDirectory.mkdirs();
}
try {
if (!noMediaFile.exists()) {
noMediaFile.createNewFile();
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100 && resultCode == SuggestSelectActivity.SUGGEST_TYPE_REQUEST) {
if (requestCode == 100 && resultCode == SuggestSelectFragment.SUGGEST_TYPE_REQUEST) {
showKefuReportDialog();
}
}
@ -365,7 +427,7 @@ public class MainActivity extends BaseActivity {
DialogUtils.showWarningDialog(MainActivity.this, "反馈成功", Html.fromHtml(str.substring(0, str.indexOf("红包奖励")) + "<font color='#FF0000'>红包奖励</font>"), "暂不", "联系客服",
() -> {
if (ShareUtils.isQQClientAvailable(this)) {
DirectUtils.directToQqConversation(this, "3467475980");
DirectUtils.directToQqConversation(this, null);
} else {
toast("本机未安装QQ应用");
}
@ -375,7 +437,8 @@ public class MainActivity extends BaseActivity {
@Override
protected void onDestroy() {
super.onDestroy();
DownloadManager.getInstance(this).removeObserver(dataWatcher);
// 退出后,同样需要更新通知栏进度
// DownloadManager.getInstance(this).removeObserver(dataWatcher);
handler.removeCallbacksAndMessages(null);
}
@ -413,6 +476,24 @@ public class MainActivity extends BaseActivity {
skipIntent.putExtras(bundle);
startActivity(skipIntent);
}
} else {
// 使用光环进行二次跳转的页面会经过这里
switch (to) {
case HOST_QQ:
DirectUtils.directToQqConversation(this, bundle.getString(KEY_DATA));
break;
case HOST_QQ_GROUP:
DirectUtils.directToQqGroup(this, bundle.getString(KEY_DATA));
break;
case HOST_WEB:
String url = bundle.getString(KEY_DATA) == null ? "" : bundle.getString(KEY_DATA);
if ("internal".equals(bundle.getString(KEY_TYPE))) {
DirectUtils.directToWebView(this, url, ENTRANCE_BROWSER);
} else {
DirectUtils.directToExternalBrowser(this, url);
}
break;
}
}
}
}
@ -421,10 +502,13 @@ public class MainActivity extends BaseActivity {
private void checkNotificationPermission() {
// 仅登录后再启动光环时请求一次权限
if (!SPUtils.getBoolean(Constants.HAS_REQUESTED_NOTIFICATION_PERMISSIONS)
/*if (!SPUtils.getBoolean(Constants.HAS_REQUESTED_NOTIFICATION_PERMISSIONS)
&& UserManager.getInstance().isLoggedIn()) {
SPUtils.setBoolean(Constants.HAS_REQUESTED_NOTIFICATION_PERMISSIONS, true);
showNotificationHintDialog();
}*/
if (UserManager.getInstance().isLoggedIn()) {
NotificationHelper.showNotificationHintDialog(NotificationUgc.LOGIN);
}
}
@ -455,6 +539,9 @@ public class MainActivity extends BaseActivity {
kv1.put("光环助手版本", BuildConfig.VERSION_NAME);
if (downloadEntity.isUpdate()) {
type = ExposureUtils.DownloadType.UPDATE;
if (downloadEntity.isPlugin()) {
type = ExposureUtils.DownloadType.PLUGIN_UPDATE;
}
DataUtils.onEvent(MainActivity.this, "游戏更新", downloadEntity.getName(), kv1);
} else {
type = ExposureUtils.DownloadType.DOWNLOAD;
@ -507,7 +594,7 @@ public class MainActivity extends BaseActivity {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0 && !mMainWrapperFragment.onHandleBackPressed()) {
DownloadEntity downloadEntity = null;
for (DownloadEntity entity : DownloadManager.getInstance(getApplicationContext()).getAll()) {
if (entity.getStatus().equals(DownloadStatus.done)) {
@ -532,12 +619,12 @@ public class MainActivity extends BaseActivity {
} else {
msg = "" + downloadEntity.getName() + "》已下载完但还未安装,是否立即安装?";
}
final String path = downloadEntity.getPath();
DownloadEntity finalDownloadEntity = downloadEntity;
DialogUtils.showWarningDialog(this,
"提示", msg,
"直接退出",
"立即安装",
() -> handler.postDelayed(() -> PackageUtils.launchSetup(MainActivity.this, path), 200),
() -> handler.postDelayed(() -> PackageUtils.launchSetup(MainActivity.this, finalDownloadEntity), 200),
this::finish);
return true;
}
@ -553,6 +640,11 @@ public class MainActivity extends BaseActivity {
return super.onKeyDown(keyCode, event);
}
@Override
protected boolean handleBackPressed() {
return true;
}
@Override
public void finish() {
// 上传数据
@ -582,6 +674,9 @@ public class MainActivity extends BaseActivity {
if (getIntent().getBooleanExtra(SWITCH_TO_COMMUNITY, false)) {
switchToCommunityTabAndRefresh();
}
if (getIntent().getBooleanExtra(SWITCH_TO_VIDEO, false)) {
mMainWrapperFragment.setCurrentItem(2);
}
}
private void switchToCommunityTabAndRefresh() {
@ -591,32 +686,6 @@ public class MainActivity extends BaseActivity {
EventBus.getDefault().post(new EBReuse(CommunityFragment.EB_RETRY_PAGE));
}
private void getGhzsSettings() {
String channel = HaloApp.getInstance().getChannel();
RetrofitManager.getInstance(this)
.getApi().getSettings(PackageUtils.getVersionName(), channel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<SettingsEntity>() {
@Override
public void onResponse(SettingsEntity response) {
Config.setSettings(response);
// 意见反馈
SharedPreferences.Editor edit = mSp.edit();
edit.putString(SuggestionActivity.SUGGESTION_HINT_TYPE,
GsonUtils.toJson(response.getSuggestion()));
edit.apply();
if (!mSp.getBoolean(Config.FIX_DOWNLOAD_KEY, false) && Config.isShow()) {
mSp.edit().putBoolean(Config.FIX_DOWNLOAD_KEY, true).apply();
}
EventBus.getDefault().post(new EBReuse("Refresh"));
}
});
}
private void checkRetryDownload() {
DownloadManager.getInstance(this).checkRetryDownload();
}
@ -711,7 +780,7 @@ public class MainActivity extends BaseActivity {
@SuppressLint("CheckResult")
private void showNotificationHintDialog() {
if (!SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_HINT)) {
if (!SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN)) {
RetrofitManager.getInstance(this).getApi().getBootPopup()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@ -801,7 +870,7 @@ public class MainActivity extends BaseActivity {
if (busNetworkState.isNetworkConnected()) {
checkRetryDownload();
if (Config.getSettings() == null) {
getGhzsSettings();
Config.getGhzsSettings();
}
mPackageViewModel.checkData();
@ -850,11 +919,11 @@ public class MainActivity extends BaseActivity {
ThirdPartyPackageHelper.saveGameId(mDownloadEntity.getPackageName(), mDownloadEntity.getGameId());
}
DownloadManager.getInstance(getApplicationContext()).cancel(
mDownloadEntity.getUrl(), false); // 默认不删除安装包 mSp.getBoolean("autodelete", true)
mDownloadEntity.getUrl(), false, true); // 默认不删除安装包 mSp.getBoolean("autodelete", true)
}
if (mSp.getBoolean("concerngame", true)) { //设置页面控制是否安装后自动关注
if (mSp.getBoolean(SettingsFragment.CONCERN_GAME_SP_KEY, true)) { //设置页面控制是否安装后自动关注
// 安装后关注游戏
DownloadEntity finalDownloadEntity = mDownloadEntity;
RetrofitManager.getInstance(this).getApi().getGameDigestByPackageName(UrlFilterUtils.getFilterQuery("package", packageName))
@ -901,6 +970,7 @@ public class MainActivity extends BaseActivity {
DataCollectionUtils.uploadInorunstall(this, busFour.getType(), busFour.getPackageName());
}
@SuppressWarnings("ResultOfMethodCallIgnored")
@SuppressLint("CheckResult")
private void postNewlyInstalledApp(String gameId, String packageName) {
@ -920,11 +990,20 @@ public class MainActivity extends BaseActivity {
.subscribe(new EmptyResponse<>());
if (!TextUtils.isEmpty(gameId) && UserManager.getInstance().isLoggedIn()) {
RetrofitManager.getInstance(MainActivity.this).getApi()
.postPlayedGame(UserManager.getInstance().getUserId(), gameId)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new EmptyResponse<>());
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("game_id", gameId);
jsonObject.put("package", packageName);
RequestBody rBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString());
RetrofitManager.getInstance(MainActivity.this).getApi()
.postPlayedGame(UserManager.getInstance().getUserId(), rBody)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new EmptyResponse<>());
} catch (JSONException e) {
e.printStackTrace();
}
}
}

View File

@ -55,6 +55,7 @@ import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.newsdetail.NewsDetailAdapter;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.halo.assistant.fragment.SettingsFragment;
import com.lightgame.download.DataWatcher;
import com.lightgame.download.DownloadEntity;
import com.lightgame.utils.Utils;
@ -297,7 +298,7 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
}
sp = PreferenceManager.getDefaultSharedPreferences(this);
fontsize = sp.getInt("fontsize", 1);
fontsize = sp.getInt(SettingsFragment.FONT_SIZE_SP_KEY, 1);
if (fontsize == 0) {
fontsize = 1;
}
@ -542,14 +543,14 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
if ((R11 - R12) > scrollSize && fontsize > 1) {
fontsize--;
adapter.setFontSize(fontsize);
sp.edit().putInt("fontsize", fontsize).apply();
sp.edit().putInt(SettingsFragment.FONT_SIZE_SP_KEY, fontsize).apply();
String fontSizeText = getFontSize(fontsize);
Utils.toast(this, fontSizeText);
}
if ((R11 - R12) < -scrollSize && fontsize < 4) {
fontsize++;
adapter.setFontSize(fontsize);
sp.edit().putInt("fontsize", fontsize).apply();
sp.edit().putInt(SettingsFragment.FONT_SIZE_SP_KEY, fontsize).apply();
String fontSizeText = getFontSize(fontsize);
Utils.toast(this, fontSizeText);
}

View File

@ -10,15 +10,15 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.gh.base.ToolBarActivity;
import com.gh.common.util.MessageShareUtils;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.QRCodeUtils;
import com.gh.common.util.ShareUtils;
import com.lightgame.utils.Utils;
import com.tencent.tauth.Tencent;
import androidx.annotation.NonNull;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
@ -72,6 +72,7 @@ public class ShareGhActivity extends ToolBarActivity {
@OnClick(R.id.gh_address_tv)
public void copyAddress() {
MtaHelper.onEvent("我的光环_新", "分享光环", "复制官网");
ClipboardManager cmb = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
cmb.setText(getString(R.string.gh_website_url_100));

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