Compare commits

...

1013 Commits
v2.6 ... v3.4.1

Author SHA1 Message Date
3cdc76b548 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-09-09 18:50:47 +08:00
b56ecfbf8f 优化开服表提示 2018-09-07 18:38:11 +08:00
27c0b4c497 还原 targetSdk 以及 MTA 更新 2018-09-07 17:57:07 +08:00
de1558d58f 提高 targetSDK 至 8.1,升级 MTA 版本 2018-09-07 14:53:37 +08:00
0197355126 Merge remote-tracking branch 'origin/dev' into dev 2018-09-07 11:07:34 +08:00
e66698d2bd 处理推送的通道问题 2018-09-07 11:07:14 +08:00
def5996c49 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-09-06 16:30:33 +08:00
700fd2e390 关注,粉丝增加分页 2018-09-06 16:30:24 +08:00
21a8eaafeb 去掉推送机型通道 2018-09-06 16:28:53 +08:00
4391891999 更改dexOptions 2018-09-06 10:47:00 +08:00
8302e8b5e0 修复游戏动态“推荐关注”无法出现问题 2018-09-06 10:02:15 +08:00
a8de52d5cd 修复游戏详情开服提示与开服日历底部对不齐问题,修改UmengMessageReceiver的启动方式 2018-09-05 16:05:05 +08:00
46a42c9212 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-09-05 09:34:15 +08:00
9ed97ea32c tinkerPatchName -> 3.4.1 2018-09-05 09:33:52 +08:00
4f087cdcc7 Merge remote-tracking branch 'origin/dev' into dev 2018-09-04 19:32:19 +08:00
4c4fcba2d2 修复推送的一些问题 2018-09-04 19:32:06 +08:00
69e9bfa7a9 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-09-04 16:22:52 +08:00
c3b29697bc 更改刷新Token失败处理顺序 2018-09-04 16:22:44 +08:00
f0937e8d1e 修复了点击专题大图带的路径的是游戏名字而不是专题名字的问题 2018-09-04 15:55:21 +08:00
85f713dc2d Merge remote-tracking branch 'origin/dev' into dev 2018-09-04 12:03:50 +08:00
cd146366c0 修复曝光事件统计插件升级时没有附带游戏名字的问题 2018-09-04 12:03:29 +08:00
08054ad6e5 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-09-04 11:34:02 +08:00
011b4b536a 修复Gif图片保存失败问题 2018-09-04 11:33:30 +08:00
d2e118180c 完善推送的内容过滤功能以及记录点击和忽略通知事件 2018-09-04 10:26:05 +08:00
93856925ba 更换个人主页问题和答案接口,修复Gif(文件名不是.gif)上传后显示成普通图片问题 2018-09-04 10:02:37 +08:00
da0a33798b Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-09-03 17:08:39 +08:00
33f4f2e60b 修复3.4闪退问题 2018-09-03 17:08:27 +08:00
5827583edc 修复一个 MTA 的统计多个参数时出现的 BUG 2018-09-03 14:28:02 +08:00
2b33d95329 修复一个 MTA 的统计 Bug 2018-09-03 09:52:27 +08:00
7f0be97170 去除无关内容 2018-08-31 01:22:18 +08:00
b6a0fa9196 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-31 01:04:33 +08:00
52c624e94b 修复游戏详情闪退 开服表UI优化 2018-08-31 01:04:22 +08:00
de847ac0d5 Merge remote-tracking branch 'origin/dev' into dev 2018-08-31 00:59:49 +08:00
2bb579fec7 修复了重复通知复用的问题 2018-08-31 00:59:38 +08:00
6a6b15fb14 修复游戏详情闪退 游戏新闻回退 2018-08-30 22:46:54 +08:00
81e6778148 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-30 21:25:18 +08:00
309a6a6425 ConnTimeout->5 2018-08-30 21:24:50 +08:00
65e5ca64a1 修复点击启动弹窗闪退的问题 2018-08-30 21:20:32 +08:00
69825d33ff 新增收到客服新信息时永远显示客服浮窗 2018-08-30 21:18:18 +08:00
ec4acd0043 修复图片无法保存问题 2018-08-30 20:30:52 +08:00
22bb168e49 合并 2018-08-30 20:17:11 +08:00
b7bea01eb1 修改okhttp超时时间,.如果数值超过10000-19999的全部统一显示为1.0W-1.9W 2018-08-30 20:16:24 +08:00
82c3591d25 部分接口增加 channel 字段 2018-08-30 20:02:58 +08:00
20d8de32ec 修复图片不能保存的问题 2018-08-30 19:54:10 +08:00
3976646f39 修复 IM 客服消息不及时的问题 2018-08-30 17:25:04 +08:00
c849d4e0b0 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-30 17:09:58 +08:00
671fab2fee 用户相关部分接口加上时间戳,修复答案编写时会上次本地图片链接问题 2018-08-30 17:09:53 +08:00
8491609da7 增加网络错误的 MTA 统计 2018-08-30 17:06:23 +08:00
67257748f9 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-30 15:52:40 +08:00
312a3fe7bb 修复搜索列表下载无法更新进度问题 2018-08-30 15:52:25 +08:00
2c16c54c96 增加 UI Executor 类 2018-08-30 15:51:30 +08:00
bbae5f0b9c 补充 MTA 统计事件 2018-08-30 14:06:23 +08:00
95022da700 修复从不同位置进入游戏详情显示不一致的问题 2018-08-30 10:00:17 +08:00
6471e95077 光环助手V3.4 RELEASE(20180828-1850)测试问题汇总(UI部分完成) 2018-08-29 20:26:14 +08:00
707e6f5d11 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-29 17:06:56 +08:00
66dfcc8064 个人主页的某些接口添加渠道号 2018-08-29 17:06:41 +08:00
0400b7d396 修复了消息弹窗标记已读造成的问题 2018-08-29 14:54:01 +08:00
96d4ca43ff Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-29 14:37:09 +08:00
d2c0699b66 UI微调 2018-08-29 14:36:35 +08:00
0e4cf2cd3a 修复 MTA 上报内容带有 HTML 元素的问题 2018-08-29 11:39:27 +08:00
8144a7e857 补充 MTA 统计需求 2018-08-29 11:03:43 +08:00
ea38698ac3 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-28 18:42:36 +08:00
d00b34ebdd 光环助手V3.4 RELEASE(20180828-0950)测试问题汇总 2018-08-28 18:42:21 +08:00
a4c285df6f 增加新补充的 MTA 统计需求 2018-08-28 17:50:20 +08:00
6dfd9d5b7a Rxjava merge->mergeDelayError 2018-08-28 17:41:05 +08:00
876f7317a8 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-28 14:23:32 +08:00
430a975e98 修复礼包淘号接口 2018-08-28 14:23:22 +08:00
f277319019 统一跳转至社区的逻辑,补充部分方法描述 2018-08-28 11:13:02 +08:00
6b9fedd289 Merge remote-tracking branch 'origin/dev' into dev 2018-08-28 08:39:55 +08:00
d0ad48ada2 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-27 20:21:40 +08:00
a6b7beed75 光环助手V3.4 RELEASE(20180827-0940)测试问题汇总 2018-08-27 20:21:12 +08:00
fa257e4a04 启动弹窗在下载完图片才弹出来 2018-08-27 19:59:19 +08:00
8d827b7275 Merge remote-tracking branch 'origin/dev' into dev 2018-08-27 19:18:30 +08:00
27d73b545c 完成 MTA 事件统计需求 2018-08-27 19:18:19 +08:00
7802d961a3 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-27 17:43:13 +08:00
d5d63371e3 修改退出登录逻辑 2018-08-27 17:43:05 +08:00
fcf1d38578 优化消息弹窗显示逻辑 2018-08-27 16:17:19 +08:00
fe17f817da 修复在 Mumu 模拟器上的一些 bug 2018-08-27 14:55:26 +08:00
bfa76c0fda Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-27 10:40:51 +08:00
2e1a99f905 个人动态时间格式修改 2018-08-27 10:39:47 +08:00
e7cb8e41b5 修复系统推送不能通过游戏报名进行限制的 bug 2018-08-27 09:52:40 +08:00
f88d4bde45 光环助手V3.4最后优化需求汇总(20180824) 2018-08-27 09:33:04 +08:00
b470194807 光环助手V3.4最后优化需求汇总(20180824) 2018-08-25 17:13:26 +08:00
ba5e3cb3eb 光环助手V3.4 RELEASE(20180823-1835)测试问题汇总 2018-08-25 15:30:15 +08:00
d5440b5d01 光环助手V3.4 UI优化汇总(20180823) 2018-08-25 11:00:49 +08:00
a8f3f27fb3 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-25 09:48:19 +08:00
bec06bfbf4 部分UI修改 2018-08-25 09:45:39 +08:00
9c510dc132 调整部分 UI 2018-08-24 19:05:36 +08:00
8302c99d57 增加部分 MTA 统计,修复部分 IM 的问题 2018-08-24 17:07:26 +08:00
5209e5b463 更新消息中心接口 2018-08-24 16:49:02 +08:00
663e5124fe 更新消息中心接口 2018-08-24 16:47:08 +08:00
dea2f569a1 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-23 18:18:40 +08:00
03d25eaeae 光环助手V3.4 RELEASE(20180821-1740)测试问题汇总 2018-08-23 18:18:32 +08:00
e84f56975d 修复一些客服 IM 的问题 2018-08-23 18:17:11 +08:00
a3a21efba3 避免七陌 SDK 的 emoji 在精简代码时被精简掉 2018-08-23 16:43:16 +08:00
1daa4f91b3 修复一部分社区跳转和消息通知的 bug 2018-08-23 15:45:39 +08:00
ee1ddbcdce 完成对 MTA 已有统计事件的优化,新事件待补充 http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/316 2018-08-23 09:56:59 +08:00
772549e543 解决游戏名字过长显示不全的问题 2018-08-22 17:37:01 +08:00
db537e756a 修正魅族推送的 ID 2018-08-22 15:35:27 +08:00
f9c236fd63 修复曝光统计的一些问题 2018-08-22 15:34:31 +08:00
f414ecee32 APP统计-应用数据, 数据库升级适配 2018-08-22 10:44:56 +08:00
5b1d0d5821 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/game/GameFragmentAdapter.kt
2018-08-21 17:33:26 +08:00
1c80ba56a5 光环助手V3.4 DEV(20180817-1930)测试问题汇总 2018-08-21 17:31:17 +08:00
a92044f815 去掉无用的 SO 支持,修复 IM 反馈没有内容的问题 2018-08-21 16:24:13 +08:00
00f94bf950 修复推荐入口不能跳社区的问题 2018-08-21 14:43:14 +08:00
e27f061a92 修复一些消息弹窗的问题 2018-08-21 14:29:49 +08:00
40d28948e1 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-20 18:08:59 +08:00
9b6e29d5f2 整理社区搜索相关页面 2018-08-20 18:08:47 +08:00
0ee000f08a 修复一些启动弹窗和客服 IM 的测试问题 2018-08-20 16:15:29 +08:00
6bdd021856 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-20 16:05:23 +08:00
301e14268a 光环助手V3.4 DEV(20180810)测试问题汇总 2018-08-20 16:05:11 +08:00
825ea594f4 修复社区的一些显示 bug 2018-08-20 11:37:39 +08:00
8fcb072abb 3.4数据统计需求(APP统计-应用数据 未完成) 2018-08-20 10:39:41 +08:00
f17a4e6372 完成关于问题详情和答案详情的 MTA 时间统计 2018-08-19 15:15:34 +08:00
a5b1202e5e AskLogUtils -> LogUtils 2018-08-17 15:43:52 +08:00
b5e025984c 禁言功能优化 2018-08-17 15:33:04 +08:00
33dba4e9bf Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-16 19:01:37 +08:00
92492b21ae 压缩算法优化 2018-08-16 19:01:25 +08:00
1c8ca4b8c2 补充跳转到社区的逻辑 2018-08-16 17:32:03 +08:00
466061222d UI微调 2018-08-16 17:03:24 +08:00
905e229142 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-16 16:31:09 +08:00
6906b96ef9 修复部分手机在答案编辑页面无法复制问题 2018-08-16 16:30:56 +08:00
fb748df3ce 增加退出 IM 聊天页面确认弹窗 2018-08-16 10:06:40 +08:00
844de786d0 光环助手V3.4优化需求汇总(20180814)(部分完成) 2018-08-15 18:45:19 +08:00
7dfe55014a IM 使用 Fresco 来显示图片 2018-08-15 18:24:40 +08:00
24f19e2a61 IM部分注册/反注册 位置修改 2018-08-15 15:28:47 +08:00
f947040241 IM 处理客服关闭聊天广播 2018-08-15 14:57:59 +08:00
569bb61545 简单集成七陌的客服 IM SDK,细节待完善 2018-08-15 14:33:31 +08:00
78ea8b3e73 光环助手V3.4优化需求汇总(20180814)(部分完成) 2018-08-15 11:42:12 +08:00
6b5056da41 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-14 17:43:10 +08:00
2a86546f1a 光环助手V3.4-意见反馈优化(完成) 2018-08-14 17:42:55 +08:00
d669fec902 意见反馈部分页面完成 2018-08-14 11:27:18 +08:00
3fc14b5194 修复 Webview 链接使用 HTTPS 但图片是 HTTP 时图片不加载的问题 2018-08-14 11:12:42 +08:00
4a3a039d0e 答案列表不显示Gif,优化消息中心(预防串行问题), 登录失败统计优化 2018-08-13 16:03:13 +08:00
1f43523f04 修复图片加载刷新后闪屏问题, 修复若干bug 2018-08-12 15:43:58 +08:00
26e23fa736 图片加载移动网络是先检查大图缓存再加载 2018-08-10 18:27:03 +08:00
958bce8d42 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-10 15:45:20 +08:00
8f15e52eb5 优化用户头像修改压缩上传 2018-08-10 15:44:06 +08:00
4bedede646 删掉网易七鱼相关代码 2018-08-10 14:11:32 +08:00
f66ee1721e Gif不受查看大图控制 2018-08-10 11:15:20 +08:00
138c5bb4c2 解决Fresco缓存查询异常问题 2018-08-10 10:13:05 +08:00
d1245a9a1e 去除RichEditor无用代码 2018-08-09 16:57:42 +08:00
561d6f7ea2 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-09 16:51:19 +08:00
d5992f7ed3 图片下发分类(小图:2G/3G 下发, 大图:4G/WiFi 下发) 2018-08-09 16:51:09 +08:00
d941aa0c71 基本完成启动时读取 META-INFO 里的 JSON 实现跳转的功能 2018-08-09 15:54:21 +08:00
7fa1d1e11b 【图片高清计划】前端加载图片显示规则优化 2018-08-08 18:31:53 +08:00
3edff028bf 图片详情和答案详情适配Gif 2018-08-08 15:15:43 +08:00
78d3c529c6 图片详情增加下载原图,答案详情对接新的图片显示规则 2018-08-08 09:43:11 +08:00
f0af2e280b 合并 2018-08-07 11:51:47 +08:00
34623163e6 重构图片详情, ImageUtils remove Companion 2018-08-07 11:47:51 +08:00
c90bd007c7 完善启动弹窗跳转逻辑 2018-08-07 10:28:38 +08:00
5f9637ec50 QQ 跳转适配 TIM 2018-08-07 10:23:25 +08:00
1a05e13b03 将 QQUtils 功能合并到 DirectUtils 2018-08-07 10:09:32 +08:00
c835f88695 新增启动页弹窗 2018-08-07 09:22:10 +08:00
5674fe76a2 压缩关键参数后台可以控制 2018-08-06 15:43:07 +08:00
e6933b4ded 删除无用代码 2018-08-06 09:36:03 +08:00
8a10dac03d 增加上传进度(目前只对接了:答案图片上传,问题图片上传) 2018-08-03 18:28:32 +08:00
de71ebad52 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-02 18:12:13 +08:00
310d1a2d5c 增加图片压缩工具类 2018-08-02 18:12:02 +08:00
30fcaf190b 新增存在未读消息弹出消息弹窗的功能 2018-08-02 15:44:50 +08:00
f004b15cf0 回答详情页增加认证icon 2018-08-02 10:59:43 +08:00
480c91feb5 处理推送透传信息 2018-08-02 10:16:32 +08:00
2c70b7eefc Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-08-01 18:05:53 +08:00
2be2513081 完善个人主页相关数据 2018-08-01 17:58:58 +08:00
48c0d5d2cd 去掉 8.0 设备获取 IMEI 时添加的叹号 2018-08-01 14:55:14 +08:00
3c5a6bcdec Merge remote-tracking branch 'origin/dev' into dev 2018-08-01 14:45:51 +08:00
bd2a3d529a 完成部分推送逻辑 2018-08-01 14:45:34 +08:00
6c0ac67cfa 对接社区相关搜索接口 2018-08-01 14:44:32 +08:00
cb07b8c9f4 支持从相关页面进入个人主页 2018-08-01 11:11:59 +08:00
e22be3f233 整理游戏详情动态文件 2018-07-31 17:42:28 +08:00
fd02f120c2 ... 2018-07-31 16:55:46 +08:00
6496b3dad6 合并 2018-07-31 16:50:14 +08:00
375b57cd3d 游戏详情增加答案数据 重构游戏详情动态(动态)页面 2018-07-31 16:44:13 +08:00
269265b054 基本完成推送逻辑 2018-07-31 14:52:34 +08:00
d74154080b 修复通过 URI 跳转至回答详情以及问答详情失效的问题 2018-07-31 14:21:16 +08:00
7471825a7c 用户操作历史增加跳转 2018-07-28 17:17:54 +08:00
90580316e8 个人中心增加'个性签名' 2018-07-28 16:38:41 +08:00
61e0ef2960 个人主页粉丝未读提示完成(未经过测试) 2018-07-28 15:53:34 +08:00
1125bb9b4c 个人主页对接数据 2018-07-28 14:50:28 +08:00
1e424a3791 修复由于layout id造成的打包错误 2018-07-27 16:01:18 +08:00
a901d95895 为用户头像添加认证 2018-07-27 15:41:01 +08:00
1a0a92c542 我的主页增加Ta的答案/Ta的问题 2018-07-27 15:30:15 +08:00
6ba8344292 完善社区搜索页面 2018-07-26 17:02:43 +08:00
38d2429183 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/res/layout/personal_home_top.xml
2018-07-26 14:57:06 +08:00
36c755f781 我的光环-新增个人主页功能(完善ListActivity,相关页面的优化) 2018-07-26 14:53:43 +08:00
093c731ba7 去掉设置暗色状态栏时反射出错的日志记录 2018-07-26 11:48:02 +08:00
eae9c11d72 提取用户认证的公用部分 2018-07-26 11:46:48 +08:00
3faae4b34c Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-07-25 18:42:15 +08:00
04eef35cbd 我的光环-新增个人主页功能(页面基本完成) 2018-07-25 18:42:04 +08:00
6b08cb2159 消息通知弹窗支持滑动清除 2018-07-25 11:05:20 +08:00
0777ca90e0 处理消息通知弹窗在使用虚拟按键的设备上的位置错误问题 2018-07-24 18:00:26 +08:00
4a322d07d9 光环助手版本升为3.4 2018-07-23 14:56:06 +08:00
df49f98e46 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-07-23 14:37:28 +08:00
122e3f6aa0 社区搜索重做基本完成(还差数据接口) 2018-07-23 14:32:46 +08:00
b902837b1c 使用 Kotlin Extension 简化消息弹窗动画代码 2018-07-23 11:08:46 +08:00
62639a9c79 初步实现简陋的消息弹窗动画 2018-07-20 16:21:17 +08:00
06dc7fc566 专题改造注解 2018-07-20 11:39:31 +08:00
ece6e099ec 更新友盟 消息完成自定义处理(需要和后端协商) 2018-07-20 11:00:29 +08:00
f3ce82275a 优化专题详情断网逻辑判断 2018-07-18 18:18:07 +08:00
4000dd8383 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-07-18 17:57:53 +08:00
d67053ce7c 专题详情重构基本完成 2018-07-18 17:33:51 +08:00
37bca1ee1c 将 ListViewModel 所对应的 ListRepository 合并到 ListViewModel 中,BaseList重新整理分层结构 2018-07-18 17:32:51 +08:00
229d3e9c88 新增简单的消息弹窗 2018-07-18 15:26:03 +08:00
c5d79a014b 曝光区分 debug 和 release 包,提交到不同的库 2018-07-17 10:14:00 +08:00
7d609b9c2a 更新 README 2018-07-16 17:44:41 +08:00
97eabcc600 使用 RxJava 优化自动搜索触发机制 2018-07-16 17:37:41 +08:00
932863a73f 将 ListViewModel 所对应的 ListRepository 合并到 ListViewModel 中,BaseList重新整理分层结构 2018-07-16 16:53:24 +08:00
4014fc27af Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-07-16 15:14:22 +08:00
fdf7be4a9f 解决Retrofit + RxJava2返回null时发生异常问题(Null is not a valid element) 2018-07-16 15:13:58 +08:00
b0fd801fec 避免 kotlin 非空异常 2018-07-16 14:03:11 +08:00
34c0bbe434 修改沉浸栏(背景:白色,字体:灰色)颜色,目前只适配了MIUI和Google原生系统 2018-07-16 11:22:41 +08:00
92c5697565 图片上传增加多图上传 2018-07-13 18:20:32 +08:00
445759e511 把 ListViewModel 的数据结构类型转换方式换为抽象方法,让继承的类实现,避免出现无响应的问题 2018-07-12 17:47:26 +08:00
a5b32cc099 完成网易七鱼基本功能的实现 2018-07-12 17:21:23 +08:00
7a5f24bfe7 图片压缩增加Gif判断(是否压缩Gif) 2018-07-12 14:42:25 +08:00
b40d58f1ae 修复下载全部开始 无法更新页面问题 2018-07-12 11:00:53 +08:00
ef28fc3616 constraintLayout 退档
整理问题编辑代码位置
2018-07-11 16:51:05 +08:00
80d2e2c488 constraintLayout 退档
整理问题编辑代码位置
2018-07-11 16:50:40 +08:00
ca07f10c9d http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/284 2018-07-11 16:15:53 +08:00
8a7fa127ba 社区精选(信息流)刷新数据统计格式更改(补锅 http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/260#note_6952) 2018-07-10 18:34:59 +08:00
8ee6039a2b 增加Retrofit FileRequestBody(进度监听) 2018-07-10 17:57:46 +08:00
aac58029f6 1.上拉加载默认文案是'上拉加载',手动拖动正式触发加载时才会显示为'加载中'
2.我的关注,如果已经有关注游戏,[热门游戏推荐] 区域改为默认是收起来;如果关注为空,则默认是展开;且展开后的高度要增加(加一行游戏的高度)
2018-07-09 18:00:52 +08:00
640a8d4e0f 合并更新依赖分支的代码 2018-07-09 14:35:02 +08:00
9f621696c1 Merge branch 'update_dependency' into dev
# Conflicts:
#	app/src/main/java/com/gh/common/util/ImageUtils.kt
#	app/src/main/java/com/gh/gamecenter/game/horizontal/GameHorizontalAdapter.kt
#	app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditFragment.java
#	app/src/main/java/com/gh/gamecenter/qa/ask/QuestionEditViewModel.kt
#	app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
2018-07-09 11:54:59 +08:00
a45fff7cca 使用retrofit上传图片以及引入luban图片压缩框架 2018-07-09 11:34:41 +08:00
8ba45deac9 修复MetaUtil getMac()为空导致的闪退
封包3.3.1
2018-07-06 17:49:49 +08:00
0c9f741847 新增渠道:GH_REFRESH(刷新版) 2018-07-06 15:31:00 +08:00
696f862633 专栏热门/精华 内容位置调换(文案不变) 2018-07-06 15:08:42 +08:00
f85e3c2602 tinker版本升为3.3.1 2018-07-06 14:34:28 +08:00
d2e3635034 增加开服表 时间去秒 2018-07-06 14:33:17 +08:00
8f37cbdfde 更新 AS 版本,优化包依赖源提高获取速度 2018-07-06 11:20:06 +08:00
3ffd6f74f1 完成 RxJava 版本的更新 2018-07-06 10:44:37 +08:00
72aa1474d3 下载控制(只要打开过下载那么就无法关闭(总的下载)) 2018-07-06 10:43:07 +08:00
3f9fb27642 更新一波依赖,RxJava2 的还没改完 2018-07-05 17:54:23 +08:00
6d134edb0a Merge remote-tracking branch 'origin/dev' into dev 2018-07-05 16:34:05 +08:00
7834e9d55a 修复 MTA 统计的序号问题 2018-07-05 16:33:56 +08:00
36ba95e2fd 问题编辑 标签名称去空格(文字后面的空格) 2018-07-05 14:58:06 +08:00
00deba962e 修复若干BUG GH_TEST渠道号自动弄成刷新版 2018-07-05 11:19:59 +08:00
4713594c7e Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-07-04 18:30:18 +08:00
688a169e4e 光环助手V3.3 RELEASE(20180703-1700)测试问题汇总 2018-07-04 18:29:05 +08:00
3ace50b526 在问答 Tab 不在当前屏幕显示时不弹信息流加载错误的 Toast 2018-07-04 17:55:42 +08:00
a9dbb4850f 曝光信息里增加用户 id(若存在) 2018-07-04 15:55:45 +08:00
910cda8dbc Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-07-03 16:24:33 +08:00
7d29c0d883 光环助手V3.3 RELEASE(20180701-0730)测试问题汇总 2018-07-03 16:24:20 +08:00
3f274cb4ea 修改下拉刷新提示的字体大小 2018-07-03 15:30:47 +08:00
56d378b6dc 去掉曝光路径里重复的方括号 2018-07-03 11:09:32 +08:00
03eebf2c07 修复第三方下拉刷新依赖的造成的闪退问题 2018-07-03 09:55:53 +08:00
cf41572db7 避免重复获取曝光所需 Meta 造成滑动卡顿 2018-07-02 17:26:04 +08:00
a2361254da 曝光统计Meta相关数据允许为空 2018-07-02 10:42:28 +08:00
233f786ee0 3.3-TinkerBase 2018-07-02 09:36:09 +08:00
8590614272 开服表修改 2018-06-30 07:33:34 +08:00
e179de3d0d 开服表修改 2018-06-30 07:26:07 +08:00
defe3bb3ff Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-30 06:58:18 +08:00
24ad3e0265 优化 2018-06-30 06:56:38 +08:00
e54646afcc 增加部分 MTA 统计 2018-06-30 06:43:52 +08:00
4c62032c66 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-30 04:56:27 +08:00
627affe0f7 2018-6-30 02:25:25 测试补充: 2018-06-30 04:56:17 +08:00
b5e21bef1e 取消信息流的自动加载下一页 2018-06-30 04:15:14 +08:00
95999791bd 第一次进入社区不显示下拉刷新 2018-06-30 03:46:27 +08:00
07cba611cf Merge remote-tracking branch 'origin/dev' into dev 2018-06-30 01:06:44 +08:00
29c2dfc1e5 避免曝光来源出现两个方括号嵌套的问题 2018-06-30 01:06:34 +08:00
6b904b9213 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-30 01:02:29 +08:00
7e15307b46 光环助手V3.3 RELEASE(20180629-2135)测试问题汇总 2018-06-30 01:01:56 +08:00
626913c6ff 为一些列表页面添加单页数量过少自动尝试加载下一页的功能 2018-06-30 00:50:15 +08:00
00b98e4da9 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-29 23:09:52 +08:00
67f565bee0 解决切换社区卡在"正在加载"的问题 2018-06-29 23:07:07 +08:00
9eedf46294 光环助手V3.3 RELEASE(20180629-1610)测试问题汇总(前端) 2018-06-29 21:20:08 +08:00
810783da9c 修复统计曝光所造成的点击横向排布图标闪退的问题 2018-06-29 20:13:19 +08:00
39dfe334ed Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-29 18:28:09 +08:00
1a985f2a7e 修复PackageManage导致的闪退问题 2018-06-29 18:27:46 +08:00
35af46e3eb 修复PackageManage导致的闪退问题 2018-06-29 18:27:33 +08:00
3eefadd83b 修复分类页的复用问题 2018-06-29 18:14:22 +08:00
0fbbd79bbd Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-29 15:24:30 +08:00
84eee14363 光环助手V3.3 RELEASE(20180628-1630)测试问题汇总(前端) 2018-06-29 15:24:23 +08:00
8f7ce5d148 更换切换专题的 ICON 2018-06-29 14:44:55 +08:00
5ed2fa4a0c 信息流下拉刷新错误时不显示蓝条 2018-06-29 11:33:05 +08:00
e5a06f7a3f 修复分类文字换行问题 2018-06-29 11:23:26 +08:00
f0ef1c7a76 基本信息流完成下拉刷新新样式 2018-06-29 11:18:00 +08:00
76ea9a4ba4 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/res/layout/game_horizontal_list.xml
2018-06-28 15:50:01 +08:00
33454005c3 光环助手V3.3 RELEASE(20180627-1700)测试问题汇总 2018-06-28 15:48:30 +08:00
37b6e6bce0 分类页适配高 DPI 设备 2018-06-28 10:41:13 +08:00
aaa9aab066 避免 NoSuchMethod Error. 2018-06-28 10:23:08 +08:00
e8669cc0cf Merge remote-tracking branch 'origin/dev' into dev 2018-06-27 18:27:06 +08:00
ddb226823f UI 微调 2018-06-27 18:26:54 +08:00
76eca47979 首页游戏添加初始化下载(更新下载进度) 2018-06-27 18:26:50 +08:00
bcac6944a0 总开服表更换悬浮按钮图片 定位到当前时间去除动画(目的是快速定位) 2018-06-27 18:08:32 +08:00
d9aa1c428d Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-27 15:32:51 +08:00
85c779ecd2 光环助手V3.3 RELEASE(20180626-1710)测试问题汇总 2018-06-27 15:32:42 +08:00
87a67470fd 修复闪退问题 2018-06-27 15:31:32 +08:00
be4142ad96 微调分类样式 2018-06-27 15:21:29 +08:00
5a26f7735d 首页入口修改 2018-06-26 18:22:54 +08:00
11ec77ad99 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/game/GameFragmentAdapter.kt
2018-06-26 17:32:21 +08:00
2da4182ee1 推荐入口增加跳转类型 2018-06-26 17:28:30 +08:00
d17ad6a497 光环助手V3.3 DEV(20180622-1845)测试问题汇总(前端) 2018-06-26 15:24:04 +08:00
1abc0ecc79 光环助手V3.3-开服表优化需求汇总(20180625)(除了新增开服清空时间 其余完成) 2018-06-26 09:52:54 +08:00
51ee8c841b 分类列表使用板名字作为标题 2018-06-26 09:39:10 +08:00
0636d2276b 修复游戏详情页面和开服表详情页面滑动冲突问题 2018-06-25 16:16:54 +08:00
bffee14882 曝光操作使用单一线程处理避免数据错误 2018-06-25 15:12:43 +08:00
93f2ed3a09 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-25 14:53:12 +08:00
c7b0ed26ae 避免 Kotlin 检测非空对象为空时崩溃 2018-06-25 14:50:57 +08:00
e75ade83cb Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-25 14:22:47 +08:00
3e4f5d6361 修复在模拟器上崩溃的问题 -> https://youtrack.jetbrains.com/issue/KT-20928 2018-06-25 11:43:48 +08:00
999bc9f720 光环助手V3.2 DEV(20180620-2000)测试问题汇总(部分完成) 2018-06-25 11:15:27 +08:00
cca068821b 添加 MTA 统计 http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/264 2018-06-24 17:15:40 +08:00
6d05a00488 光环助手V3.2 DEV(20180620-2000)测试问题汇总(部分完成) 2018-06-22 18:40:27 +08:00
ba3450f2b3 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-22 17:08:21 +08:00
57c084d512 曝光路径不传空(null) 2018-06-22 17:04:41 +08:00
c956f35e07 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-22 16:23:38 +08:00
c44353fa13 网络诊断 完成 2018-06-22 16:22:20 +08:00
8ebdc924f3 更换曝光提交地址 2018-06-22 11:46:43 +08:00
3923dd377d 曝光数据结构加上渠道版本 2018-06-22 10:58:35 +08:00
82eea64035 避免越界崩溃 2018-06-21 18:28:22 +08:00
10229e59f6 问题新增空白跳转 2018-06-21 18:18:02 +08:00
8c2583eab3 问答精选刷新修改 2018-06-21 17:20:27 +08:00
f9ef4851fb Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-21 17:07:21 +08:00
d07b99fd98 问答精选(信息流)优化 2018-06-21 17:06:22 +08:00
b23ce2adc3 删除部分无用的 MTA 统计代码 2018-06-21 16:34:33 +08:00
c4f2899e07 信息流增加下拉刷新 2018-06-21 15:59:04 +08:00
ebb20f5c38 Proguard 增加 @Keep 注释 2018-06-21 15:57:50 +08:00
08aaae1b02 处理曝光临近上限时可能出现的重复提交问题 2018-06-21 10:25:56 +08:00
4aaef11f9c Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-20 19:22:45 +08:00
2d0d253149 光环助手V3.3优化需求汇总(20180614)(还有小部分未完成) 2018-06-20 19:22:23 +08:00
875c0b8c16 基本完成首页专题、专题详情、分类详情的曝光统计需求 http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/253 2018-06-20 17:22:40 +08:00
3e285a4466 我的光环移除我的游戏列表 2018-06-19 19:57:37 +08:00
76e91265d5 社区选择游戏改版完成 2018-06-19 19:46:31 +08:00
47482ba793 光环助手V3.3-游戏专题样式强化(补充测试完成) 2018-06-19 14:37:33 +08:00
685c38dcf7 版本升为3.3 新增开服新增/修改完成数据同步 2018-06-15 18:30:17 +08:00
240d97cdd5 修复无法提交实名信息问题 2018-06-14 17:40:04 +08:00
cd891d4378 问答新增专栏功能(完成) 2018-06-14 16:15:29 +08:00
b9c05483d0 解决首页插件化区域下载中无法点击问题 2018-06-14 11:21:46 +08:00
190c534dba Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/game/GameFragmentAdapter.kt
2018-06-13 17:26:53 +08:00
5cc13d8161 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/game/GameFragmentAdapter.kt
2018-06-13 17:26:31 +08:00
81ac870c62 问答新增专栏功能(界面基本完成) 2018-06-13 16:50:43 +08:00
9eab5c3d4c 新增游戏分类 http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/250 2018-06-12 19:21:46 +08:00
f4a4ae7eb3 游戏板块完成 2018-06-12 14:25:16 +08:00
4b2715e97d Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-06-12 10:27:16 +08:00
983e546a64 对接游戏板块 2018-06-12 10:27:00 +08:00
d7161578b0 添加kotlin 序列号插件 2018-06-12 10:26:20 +08:00
d8683068c1 完善游戏插件化区域更新页面问题 2018-06-11 17:31:46 +08:00
efcea45819 增加 TODO @kyh 2018-06-11 17:16:11 +08:00
28f89aa0ad 重构PackageManager 2018-06-10 18:34:06 +08:00
309d42fdc1 整理代码(首页游戏分包) 2018-06-10 17:08:41 +08:00
f8f45182ce 首页游戏重做(对接相关接口) 2018-06-10 16:14:12 +08:00
5f08dee0e0 首页游戏重做(专题大图增强) 2018-06-08 18:15:55 +08:00
deea0f3f83 首页游戏重做(横向专题完成) 2018-06-07 18:27:11 +08:00
2090c5950f 首页游戏重做(页面处理基本完成) 2018-06-07 11:34:01 +08:00
02dcbdba02 首页游戏重做(初步完成) 2018-06-06 18:00:50 +08:00
ee44b1986f 增加ExpendTextView(textView增加...全文按钮) 2018-06-05 11:52:11 +08:00
16bc7b1e75 开服表game server字段修改,同一时段多个游戏合并 2018-06-04 14:43:36 +08:00
65bc06b195 总开服表完善(还差定位到当前时间位置) 2018-06-03 15:53:51 +08:00
06734d6274 总开服表 完成下个节点 2018-06-01 19:20:56 +08:00
e1dcd72a79 修改游戏详情开服表样式 2018-06-01 15:55:28 +08:00
3429a27354 新增/修改开服完成 2018-06-01 15:20:06 +08:00
7af99a5ed5 修改开服解决数据同步问题(一条更改全部发生改变) 2018-06-01 11:52:12 +08:00
d7833cd07f 游戏详情开服表修改已完成 2018-06-01 11:22:40 +08:00
a9b885c97f 添加/修改 开服对接接口 2018-05-31 20:28:12 +08:00
5eb815dba7 添加开服继续优化(还差post请求) 2018-05-31 17:35:12 +08:00
9797841280 添加开服继续优化(已完成自动填充,和部分post判断) 2018-05-31 15:41:59 +08:00
a2382be034 删除UserSea相关 2018-05-30 19:35:39 +08:00
081ce01664 完善新增开服信息 2018-05-30 19:22:20 +08:00
eddb8a933c 接口版本升级3.3 开服server字段修改 2018-05-30 11:41:22 +08:00
7a019cc465 完善修改开服信息 2018-05-30 11:14:21 +08:00
08e8846af8 修改开服,新增开服(未完善) 2018-05-29 19:43:34 +08:00
67d6cc6f05 游戏详情开服日历修改 2018-05-29 10:03:49 +08:00
1946478ce4 数据库版本兼容, 登录数据存储位置改成sp 2018-05-28 10:01:36 +08:00
5689cdbafe 合并UserManager和RefreshTokenManager 2018-05-25 16:30:59 +08:00
44adfdede8 修改文章查看对话 跳转按钮(跳转完整详情)样式 2018-05-25 15:29:59 +08:00
2992e3ca64 我的光环-我的游戏完成 2018-05-25 14:10:57 +08:00
ffbbd44beb 我的光环-已安装的游戏(完成部分,暂时搁置,需求未定) 2018-05-24 18:15:59 +08:00
3990515dc5 光环助手V3.3-个人中心增加实名认证功能(功能完成,还差接口对接) 2018-05-23 15:46:05 +08:00
2bd218fd95 光环助手V3.3-我的光环优化汇总(完成:2.3.6.7.8.9.10)
光环助手V3.3优化需求汇总(20180520)(UI相关)
2018-05-22 17:12:22 +08:00
1a02239dd2 光环助手V3.3优化需求汇总(20180520)完成:2.4.5.6.7.8 2018-05-21 17:17:27 +08:00
a5a5e38d5c refactor_questionedit分支合并到dev(后续整理) 2018-05-21 10:32:33 +08:00
9ebf2be016 refactor_questionedit分支合并到dev 2018-05-21 10:29:24 +08:00
3e488d28cd 社区相关整理 2018-05-21 09:56:34 +08:00
ce311d9b17 修改登录相关的检验与重试逻辑 2018-05-18 10:16:03 +08:00
843a263b3f 问答相关分包整理 2018-05-16 16:55:52 +08:00
7e350cac41 下载劫持接入MTA,优化下载(有效防止解析包错误) 2018-05-15 19:01:17 +08:00
447b7b35ef toolbar修改完成 2018-05-14 17:33:12 +08:00
6e9edabd94 修复登录掉线问题,对接错误统计需求(MTA)光环助手V3.2.2需求汇总 2018-05-11 17:31:43 +08:00
68cfdc57c8 问题提问(整理代码) 2018-05-09 16:39:45 +08:00
81e0f1d9cc 问题提问databinding 升级 buildToolsVersion 2018-05-09 11:47:17 +08:00
5436775b31 搜索提示框顶部加上蓝线 2018-05-07 15:32:14 +08:00
b8f5c2ddbd 问题编辑改造还差搜索提示框顶部蓝线 2018-05-07 11:27:55 +08:00
da433bfb5b 问题编辑改造-标题搜索提示初步完成 2018-05-05 18:41:13 +08:00
50209aa6ed 问题编辑改造(标题搜索提示未完成) 2018-05-05 15:33:07 +08:00
665fbb0f6c PATCH_VERSION_NAME 升级为 3.2.1 2018-05-03 17:39:26 +08:00
fd0921870d 修复3.2的一些bug 2018-05-03 10:34:36 +08:00
568ff5cb1e 问题编辑重构 2018-05-02 15:19:11 +08:00
0cc78b1055 3.2 tinker base 2018-04-28 14:52:09 +08:00
6dc3b5c382 修复专题分页异常问题 2018-04-27 06:27:29 +08:00
9ac373bf0e 光环助手V3.2 RELEASE(20180427-0410)测试问题汇总 2018-04-27 06:08:15 +08:00
02f96f9083 Merge remote-tracking branch 'origin/dev' into dev 2018-04-27 05:59:14 +08:00
c74997f306 修复切换选择游戏,社区专题会显示到原来的社区再更新为新社区的问题 2018-04-27 05:59:05 +08:00
58d4f22a6b 光环助手V3.2 RELEASE(20180427-0138)测试问题汇总 2018-04-27 03:58:24 +08:00
c5cf1c168e 答案被删除时隐藏收藏和更多按钮 2018-04-27 02:26:24 +08:00
36638a63ca ... 2018-04-27 02:04:06 +08:00
07de30ceea 统一投票样式,选择游戏入口显示小红点 2018-04-27 01:27:13 +08:00
35e15263b0 光环助手V3.2 RELEASE(20180426-2223)测试问题汇总(除2.8.9.10其他完成) 2018-04-27 01:26:03 +08:00
420867378b room数据库版本改为4 2018-04-26 22:41:52 +08:00
0cc183df22 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-04-26 21:57:56 +08:00
eb557ca9bd 光环助手V3.2 RELEASE(20180426-1800)测试问题汇总(1.2.9.10) 2018-04-26 21:57:44 +08:00
72b39a5982 回答详情回答过快增加 Toast 提醒,移动网络点击所有缩略图后隐藏 [显示大图] 按钮 2018-04-26 21:36:32 +08:00
b96ee6bc19 修复第二次启动光环助手,点击“问答”出现的引导图,点击“我知道了”前面的“我知道”没有反应 2018-04-26 18:06:47 +08:00
684fa318ec 接口limit改为page_size,修复游戏列表下载与详情下载安装判断不一致问题,安装游戏删除addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 2018-04-26 17:09:16 +08:00
29faea14c6 光环助手V3.2 RELEASE(20180424-1820)测试问题汇总(完成部分) 2018-04-25 19:26:47 +08:00
c25f7a13db 游戏搜索以及社区搜索UI微调 2018-04-24 20:10:08 +08:00
715edd77e0 TimestampUtils 修改 2018-04-24 18:31:00 +08:00
25cc825ea6 光环助手V3.2 RELEASE(20180422-1800)测试问题汇总 2018-04-24 17:52:53 +08:00
f7e7819b84 修复UserManager equals判断问题 2018-04-23 17:27:41 +08:00
d305315d7e 光环助手V3.2 RELEASE(20180419-1810)测试问题汇总(完成) 2018-04-23 16:50:36 +08:00
965d756cba 光环助手V3.2 RELEASE(20180419-1810)UI问题汇总 2018-04-23 16:13:05 +08:00
29a19b5df6 光环助手V3.2 RELEASE(20180419-1810)测试问题汇总(运营汇总) 2018-04-23 11:09:00 +08:00
cb2cdd98e8 光环助手V3.2 RELEASE(20180419-1810)测试问题汇总(三.9和评论未完成) 2018-04-22 18:52:08 +08:00
da79a972f7 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-04-20 17:39:14 +08:00
3c13eff2cf Merge remote-tracking branch 'origin/dev' into dev 2018-04-19 18:36:34 +08:00
7050070310 修复评论弹窗没登录也能提交的问题问题 2018-04-19 18:36:14 +08:00
1dca4e8c0a 光环助手V3.2 RELEASE(20180418-1420)测试问题汇总(完成) 2018-04-19 18:00:23 +08:00
1163e04aaf Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-04-19 16:49:55 +08:00
73bc256ce6 光环助手V3.2 RELEASE(20180418-1420)测试问题汇总(部分完成) 2018-04-19 16:49:51 +08:00
df78db5686 UI微调 2018-04-19 16:42:08 +08:00
b64ceaf5d4 微调精选推荐的代码结构 2018-04-19 15:38:43 +08:00
eb9b4cd132 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-04-19 11:35:18 +08:00
b9eec94644 更改 AnswerEntity db key 2018-04-19 11:35:07 +08:00
4e388ec3d7 问答精选数据流修改 2018-04-19 11:13:23 +08:00
a5069789b3 问题/答案/评论 提交时增加限制(5秒内只能提交1次) 2018-04-19 10:59:41 +08:00
3797fd85ad 回答列表补充评论数 2018-04-19 10:43:30 +08:00
f0b0423872 修复新增回答后问题详情页面出现两条相同数据的问题 2018-04-19 09:55:30 +08:00
e5daf1d29f 修复问题详情和回答详情的部分问题 http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/210 2018-04-18 21:19:50 +08:00
2b9f40a976 修复文章列表为空导致的闪退问题 2018-04-18 16:13:01 +08:00
05fbf28d2b 部分接口修改 2018-04-18 14:18:51 +08:00
e54d06def9 签到逻辑修改(保存本地数据库) 2018-04-18 10:12:37 +08:00
840eff3cc4 光环助手V3.2 DEV(20180415-1700)测试问题汇总
http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/207
2018-04-17 15:16:25 +08:00
a0737d0010 fix issues http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/203 2018-04-16 17:57:59 +08:00
9d93df888e 修复已知bug 2018-04-16 10:15:23 +08:00
90fbb235c3 光环助手V3.2 DEV(20180413-2100)测试问题汇总
http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/206
2018-04-15 16:37:44 +08:00
9be884c672 间距调整 2018-04-13 14:36:12 +08:00
550a4cdecf Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-04-13 14:13:53 +08:00
0d883b76fe 光环助手V3.2 DEV(20180412-1000)测试问题汇总(完成部分) 2018-04-13 14:13:41 +08:00
e3c3101cab Merge remote-tracking branch 'origin/dev' into dev 2018-04-13 11:26:51 +08:00
cce289253d 修复回答详情以及评论列表的一些问题 http://gitlab.ghzhushou.com/pm/issues-Inbox/issues/345 2018-04-13 11:26:32 +08:00
2102dd729c 光环助手V3.2数据统计需求(MTA)(完成) 2018-04-12 18:37:00 +08:00
347a83cf0f 统一DataUtils 2018-04-12 17:08:50 +08:00
1f8d573fad Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-04-12 16:53:10 +08:00
72b6c2a176 Menu全部初始化放在onActivityCreated,页面间距修改 2018-04-12 16:53:01 +08:00
743e3660e9 微调回答评论列表UI 2018-04-12 15:27:22 +08:00
2ab6a49bec Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-04-12 14:43:41 +08:00
1e31e13384 修复已知BUG OkHttpNetworkInterceptor去除接口404处理 2018-04-12 14:42:15 +08:00
f77fbe680f 1、回答评论列表答案作者显示作者
2、修复回答详情页查看大图滑动后返回依旧不是大图的问题
2018-04-12 14:19:12 +08:00
53c55a3f36 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-04-11 21:32:18 +08:00
18d11e3421 删除无用图标 2018-04-11 21:32:10 +08:00
bf42834051 光环助手V3.2 DEV(20180410-1140)测试问题汇总(部分未完成)
光环助手V3.2 DEV(20180410-1140)文案优化(部分未完成)
2018-04-11 21:31:40 +08:00
ee6337276c 回答详情也以及回答列表问题修复 2018-04-11 19:01:06 +08:00
cdc001b43e Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-04-11 11:19:31 +08:00
f3eeaddec8 光环助手V3.2数据统计需求(登录,问答精选刷新) 2018-04-11 10:45:17 +08:00
b8e1e4e21c 首页-下载,下载列表右边button未与上方全部开始对齐,列表下载条占位往左扣减5dp 2018-04-10 21:07:57 +08:00
64f2c83894 为所有页面添加Activity(为了接入MTA页面访问统计) 2018-04-10 20:50:19 +08:00
f9211e17a1 修改问答评论页UI 2018-04-10 20:09:36 +08:00
f0c952848a 修复部分已知bug 2018-04-10 16:15:07 +08:00
c736068d0e 光环助手V3.2其它优化汇总 2018-04-10 11:34:39 +08:00
e0c9d43f02 重新整理签到 2018-04-09 10:25:12 +08:00
0a4b657a85 修复由于xml id问题导致的打包失败 2018-04-08 18:08:56 +08:00
0121d9601c 游戏求版本ListFragment改造 2018-04-07 17:34:10 +08:00
371a450f5a 首页游戏执行分页操作 2018-04-07 15:38:43 +08:00
2796145d26 我的光环-签到功能优化(完成) 2018-04-07 14:53:28 +08:00
5a662ac72b 升级 OkHttp 依赖来解决 HTTP/2 连接问题 (http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/193) 2018-04-04 16:24:35 +08:00
6cd62cbd0a 回答详情页滑动时显示问题标题 2018-04-04 11:07:42 +08:00
299fa1a107 修复社区相关举报跳转至反馈页面没有提示选项问题 2018-04-02 18:30:43 +08:00
c39ba2e17e issues测试以及整理 2018-04-02 17:51:29 +08:00
414b5b3861 列表点击逻辑修改,助手版本升为3.2 2018-04-02 16:16:49 +08:00
6f89f4acce Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-04-02 14:51:18 +08:00
5f09fd1fa3 问答精选新增专题功能(完成) 2018-04-02 14:51:04 +08:00
00f1b0e8a3 Merge remote-tracking branch 'origin/dev' into dev 2018-04-02 11:14:37 +08:00
4473d0f787 修改回答详情页顶部title 2018-04-02 11:14:25 +08:00
d5255f91d0 修复问题详情闪退问题,修改CheckLoginUtils 2018-04-01 10:04:28 +08:00
57a3479144 问答精选列表数据流刷新(完成) 2018-03-30 18:21:24 +08:00
82c4ebf375 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-03-30 16:03:33 +08:00
23ca884684 所有接口offset改为page(完成) 2018-03-30 16:01:41 +08:00
cdfa999b05 评论弹窗显示条数 2018-03-29 18:28:47 +08:00
224092b30a 根据接口字段变动修改回答评论列表 2018-03-29 18:18:26 +08:00
8daefb2e42 消息中心改造基本完成(还差测试) 2018-03-29 17:51:14 +08:00
c0c0ef979d Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
2018-03-28 17:28:12 +08:00
6f0738cebb 提问问题/修改问题(完成) 2018-03-28 17:22:24 +08:00
3c352921bb 根据接口变动修改回答详情页细节 2018-03-28 11:53:15 +08:00
4df8f18cc4 V3.2Api接口更改(分页改为page未完成) 2018-03-28 10:01:10 +08:00
120acdefc6 Resolve conflict. 2018-03-27 10:24:00 +08:00
7eb31085b0 修改回答详情评论接口传参 2018-03-27 10:16:51 +08:00
17a3446be4 增加回答详情页菜单选项弹窗 2018-03-26 10:25:07 +08:00
d713c67c9b 我的光环-消息中心改版 2018-03-24 18:33:10 +08:00
76d788ee66 增加部分回答详情评论的接口 2018-03-23 18:09:52 +08:00
1cf13fc2a1 提问页面流程优化(还差接口调试) 2018-03-23 16:44:09 +08:00
de08d4d32d 为回答详情添加评论(增加部分UI 2018-03-22 18:32:09 +08:00
dce3a91156 删除QuestionsDetailActivity 2018-03-22 16:48:17 +08:00
38bf17c932 问题详情与邀请回答优化(完成) 2018-03-22 16:31:02 +08:00
5d0ccb9a34 光环助手V3.2 CTA按钮样式优化方案(完成) 2018-03-21 11:58:15 +08:00
b557afde2c ListRepository add todo 2018-03-21 10:44:58 +08:00
ea9375c20e baseList多接口兼容完成 2018-03-21 10:41:51 +08:00
fa464a9f1d baseList多接口-资讯页面(完成) 2018-03-20 17:33:06 +08:00
b3ff6ea991 baseList多接口-资讯页面(未完成) 2018-03-20 15:22:20 +08:00
f9dbdd4aa8 baseList 兼容多接口列表 2018-03-19 18:15:08 +08:00
21d06d97ef 更改主题色(包括一些按钮的调整) 2018-03-16 18:24:02 +08:00
fb28a49537 所有TabLayout指示器统一长度 2018-03-16 15:31:07 +08:00
d124504d5b 详情(游戏,文章,礼包)下载改造完成 2018-03-15 17:14:34 +08:00
0c69e0c5e5 更改Fragment初始化Toolbar Menu的位置(onCreate ->onActivityCreated) 2018-03-13 16:38:55 +08:00
39aee1ce89 首页+发现+我的光环 页面优化:http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/175(全部完成) 2018-03-13 15:01:01 +08:00
b3fe87b79a 光环助手V3.2 其它UI优化汇总:http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/176(除第二点外其他的完成) 2018-03-13 11:45:56 +08:00
2dfdc17523 Merge branch 'plugin_control' into dev 2018-03-12 17:53:12 +08:00
c208e7f72d 3.1.1封包(0.0) 2018-02-07 21:00:05 +08:00
8722d0a65b 更改BaseList的数据传递和刷新方式 2018-02-07 19:29:47 +08:00
54f044dfa0 修复部分bug 2018-02-07 14:43:40 +08:00
b854a6dfef WebFragment onActivityResult 数据非空判断 2018-02-06 15:42:57 +08:00
badb99da59 tinker 版本升为3.1.1 准备打补丁包 2018-02-05 15:23:32 +08:00
30d99dbe54 修复切换社区时问答页面销毁导致无法更新问题 2018-02-05 15:12:39 +08:00
c44c4e8b2d 修复切换社区时问答页面销毁导致无法更新问题 2018-02-05 15:12:24 +08:00
656b2f469b NormalActivity getMenuItem 非空判断 2018-02-05 15:04:07 +08:00
39e17842cc bug修复 2018-02-05 14:23:31 +08:00
57f7c0bb31 .gitignore增加选项 2018-02-03 17:51:27 +08:00
76b03fa68b list大小判断 2018-02-03 17:47:41 +08:00
c99d6fb16f 适配开启不保留活动模式(未完全适配 只是尽量让app不要崩) 2018-02-03 17:34:00 +08:00
d29ccc0aca toast context判断 禁止context.getString 操作 2018-02-03 10:16:27 +08:00
bf51be498b ImageUtils 非空问题 2018-02-01 16:02:28 +08:00
6d941975e2 toast禁止使用context 2018-02-01 15:27:29 +08:00
0e075d28a5 imageUtils kotlin非空问题 2018-01-31 14:25:40 +08:00
4b5e6b574f 修复列表刷新FooterViewHolder的方式 以及调整邀请达人FooterViewHolder的间距 2018-01-31 10:56:20 +08:00
fc79581f8c NavigationTitle空处理 MessageDetailActivity继承NormalActivity 2018-01-30 20:48:32 +08:00
6176c47e2f 修复已知bug,debug状态关闭数据上报,release增加tinker开发设备(channel:GH_TEST) 2018-01-30 19:45:56 +08:00
9abe0eb158 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-01-30 16:30:13 +08:00
4d7cedb8a6 解决社区游戏选择分页后数据异常问题,解决问题详情无法分页问题 2018-01-30 16:28:34 +08:00
2b02fe06ac Merge remote-tracking branch 'origin/dev' into dev 2018-01-30 11:34:27 +08:00
cd5f530fc6 Add todo. 2018-01-30 11:34:04 +08:00
b9085c7091 修复最新礼包无法下拉刷新问题,appbar在触控屏幕时禁止open/close,部分Fragment commit 替换成commitAllowingStateLoss 2018-01-30 10:38:26 +08:00
679ee71f89 修复channel脚本路劲问题,打tinker基础包 2018-01-28 16:10:12 +08:00
536f0e038a Activity 相关跳转(内部/外部)增加NormalActivity兼容 2018-01-28 15:34:13 +08:00
b087e35b30 修复问答-问题由于调整顺序可能会造成的闪退问题,修复社区-问题由于切换社区造成的数据异常 2018-01-28 14:33:30 +08:00
db3df649ce 优化下载超过100%问题 2018-01-26 16:51:47 +08:00
bb708277b1 修改昵称违规toast文案 2018-01-26 15:43:24 +08:00
c3b694dc6c 优化下载进度超过100%问题 登录相关增加错误toast 2018-01-26 15:34:21 +08:00
b9ff0b1c88 修复下载相关无法即时刷新页面问题 2018-01-25 19:06:04 +08:00
52be8db71f 后台控制关闭插件相关的功能 2018-01-25 17:41:54 +08:00
0e791133dd gradle internal publish 2018-01-24 18:12:01 +08:00
b4f760d69f 社区问题加载... 2018-01-24 18:02:55 +08:00
9bba3c9560 修复问答社区切换时造成数据异常问题 2018-01-24 17:59:49 +08:00
bcd61e87d3 修改草稿后重新刷新我的草稿列表 2018-01-24 11:28:15 +08:00
e8c0e523e6 光环助手V3.1 RELEASE(20180123-1205)测试汇总 2018-01-24 10:53:10 +08:00
af9e9a87b4 去除KEY_DATA, NormalActivity增加适配规则 2018-01-23 17:32:48 +08:00
2d1bb6435f 修复安装/卸载后游戏插件化区域无法更新问题 2018-01-23 14:50:41 +08:00
5680b8508d 问题详情标题去除行数限制 调整标签顺序 2018-01-23 11:00:21 +08:00
df0e9197dc 对话详情回复字数限制,答案/回答详情标题间距修改 2018-01-23 10:21:00 +08:00
79964160ff 发现页面入口点击统计 问答问题修改后刷新问题详情页面 2018-01-22 17:28:45 +08:00
0d46554b66 光环助手V3.1 RELEASE(20180118-2020)测试汇总(完成部分) 2018-01-22 16:07:07 +08:00
2c674896ff tinker脚本修改(internal切到publish) 2018-01-22 09:35:18 +08:00
3ce1f28ae6 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-01-19 11:33:20 +08:00
5ef145ed47 修复InstallUtils卸载事件异常BUG 修复提问时问题标签顺序混乱问题 2018-01-19 11:30:54 +08:00
b478cd6812 Merge remote-tracking branch 'origin/dev' into dev 2018-01-19 11:05:28 +08:00
7e86187132 1.答案编辑页面去处拷贝来的样式
2.增加超出文字字数处理逻辑
2018-01-19 11:04:49 +08:00
58b7a9515f 修复点击取消安装后依然收到安装通知的Bug,删除安装完成自动删除安装包 默认安装后不删除安装包 2018-01-18 18:13:35 +08:00
370b2122aa 解决重复登录 出现多个弹窗问题 2018-01-18 15:35:42 +08:00
c6f1a7d212 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-01-18 14:41:07 +08:00
c04e425550 光环助手V3.1 RELEASE(20180116-1826)测试汇总 补充 2018-01-18 14:40:40 +08:00
19543d7d29 修复了修改回答 Webview 进入时无法滚到页面底部的问题 2018-01-18 09:19:45 +08:00
12af602066 问答相关一些间距调整, 社区搜索增加提问按钮,提问标题字数不足30字且最后字节不是问号的情况下自动增加问号 2018-01-17 16:13:24 +08:00
000515cda7 首页问答增加断网重连 2018-01-17 15:12:05 +08:00
645e5a94a6 调整toolbar menu间距 2018-01-17 14:54:45 +08:00
c2f69eb03d 问题详情我的回答和我来回答图标调换 2018-01-16 18:14:46 +08:00
93a9c41bee Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	README.md
2018-01-16 18:07:08 +08:00
02dffc6e22 修复消息小红点问题,修改问题详情刷新方式 2018-01-16 18:04:00 +08:00
2658b7ca93 Add todo. 2018-01-16 17:23:17 +08:00
8c3335a7bf 再次优化图片压缩方式, 提问和反馈(先压缩再显示界面) 2018-01-16 14:18:36 +08:00
c0e7b8e3ee 修复外部跳转NormalFragment失败问题,光环助手V3.1 RELEASE(20180112-0755)测试汇总 2018-01-15 18:37:04 +08:00
9ef3d65aa4 修复回答编辑框默认文案显示异常问题 2018-01-15 16:56:45 +08:00
8d188d4798 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-01-15 14:41:26 +08:00
7bfc84c156 回答详情重命名,外部跳转支持NormalFragment(未测试) 2018-01-15 14:38:58 +08:00
18bc47efe1 图片压缩优化 以及 问题详情页面调整 2018-01-15 11:53:43 +08:00
4593952cc3 把查询发现红点的间隔从60秒改成5分钟 2018-01-15 11:32:55 +08:00
1d3e30f8d3 社区问题页面 ViewPager Adapter 更换 2018-01-13 19:14:58 +08:00
6fef655e44 合并后续 2018-01-13 15:53:19 +08:00
552b81c558 1-12最后部分修改以及合并代码 2018-01-13 15:51:40 +08:00
6c9a4daf9b 修复了发现tab的红点问题 2018-01-12 18:44:57 +08:00
fbc46c54c4 修复社区页面没有登录也能进入提问编辑页面的问题 2018-01-12 14:43:45 +08:00
bc7aaa8b08 1-12修改 2018-01-12 08:26:13 +08:00
95af9902e7 部分UI调整,选择社区和问题详情脚布局调整 2018-01-11 18:15:01 +08:00
f340a13212 光环助手V3.1 DEV(20180109-2100)测试汇总 2018-01-10 21:30:25 +08:00
3d8f17d641 社区回答修改答案上传规则 2018-01-10 16:07:02 +08:00
68f7b0f20f 增加首页-发现和修复部分汇总 2018-01-09 21:22:12 +08:00
c3a3060b92 光环助手V3.1 DEV(20180106-1901)测试汇总(补充) 2018-01-09 14:07:50 +08:00
c01b96298d 光环助手V3.1 DEV(20180106-1901)测试汇总(部分未完成) 2018-01-09 10:49:31 +08:00
26655da185 toolbar统一样式(后续有时间再全部整理) 2018-01-08 11:01:18 +08:00
9d0345303a 重新整理ShareUtils,增加社区相关分享 2018-01-06 18:19:15 +08:00
33d02a0b2e 问题正文,如果超过3行的,要出现查看全文按钮,默认最多只支持显示3行 2018-01-06 17:23:13 +08:00
f301ab694c 所有user_data的SerializedName改为me,答案详情增加“查看大图”按钮 2018-01-06 15:49:31 +08:00
baa6c0db3c 光环助手V3.1 DEV测试汇总(20180104) 2018-01-06 11:43:34 +08:00
d118f54bd3 重新整理ShareUtils,增加社区相关分享 2018-01-05 18:17:39 +08:00
4a7384d371 LogHub增加混淆,修复问题详情无法查看我的答案 2018-01-05 10:55:18 +08:00
6a91b8ae0f Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-01-04 18:24:57 +08:00
b5fddfbbd0 界面调整和部分测试汇总 2018-01-04 18:24:36 +08:00
cfa3ceaae7 RichEditor 增加缩略图控制,图片监听(还差查看大图按钮),相关页面已经接入 2018-01-04 11:09:29 +08:00
7a8f75abfc 问答用户头像圆角,发布问题成功后跳转到问题详情 2018-01-03 14:40:26 +08:00
3db70fcbbe Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2018-01-03 12:05:45 +08:00
7b74d9fe47 fix webview wide viewport 2018-01-03 12:05:15 +08:00
553c211f24 新增问答搜索统计 2018-01-02 17:49:09 +08:00
3b153f5967 增加LogHub 新增问答答案统计, 新增问答问题统计 2018-01-02 17:05:53 +08:00
926b2d070f 修复有草稿箱进去回答答案成功后无法刷新页面问题 2017-12-29 18:24:31 +08:00
3e37731d84 评论关键字标红 答案编辑传参更改 2017-12-29 15:38:25 +08:00
24b5b81279 问答相关非GET请求处理(toast),修复由我的草稿编辑无法评论问题 2017-12-28 19:20:23 +08:00
0534294b82 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-12-28 17:26:24 +08:00
a314404b61 更改消息客服接口 2017-12-28 17:26:14 +08:00
71b81b2255 消息中心-消息页面 改造完成 2017-12-28 17:21:32 +08:00
c8cb61436e 问题Tag标签整理(位置调整保持),社区选择回调(刷新界面) 2017-12-28 09:52:04 +08:00
1006bf25c1 1、移除MTA可视化埋点
2、增加TalkingData可视化埋点
2017-12-27 19:20:31 +08:00
cb6f03231e 问答社区相关优化 2017-12-27 16:47:42 +08:00
8ee2308ee1 整理NormalFragment相关代码 2017-12-27 15:02:17 +08:00
719dbeef76 整理页面toolbar,修复开服表跨年显示异常问题 2017-12-26 17:30:59 +08:00
4c34333956 NormalFragment 增加getItemMenu, 修复答案收藏无法反选问题 2017-12-25 18:11:35 +08:00
bff677d607 增加创建社区投票,编辑草稿回调失败问题, gameInfo增加icon 2017-12-25 15:48:15 +08:00
ba1461c874 增加收藏-答案 2017-12-22 15:56:35 +08:00
7a0e885444 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-12-21 18:26:10 +08:00
72d4ab6db5 优化我的问答界面以及跳转和其他问答相关页面整理 2017-12-21 18:25:40 +08:00
dfd6b61123 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-12-21 17:27:24 +08:00
352d7d032e 1、解决toolbar上面文字的问题。。。简直6
2、解决快传文件的一个bug
2017-12-21 17:01:29 +08:00
ae6ba7832d x 2017-12-21 14:46:08 +08:00
9d63a6d0c4 fix string 2017-12-21 14:45:24 +08:00
e905fb366e 问题精选更改Entity 和点击跳转 2017-12-21 11:33:55 +08:00
27b325f7d9 答案编辑-保存草稿 修复答案收藏和问题关注 2017-12-21 10:49:28 +08:00
5c2f8c60dd 对接问题关注和答案收藏 2017-12-20 19:49:24 +08:00
3ac5905994 增加答案编辑(接口测不通) 2017-12-20 16:55:10 +08:00
0e460b0778 个人中心 增加我的问答 2017-12-20 15:39:00 +08:00
4eea5b99d6 ... 2017-12-19 21:16:38 +08:00
34c60d09f6 问答相关接口测试整理 升级3.1 2017-12-19 18:10:43 +08:00
48e1ee4e7b Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/ask/questionsdetail/AnswerEditFragment.java
2017-12-19 16:21:09 +08:00
46863d09a2 问答接口测试 整理 2017-12-19 16:17:48 +08:00
ade08dcbee revert gradle 2017-12-19 15:57:15 +08:00
e9a381068e 1、用户信息相关页面整理 2017-12-19 15:56:32 +08:00
f5a068937a Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-12-19 11:21:00 +08:00
c2bc52e474 重构专题页面相关逻辑
其他toolbar逻辑移除
2017-12-19 11:20:47 +08:00
cd4ce2aa6b Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/ask/questionsdetail/AnswerEditFragment.java
2017-12-19 09:27:48 +08:00
257e82e825 问答相关接口测试与对接 2017-12-19 09:25:22 +08:00
a705f0ec53 fix gradle.properties 2017-12-18 16:20:17 +08:00
46699a05ce Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-12-18 16:00:44 +08:00
9fd1855daa 资讯相关页面的整理 2017-12-18 16:00:30 +08:00
9a96fffd18 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-12-18 15:07:36 +08:00
00d6f5e4b1 问题搜索 问题编辑 页面处理 2017-12-18 15:06:52 +08:00
a3adb87a6a (答案-编辑,问答-问题,问答-邀请)功能优化整理 2017-12-17 18:30:32 +08:00
d0c01f1873 问答-答案详情 2017-12-17 14:20:44 +08:00
725d0b217a 优化问答编辑框 2017-12-17 10:10:47 +08:00
1958c6aefb update readme 2017-12-15 18:06:27 +08:00
05be092d69 1、移除部分haloapp的静态变量
2、整理hardcode tag
3、修复NPE
2017-12-15 18:04:56 +08:00
40fccea23a 1、修复libaoactivity、libaodetailactivity崩溃
2、处理部分toolbar
3、处理输入法弹出、隐藏
2017-12-15 17:23:34 +08:00
a022526e7e Merge remote-tracking branch 'origin/temp' into dev 2017-12-15 11:00:08 +08:00
765b4c3afa fix to compile 2017-12-15 10:26:27 +08:00
f704a29b38 Merge remote-tracking branch 'origin/3.1' into dev 2017-12-15 09:57:57 +08:00
309bb98036 选择游戏页面修改 2017-12-14 18:06:09 +08:00
bf7b0b0a82 处理一部分activity的toolbar,已经处理完毕的标记为Deprecated,为了保持MTA数据上报兼容性,暂时未删除对应的Activity 2017-12-14 17:56:54 +08:00
98629c5e85 问答标签同步 2017-12-14 15:38:45 +08:00
461acbd376 答案编辑改进 2017-12-13 18:02:17 +08:00
e0b70b26f3 1、分离datautils,debug release独立逻辑
2、baseactivity toolbar处理(继续处理消除activity)
3、xml处理
2017-12-13 16:47:27 +08:00
4a831f4cb9 优化部分命名问题 2017-12-12 17:55:00 +08:00
b58bbbe705 社区对接接口 2017-12-12 17:13:00 +08:00
dc186e2e6b 部分enum修改 2017-12-12 10:22:16 +08:00
44deb59624 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	gradle.properties
2017-12-11 18:42:29 +08:00
886007eae5 对接部分接口 2017-12-11 18:37:12 +08:00
27fc39cb70 revert tinkerid 2017-12-11 17:35:25 +08:00
5480caf44e update gradle to 3.0 & fix tinker filepath 2017-12-11 17:33:44 +08:00
877ecbaef1 问答相关页面整理 2017-12-11 16:45:09 +08:00
434bfde292 问答-搜索,问答-提问 2017-12-08 18:35:46 +08:00
40c55e716d 问题详情/问题详情-邀请页面/问题详情-回答编辑页面 2017-12-08 14:47:27 +08:00
a448a974f1 1.开服日历页面时关闭日历详情
2.删除对开服信息时间的判断 如果有开服信息就显示开服日历
2017-12-07 16:14:15 +08:00
1738fac5fd Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-12-06 18:33:10 +08:00
7b74318ca5 修复详情页面 启动需要检查网络的BUG 2017-12-06 18:32:19 +08:00
19e394abb8 问答社区-问题/切换社区-选择游戏/问答社区-调整问题类型顺序 2017-12-06 18:09:11 +08:00
6dabbe19dd update libs 2017-12-06 16:15:20 +08:00
7b95d991d4 问答-问题 2017-12-05 19:18:45 +08:00
e286be7f1e 修复开服表过年无法显示问题,修改开服表显示规则 2017-12-05 16:39:21 +08:00
4214c08e76 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1
QQ 跳转无法回话问题
2017-12-05 11:02:17 +08:00
180c49f9d3 问答精选基本完成(还差接口) 2017-12-05 11:00:52 +08:00
ef040f68c7 区分企业QQ和普通QQ的打开方式 2017-12-05 10:15:44 +08:00
65e098e1c8 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-12-04 18:48:41 +08:00
3978ab95f4 新增通用列表模块,问答精选 2017-12-04 18:47:53 +08:00
b134d077cf 礼包领取判断修正 2017-12-04 12:01:43 +08:00
d537cb2383 登录重构(token过期重试部分) 2017-12-02 14:32:08 +08:00
dba866e5c9 登录重构相关 2017-12-01 17:44:09 +08:00
ce36dd4012 登录重构(网络层的token重试未完成, 还有其他登录相关代码的整理) 2017-12-01 16:59:32 +08:00
ea2b9ef4df Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-11-28 15:45:12 +08:00
69fe3b3d76 fix appbar scroll behavior 2017-11-28 15:37:57 +08:00
a34b101a05 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-11-28 09:23:56 +08:00
c134c4bf9e 删除无用log 2017-11-28 09:22:09 +08:00
b0fe7595da Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-11-27 16:39:04 +08:00
6a7ef44bdd 字符串hardcode问题 2017-11-27 16:37:06 +08:00
633acb9236 礼包领取限制 2017-11-27 16:03:32 +08:00
cf84205571 修复礼包列表和专题列表分页加载过慢问题 2017-11-27 15:04:12 +08:00
5aced2c03c 光环助手V3.0.2优化需求与bug汇总(11-27) 2017-11-27 11:57:11 +08:00
6cfa949493 解决跳转QQ后无法聊天问题 2017-11-27 09:27:29 +08:00
4131396117 引入constraintLayout 2017-11-24 10:42:53 +08:00
e5f8d959ed Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-11-23 20:07:25 +08:00
6f0c9e0b59 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-11-23 20:04:55 +08:00
dcfe3dee0e Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-11-23 20:04:24 +08:00
8348568ea7 修复3.0.1意见反馈Bug
1.ImageUtils传入的url允许为空
2.修复专题ActionBarTitle有可能为空问题
2017-11-23 19:58:00 +08:00
1d5dece894 fix git submodule update script 2017-11-23 15:57:52 +08:00
051e0751a5 禁止用Class SimpleName做bundle的TAG 2017-11-23 10:15:02 +08:00
64594c4457 调整下载重试时间间隔 2017-11-22 17:12:07 +08:00
5f19f55e03 文章详情 相关文章推荐优化 2017-11-22 17:09:35 +08:00
da6cfdc4e8 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-11-22 15:44:27 +08:00
c2274d6b6f 3.0升级日志 2017-11-22 15:44:04 +08:00
adbdc55bc4 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-11-22 15:23:56 +08:00
165059ca2d 快传 传送最低时间设为1秒 2017-11-22 15:07:29 +08:00
6c1da15ae4 整理文章详情和游戏详情的文章列表(将布局代码抽离到xml) 2017-11-21 18:31:03 +08:00
ecf05bcd00 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1
# Conflicts:
#	app/src/main/java/com/halo/assistant/HaloApp.java // 设置GH_TEST渠道为Bugly(tinker)开发设备
2017-11-21 17:02:25 +08:00
3baec32ff8 彻底删除小米推送,整理部分TODO 2017-11-21 16:55:45 +08:00
cb95204fac 解决一些hardcode和命名规范 2017-11-21 09:23:33 +08:00
89e05d1a29 设置GH_TEST渠道为Bugly(tinker)开发设备 2017-11-20 17:24:02 +08:00
41b940a8e9 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-11-19 14:29:32 +08:00
3d8d612897 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-11-19 14:27:09 +08:00
b3297e3fcd 升级最新友盟推送(包含华为小米),删除旧版小米(已包含在友盟) 2017-11-19 14:14:39 +08:00
9f00cab409 优化首页缓存 2017-11-19 12:00:00 +08:00
e8a795f97b 1117测试问题:
1.如果后台隐藏了评论,前端在消息中心点击跳转对话详情,会一直转圈圈,也没任何提示(应该要出现飞碟提示才对)
2.消息中心-客服,排版和“评论”不一致
(1)分割线与头像之间的间距(比“评论”那边窄了)
(2)昵称和时间之间的间距(比“评论”那边宽了)
2017-11-17 11:37:00 +08:00
c8c93cac6e 与3.0.2合并 2017-11-17 10:47:43 +08:00
96c233ebd0 光环助手V3.0.2 评论对话增加弹窗(回复/点赞/复制 等) 2017-11-16 20:04:03 +08:00
36ef13b237 光环助手V3.0.2优化需求汇总(20171116) 2017-11-16 18:06:23 +08:00
f54fdd6016 可以多次重定向,但有数量限制.断网重连先延迟后判断 2017-11-16 12:02:32 +08:00
a43947077a 新增打渠道包脚本 2017-11-16 09:19:47 +08:00
a863b7be13 fix proguard library 2017-11-15 17:33:47 +08:00
ab1ce8e179 HttpDns版本和友盟HttpDns改成一致 2017-11-15 17:12:27 +08:00
d391ab20b7 更换3.0.1tinker_id以及tinker_base_apk_dir 2017-11-15 15:13:47 +08:00
8403bc3a64 求版本敏感词优化 2017-11-15 15:07:34 +08:00
038e736eb1 下载暂停和继续延迟一秒,防止一个包同时有多个线程在下载(后续想一个更好的方案) 2017-11-15 10:41:02 +08:00
a215192175 下载增加httpdns 2017-11-14 20:42:27 +08:00
22a1895050 消息中心优化, 求版本功能完善(敏感词toast还要确认), 修复搜索游戏失败时无法重试问题 2017-11-13 17:44:10 +08:00
2df42c772b 下载重试优化 2017-11-13 15:34:24 +08:00
e68e47e132 增加 baselist 相关 2017-11-11 15:48:10 +08:00
72f9e8ed79 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-11-11 09:34:43 +08:00
3a2c67152e 字符串hardcode问题 2017-11-11 09:34:01 +08:00
82fea04460 首页启动性能优化-获取到了新数据后 要更新界面 2017-11-10 15:53:53 +08:00
6ccd70dad2 首页启动性能优化,修复游戏平台面板插件图标异常问题 2017-11-09 19:28:24 +08:00
ec2d14bffe 修复refreshToken过期重试问题 2017-11-09 11:47:13 +08:00
1d544ff558 修复登录相关问题(删除用户数据后发注销广播) 2017-11-08 20:06:40 +08:00
867cd29e0f 修复强制弹窗 2017-11-08 19:39:59 +08:00
d1cf660af6 修复获取验证码返回处理 2017-11-08 18:36:58 +08:00
adabe3a227 20171108issues: http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/91
登录无网络处理
2017-11-08 18:31:38 +08:00
b57ef6c3b4 refreshToken抽离 refreshToken同一时间只能访问一次 2017-11-08 10:53:23 +08:00
1b50823843 修复第一次登录头像提示 2017-11-07 21:04:31 +08:00
c4c499532a Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into 3.1 2017-11-07 14:57:02 +08:00
18ddad522a 补丁弹窗问题 2017-11-07 14:40:50 +08:00
85b034ecfb make sure that update dialog show 2017-11-07 12:05:11 +08:00
5a04749ef2 make sure that update dialog show 2017-11-07 11:59:22 +08:00
bcd32dde85 fix tinker patch 2017-11-07 11:31:41 +08:00
7832cb810b fix tinker script bug 2017-11-07 10:59:00 +08:00
cb652721a7 fix tinker script bug 2017-11-07 10:57:19 +08:00
4ad005fb53 update about version 2017-11-07 10:46:19 +08:00
ce312aea72 fix tinkerId show update log 2017-11-07 10:39:40 +08:00
6c5dc556e8 fix tinker support 2017-11-07 10:21:03 +08:00
95dc18f1d0 remove tinkerid before tinker release base 2017-11-07 10:17:10 +08:00
f284cc8676 test 2017-11-07 09:59:47 +08:00
0cc456c4a1 3.0.1优化
http://gitlab.ghzhushou.com/pm/halo-app-issues/issues/87
2017-11-06 18:29:34 +08:00
0666146374 11-6 打母包 2017-11-06 15:56:32 +08:00
5860ca720e 优化掉线问题 2017-11-03 19:43:49 +08:00
91ee8362ba 修复查看评论 2017-11-02 19:43:04 +08:00
d8f043ad71 游戏列表开服信息 重写到ViewHolder类本身 2017-11-02 16:45:36 +08:00
1706ead392 整理已安装的游戏数据表 2017-11-02 15:20:38 +08:00
dd81460826 修复补丁弹窗问题 2017-11-01 17:29:50 +08:00
5180916d9f Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-11-01 17:16:18 +08:00
4d92ddcc75 ... 2017-11-01 17:15:09 +08:00
f1f0900e13 get tinkerid 2017-11-01 17:12:46 +08:00
6edf68d03c 补丁安装完成弹窗提示优化 2017-11-01 15:23:11 +08:00
c643ae507b 添加额外渠道 2017-10-31 18:13:05 +08:00
fdc843a93a V3.0.1优化完成 补丁安装完成要出现弹窗提示->还没测试 2017-10-31 18:11:09 +08:00
383c06c72a V3.0.1优化 1~9 2017-10-31 11:10:29 +08:00
a255ce3e36 添加渠道 2017-10-27 18:16:00 +08:00
fa58e820c1 修改老用户同步逻辑 2017-10-27 18:07:51 +08:00
fad011e2fc 修复登录掉线问题(应该OK了),关于版本显示补丁包版本号 2017-10-26 14:51:51 +08:00
9fad040e14 修复礼包(从文章超链接进入礼包详情),登录问题 2017-10-25 18:39:24 +08:00
8d0ab82f15 整理hardcode问题,整理imageUtils工具类 2017-10-19 09:11:22 +08:00
3d7e994b93 增加NormalActivity/fragment 2017-10-17 20:35:03 +08:00
4d40c0f431 修复首页页面切换时 插件化模块自动滑动问题 2017-10-16 17:53:39 +08:00
d9bb60e66b 整理Entrance type 2017-10-16 16:49:22 +08:00
52433ba347 抽离部分java代码中的字符串,equals判断常量放在前面 2017-10-14 15:52:15 +08:00
4290846698 抽离代码中的fromHtml的content,修复个人中心同步问题 2017-10-14 14:44:25 +08:00
6bbd7ec00d ... 2017-10-13 17:01:51 +08:00
dc535ddb38 V3.0 10-12汇总, 优化我的关注和登录页面 2017-10-13 16:54:37 +08:00
dfe087e702 登录增加进度弹窗,统一toast 2017-10-12 17:57:40 +08:00
930e0b92eb 修改下载管理更新游戏逻辑 2017-10-12 16:37:18 +08:00
3199bc6118 10-12优化补充 2017-10-12 09:57:36 +08:00
b1384375a3 打publish包 2017-10-12 09:24:45 +08:00
81dd98cefd 关于版本号更改, gson工具类 2017-10-11 20:19:14 +08:00
02108b3273 ViewPager 指针四舍五入取整 2017-10-11 15:34:12 +08:00
c5deb87c23 整理代码中的文本 2017-10-11 10:24:07 +08:00
572274a2e3 V3.0 10月10日测试包 2017-10-10 16:36:10 +08:00
7f303b362d bug修复 2017-10-10 15:19:17 +08:00
41ce6cce05 打tinker包 2017-10-10 10:17:38 +08:00
f6e1c55749 ... 2017-10-10 09:53:14 +08:00
d24bcf8e6e 修复游戏详情空白提示异常问题 2017-10-09 18:42:46 +08:00
2b497ff679 登录成功提示逻辑修改 2017-10-09 16:05:09 +08:00
627c20f6fd 修复验证码礼包无法领取问题 2017-10-09 15:15:18 +08:00
cfab918bea layout的颜色代码抽离 2017-10-09 14:29:53 +08:00
89746203fe 登录完成后自动刷新页面(我的关注,存号箱,礼包-关注), 修复资讯-关注礼包同步问题 2017-10-09 11:47:25 +08:00
8bc6947c94 dialog由默认layout改为在xml创建 2017-10-08 17:58:53 +08:00
5a264804da 整理礼包详情内容(layout抽离到xml) 2017-10-08 15:42:04 +08:00
1f5e025fea java代码抽离颜色代码,修复历史礼包已知bug 2017-10-08 14:56:40 +08:00
3201e220a0 礼包重复领取修复已知问题,收藏页面优化 2017-10-08 11:39:49 +08:00
d41129011b Tab指针居中 2017-09-28 17:50:20 +08:00
6eb1aefb1c V3.0 09-27 Tab指针居中问题未解决 2017-09-28 15:25:06 +08:00
433646b455 修改登录相关接口循环请求问题, 定时任务统一用postDelayedRunnable在baseFragment 统一remove 避免刷新过程中对出闪退 2017-09-28 11:57:34 +08:00
257e7d1d27 viewPager+fragment adapter notifyItemRangeInserted去除判断(好像是recyclerview修复了这个bug) 2017-09-27 18:22:51 +08:00
f668d6492a 整理部分可以快速弄好的todo 2017-09-27 17:44:15 +08:00
b8ea968a58 抽离列表的onclick事件 还未完成(太太太多啦), click startActivityForResult相关已经完成 2017-09-27 17:15:58 +08:00
5b361afc67 更换沉浸栏实现方法, actionBar menu 修改 2017-09-27 11:28:07 +08:00
0947cd1e24 fix tinker 2017-09-26 19:22:30 +08:00
f8ab1f108b Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-26 18:39:53 +08:00
84f53bbf81 fix gnu/bsd script 2017-09-26 18:39:50 +08:00
ad2656a24b ... 2017-09-26 18:39:42 +08:00
4734fbd651 fix tinker 2017-09-26 17:46:20 +08:00
a947755383 tinker test 2017-09-26 17:05:45 +08:00
f4a1283073 将列表onclick事件提取出来(只完成资讯模块) 2017-09-26 16:34:51 +08:00
f37a2c5b24 测试tinker回退, 没有测试成功.
获取VERSION_CODE失败 返回的是null.
跑patch脚本 gradle指定baseApk路径和脚本生成(多出两层目录)的路径不一致.
打出来的补丁包上传时提示"未匹配到可应用补丁app版本".
2017-09-25 20:56:10 +08:00
cca7d770f1 测试tinker 改了一些脚本 待会改回来哈 2017-09-25 19:28:30 +08:00
2c7f3f2321 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-25 18:34:16 +08:00
cc92e025f2 fix tinker build.gradle file 2017-09-25 18:32:57 +08:00
ce0e28dad6 activity入口整理(涉及到外部启动(插件跳转/推送)的未完成) 2017-09-25 17:22:07 +08:00
b483f7cdb6 整理xml的hardCode(部分固定文案尚未抽离) 2017-09-25 16:36:40 +08:00
8ce0694099 重写选择地区页面 2017-09-25 16:04:52 +08:00
910b356a05 push LGLibrary?? 2017-09-25 12:05:13 +08:00
d74e0310f8 测试tinker 2017-09-25 11:40:10 +08:00
ee19879577 整理startActivityForResult CODE 2017-09-22 18:02:20 +08:00
5e3d7d2f2b 删除无用的数据库相关类(concernDao还需整理), 修复不能重复领取/淘号问题 2017-09-22 15:27:54 +08:00
f292eb0fc6 9月19日测试包 完成 2017-09-22 09:21:49 +08:00
475de2281b Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-21 16:15:12 +08:00
949c8331d2 礼包详情重复淘号,从存号箱和普通列表进去礼包详情 数据同步 2017-09-21 16:09:06 +08:00
a5e0fa8402 fix conflict 2017-09-21 15:27:03 +08:00
f0066b3dac fix strings.xml formatable string 2017-09-21 15:26:04 +08:00
10480a533c add readme sample 2017-09-21 12:12:45 +08:00
d36dcac817 登录失败提示 2017-09-21 10:33:42 +08:00
d6d49ac7ad 整理Activity入口(还有部分未检查) 2017-09-20 20:01:07 +08:00
573e127fc7 整理消息页面(阅读后即时提交) 2017-09-20 15:39:20 +08:00
9cb6e599a4 整理无用代码 2017-09-20 14:37:40 +08:00
f42dd1013e Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-19 15:05:48 +08:00
70441658e5 收藏同步相关 2017-09-19 15:04:59 +08:00
0ca71f25f6 fix context related 2017-09-19 14:28:43 +08:00
5d3a4e24f9 fix debug keystore 2017-09-19 10:29:03 +08:00
3b8faf47c4 资讯-关注 优化 2017-09-18 19:33:01 +08:00
ac21776d3b 退出登录时增加过程弹窗, 防止过早或过慢清除token造成的页面错误 2017-09-18 18:36:13 +08:00
e5127c9040 退出登录时增加过程弹窗, 防止过早或过慢清除token造成的页面错误 2017-09-18 18:35:32 +08:00
8533d06943 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-18 17:11:27 +08:00
066dd6103f 用户数据同步-收藏增加多页面同步, 礼包部分整理(资讯-关注接口欠缺礼包用户数据, 评论相关接口欠缺用户数据) 2017-09-18 17:11:15 +08:00
670f9c280c add debug bugly 2017-09-18 15:37:43 +08:00
5ea3c58b77 update tree image 2017-09-18 14:16:50 +08:00
6e15571ef4 create patch test 2017-09-18 12:17:49 +08:00
ad46fced4f Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-18 12:06:54 +08:00
5acf42423e add rsync to 2.100 for backup 2017-09-18 12:06:44 +08:00
2a2bef8a47 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-16 18:31:20 +08:00
2ffb0f59a2 用户数据同步-礼包相关(优化/整理) 2017-09-16 18:30:51 +08:00
400bdaa6f5 fix script var naming 2017-09-16 18:10:54 +08:00
fa449966f3 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-16 17:29:41 +08:00
f4078493f6 fix patch/channel/ release scripts 2017-09-16 17:29:31 +08:00
5007f7e83d 用户数据同步-我的关注(页面更新逻辑修改) 2017-09-16 14:49:25 +08:00
ca1a8e15cb Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-16 09:24:35 +08:00
b9f299805f 用户数据同步-基本完成(比较多细节问题需优化) 2017-09-15 18:38:31 +08:00
acde49012f test tinker multiple channel release & patch 2017-09-15 18:17:35 +08:00
76c69f0d19 fix tinkerid not the same 2017-09-15 17:38:51 +08:00
c0b91b4a63 Merge remote-tracking branch 'origin/dev' into dev 2017-09-15 17:00:47 +08:00
f6a194ae92 fix patch script 2017-09-15 16:57:27 +08:00
9e7d178972 fix tinker patch path 2017-09-15 16:25:03 +08:00
17b2e2dca7 test patch 2017-09-15 16:03:22 +08:00
eb73bcd25f fix script 2017-09-15 16:00:13 +08:00
f96c090120 test script 2017-09-15 15:39:46 +08:00
aefdaee424 fix script 2017-09-15 15:34:50 +08:00
27ceee37c0 fix script 2017-09-15 15:33:24 +08:00
e1c2e3c984 fix script 2017-09-15 15:25:56 +08:00
48e3718fc2 add tinker scripts 2017-09-15 15:24:44 +08:00
ee20f65a9b 用户数据同步-礼包相关(基本完成, 尚未测试) 2017-09-15 14:22:40 +08:00
235a13855b 用户数据同步相关 2017-09-14 20:03:47 +08:00
acec42c6af 光环助手V3.0(9月12日测试包) 2017-09-14 17:16:33 +08:00
6d009eddf5 test tinker 2017-09-14 16:54:17 +08:00
b0dde281ea 相关数据关联UserDataEntity, 统一在Interceptor添加token 2017-09-14 15:23:08 +08:00
1e7d43bc72 优化6.0权限, 快传部分权限先搁置 2017-09-14 11:54:19 +08:00
8576a1edaf test patch 2017-09-13 19:24:26 +08:00
5dc97d2191 add test 2017-09-13 19:12:48 +08:00
a32b45e067 fix conflict 2017-09-13 18:31:41 +08:00
ff8210c72b proxy app logic 2017-09-13 18:27:11 +08:00
85031e89b6 Android 6.0及以上 权限适配 2017-09-13 18:23:55 +08:00
f2676532ce test fresco 2017-09-13 17:58:18 +08:00
7a996ee8f4 test fresco 2017-09-13 17:50:04 +08:00
d09e28d653 fix fresco crash 2017-09-13 17:08:24 +08:00
e446f4190f remove crash button 2017-09-13 16:57:34 +08:00
f53534b803 add crash button 2017-09-13 16:40:49 +08:00
fb6792f71b add crash button 2017-09-13 16:40:37 +08:00
5d66d55db1 remove crash me 2017-09-13 16:19:40 +08:00
d3bdd48425 test 2017-09-13 16:07:33 +08:00
c89f675ccf remove uncaught handler 2017-09-13 16:02:30 +08:00
f0b989d20e add crash button 2017-09-13 15:54:18 +08:00
3b950b6b28 fix extend 2017-09-13 15:47:37 +08:00
d10a0f956e fix crash 2017-09-13 15:11:41 +08:00
2317228642 test tinker patch 2017-09-13 14:47:08 +08:00
78a4571a8a Merge remote-tracking branch 'origin/dev' into merge 2017-09-12 15:03:56 +08:00
c7b16ce91b fix npe 2017-09-12 15:02:46 +08:00
2e84aeaccf 9月7日测试包 UI部分完成 2017-09-12 10:52:17 +08:00
49e9a532b8 Merge remote-tracking branch 'origin/dev' into merge 2017-09-11 15:37:45 +08:00
47f7d70cfb fix apiservice 2017-09-11 15:37:31 +08:00
a3b03efcbe Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-11 10:44:47 +08:00
814d4faf3e 9月7日测试包 UI部分未完成 2017-09-11 10:44:30 +08:00
c487dc2f03 fix webview focus issue 2017-09-08 15:22:40 +08:00
f552a06bd7 1、takingdata升级,精简无用的组件,480kb->220kb
2、数据统计部分整理,切勿更改数据统计和错误上报任何顺序
3、依赖整理
2017-09-08 11:58:56 +08:00
4de5593802 9月7日测试包 部分修复 2017-09-08 11:04:45 +08:00
4294e9f98d 最新礼包合并 2017-09-07 16:13:23 +08:00
05a911f1e3 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-07 16:06:08 +08:00
464f8d7851 最新礼包重做完成 2017-09-07 16:05:26 +08:00
370b07be31 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-07 14:32:30 +08:00
cb49c71279 check entrance 2017-09-07 14:32:20 +08:00
f637fb9596 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-06 17:01:27 +08:00
5c8072cc9e 完善礼包最新页面(未完成), 9.5测试需求 2017-09-06 17:00:59 +08:00
40cd057c28 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-06 16:18:52 +08:00
0bcd37c1f1 礼包最新页面修改实现逻辑(未完成), 9.5测试需求 2017-09-06 14:37:10 +08:00
6fce6fd80b Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-09-06 10:43:50 +08:00
bc13a6056d update gradle.properties to use https 2017-09-06 10:43:13 +08:00
00879964e4 3.0Bug修复/UI优化/礼包优化
暂时未解决:礼包页面切换时,礼包搜索条自动顶上去/LibaoEntity getId和getLibaoId混乱
2017-09-05 11:57:19 +08:00
64711d6175 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/base/AppController.java
2017-09-04 10:54:35 +08:00
0d3704f55d 3.0bug优化,3.0UI问题汇总,3.0礼包问题.部分未完成需要检查 2017-09-04 10:52:21 +08:00
0856eed7fc update lglibrary 2017-09-03 17:13:23 +08:00
8efaa9e724 1、更改build variant,debugCompile,确保正式打包不包含debug类库
2、支持按照debug/release简单区分更多代码逻辑
2017-09-03 17:11:04 +08:00
98983ff4eb 关注操作成功时才改变按钮状态 2017-08-29 11:52:04 +08:00
0ae36ed7a7 完善token重试逻辑和多设备登录 2017-08-28 16:58:39 +08:00
8e8b20c3dd 光环助手V3.0(8月24日)测试包问题汇总 2017-08-25 17:40:17 +08:00
82e2aa45c6 更新登录相关错误码 多设备登录提示优化(没效果) 2017-08-25 10:47:15 +08:00
e4be47e7e7 部分UI调整,优化登录模块 2017-08-23 17:48:42 +08:00
404c605a1e 优化开服表(主要是单个游戏开服点下载是非常卡,修复后还是有点卡),把首页控制台的消息提示红点移到我的光环 2017-08-22 10:51:23 +08:00
4966d85634 新开服表(默认定位未完成,等待根据游戏id获取开服信息接口) 2017-08-20 17:47:53 +08:00
043eebf013 修改获取token逻辑,以及处理token 401问题 2017-08-18 11:25:28 +08:00
3b521ddd08 首页-游戏插件化模块改成可伸缩,user部分接口移到api(关注) 2017-08-16 16:00:42 +08:00
bd74d3a1a3 底部点击回到顶部(首页-游戏),闪退重启出现提示框 2017-08-15 11:30:04 +08:00
0dc867ce64 重做登录页面(普通登录和老用户登录) 2017-08-14 17:19:41 +08:00
dde08e2d67 老用户登录,token过去处理,登录模块优化 2017-08-14 15:17:26 +08:00
3c5871526d 登录签名认证 专题列表开服时间格式更改  收藏优化 2017-08-10 10:20:35 +08:00
49f4ba2da8 同步最后修改2.6代码 2017-08-01 17:10:47 +08:00
77b660576a 登录验证(还不行) 2017-08-01 16:43:59 +08:00
a15ab62f03 收藏相关(文章检查是否修改未完成) 2017-07-28 18:32:29 +08:00
c65250973c fix okhttp retry logic 2017-07-24 16:36:16 +08:00
d5872aad55 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/base/AppController.java
2017-07-23 18:42:41 +08:00
9d27bba6fd 增加流量统计(尚未完善) 2017-07-23 18:36:45 +08:00
caeecce50b add okhttp request retry logic 2017-07-21 19:58:03 +08:00
f6c82dd767 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-07-21 18:21:16 +08:00
f88205f957 消息页面入口移到我的光环 2017-07-21 18:19:59 +08:00
3a0a4726b9 fix host and gradle vars 2017-07-21 10:11:30 +08:00
a113fc1c73 优化登录流程,修复2.6已知的BUG 2017-07-20 18:04:38 +08:00
92d122b0a3 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-07-19 11:24:15 +08:00
d96a2d22e0 增加收藏页面,优化登录流程 2017-07-19 11:21:42 +08:00
8d96b9fe7f add init submodule scripts 2017-07-19 10:25:17 +08:00
fdf7bdd64d 修改用户信息(更换头像未完成) 2017-07-18 15:43:02 +08:00
4f4c90f792 对接测试登录流程(第三方登录以及手机号码登录) 2017-07-18 10:43:38 +08:00
f42674ed6f add dev/public host product flavors 2017-07-14 17:15:05 +08:00
e66b697663 修改域名为ghzs666 2017-07-14 16:45:00 +08:00
a21e40a4f1 Merge branch '3.0' of gitlab.ghzhushou.com:halo/assistant-android into 3.0 2017-07-10 17:03:06 +08:00
03dd58ca41 .. 2017-07-10 17:00:41 +08:00
6f3827db15 Merge branch '3.0' of gitlab.ghzhushou.com:halo/assistant-android into 3.0
# Conflicts:
#	app/src/main/java/com/gh/common/util/GetLoginDataUtils.java
#	app/src/main/java/com/gh/gamecenter/LoginActivity.java
2017-07-10 17:00:22 +08:00
fd2b333bc7 fix weibo webview proguard 2017-07-10 16:37:18 +08:00
ba3e882f47 微信获取登录数据成功回调,登录模块优化 2017-07-10 16:22:13 +08:00
b9a80e12a8 patch viewpagerfragment for onactivityresult callback 2017-07-10 16:07:38 +08:00
979ee209dd Merge branch '3.0' of gitlab.ghzhushou.com:halo/assistant-android into 3.0 2017-07-10 15:01:39 +08:00
10b1380aad 1、下载模块部分重构
2、整理actionbar高度问题,测试toolbar,暂时未启用
3、sharedpreference使用default文件
2017-07-10 14:35:32 +08:00
b239407c25 模拟对接登录接口已经登录流程(未完成) 2017-07-07 19:31:58 +08:00
475221a011 debug和release生成对应域名 2017-07-07 14:36:15 +08:00
658ee78213 分离build/release key 2017-07-07 10:46:23 +08:00
5244fe73ea 1、处理release debug build区分 2017-07-07 10:43:29 +08:00
243e024d1a 修复友盟推送初始化异常,ImageUtils代码转换kotlin 2017-07-06 19:50:40 +08:00
5930996e1c 修复插件平台图片(旧版本)无法更新问题, 优化登录 2017-07-06 09:10:44 +08:00
a05e6917b8 更改弹出软键盘时移动布局方法(防止软键盘挡住布局),以适配个别手机计算错误 2017-07-05 15:09:51 +08:00
d05e9e57c3 实体类全部转换成kotlin 2017-07-04 17:07:12 +08:00
1b88e9c238 ... 2017-07-03 19:51:51 +08:00
ce32b8d63a Merge remote-tracking branch 'origin/3.0' into 3.0 2017-07-03 10:04:15 +08:00
2bc26c9046 接入微信登录, 增加个人信息编辑页面,我的光环增加自动检测更新,登录页面增加新老用户切换 2017-07-03 09:58:54 +08:00
714a64975f 1、对下载器任务的状态变化修改
2、对下载器内部的handler的消息屏蔽,pause的修改,剩余download roll未改动。
2017-07-02 09:49:21 +08:00
7a6354e781 Merge remote-tracking branch 'origin/3.0' into 3.0 2017-06-30 17:30:03 +08:00
5f11c2d0b6 接入微信登录, 增加个人信息编辑页面,我的光环增加自动检测更新,登录页面增加新老用户切换 2017-06-30 17:29:43 +08:00
9c6814482d 1、downloadmangeractivity逻辑改动到viewpager fragment 2017-06-30 11:44:23 +08:00
94a5736939 fix data error in gameentity 2017-06-29 16:36:27 +08:00
bc496d8277 update lib 2017-06-29 16:00:32 +08:00
2b23665cb5 fix entity 2017-06-29 15:59:36 +08:00
1d1c9666dc Merge remote-tracking branch 'origin/3.0' into 3.0 2017-06-29 11:27:21 +08:00
1b14f3f608 微博登录改动 2017-06-29 11:27:07 +08:00
d370e817c0 update lib 2017-06-29 11:25:06 +08:00
ea4c6c95a1 Merge branch '3.0' of gitlab.ghzhushou.com:halo/assistant-android into 3.0
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/adapter/CommentDetailAdapter.java
#	app/src/main/java/com/gh/gamecenter/adapter/MessageDetailAdapter.java
#	app/src/main/java/com/gh/gamecenter/newsdetail/NewsDetailAdapter.java
2017-06-29 11:23:47 +08:00
f97ccd5c5d 1、更改部分下载类,未完成
2、@#&@*#
2017-06-29 11:17:01 +08:00
0b2a672f2d Merge remote-tracking branch 'origin/3.0' into 3.0
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/newsdetail/NewsDetailAdapter.java
2017-06-28 18:09:08 +08:00
f960b07ee1 涉及到用户操作的加上登录验证, 把评论点赞抽离成工具方法 2017-06-28 18:06:36 +08:00
5cbf06f6a6 1、回退umeng push版本到3.1.1
2、catch umeng初始化。
2017-06-28 11:06:50 +08:00
70ea517a3a update LGLibrary, fix libaodetail entrance 2017-06-28 10:12:48 +08:00
957305d6f5 抽离详情页面下载模块(已完成) 2017-06-28 09:53:03 +08:00
bbd1d429a6 Merge remote-tracking branch 'origin/3.0' into 3.0 2017-06-27 16:31:48 +08:00
56ba47a844 抽离详情页面下载模块(新闻详情已完成) 2017-06-27 16:31:27 +08:00
8101d394a8 fix conflict 2017-06-27 16:28:33 +08:00
496144f8ad 1、统一下载逻辑,下一步准备移动到通用类库
2、修复viewimageactivity npe
2017-06-27 16:27:51 +08:00
4cbee71636 fix submodule 2017-06-26 18:57:09 +08:00
7aed643eba fix conflict 2017-06-26 18:38:16 +08:00
829da52101 更换新版Dialog,微博获取用户信息 2017-06-26 18:27:36 +08:00
9dd449c2ef 1、移动公用文件、样式到libraries/LGLibrary
2、请使用git submodule foreach git pull更新代码
2017-06-26 16:35:36 +08:00
f78bdaa358 mv BaseRecyclerAdapter to lib 2017-06-26 15:16:00 +08:00
16236e1361 remove weibo lib 2017-06-26 15:12:18 +08:00
8e52d45037 fix build script 2017-06-26 14:57:33 +08:00
2246670487 1、移除libraries/LGLibrary,使用submodule替代,具体使用方式参考README.md
2、更新readme.md的说明
3、添加CHANGELOG.md文件,用于保存版本更新记录
2017-06-26 14:48:16 +08:00
cde325198e 登录模块界面 2017-06-26 09:20:08 +08:00
faa0710fd5 ... 2017-06-22 16:28:54 +08:00
d1bb27ad6b 雷达扫描动画GIF 用自定义View实现 2017-06-22 16:28:08 +08:00
8f1f679077 修改代码遗留问题 2017-06-22 15:05:11 +08:00
b632cbba0f 命名规则 2017-06-22 11:08:22 +08:00
de438e90c4 大于两个的if分支,使用switch 2017-06-21 20:54:12 +08:00
7a3b1d4dbe viewpager滑动时,tab无法同步问题 2017-06-21 17:17:35 +08:00
44e9b4da4d Activity 统一入口 2017-06-21 12:03:27 +08:00
559710b4b4 部分Intent.putExtras参数传递实体类 用Parcelable来处理, 修复游戏插件下载闪退 2017-06-20 18:29:49 +08:00
a05c5b4976 登录页面 2017-06-20 09:30:49 +08:00
51cfe767ee 合并冲突 2017-06-19 11:30:25 +08:00
0891e78b8d Merge remote-tracking branch 'origin/3.0' into 3.0
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java
2017-06-19 11:06:16 +08:00
5c834ec09c gradle引入weiboSDK,接入第三点登录(QQ、微信、微博(未完善)), 我的光环改版 2017-06-19 11:05:16 +08:00
fc5b6ae4e4 1、处理viewpager fragment
2、将MainActivity管理的逻辑移到MainFragment,MessageFragment,NewsFragment同理,
3、处理首页ViewPager等手动计算size的问题
4、添加一堆ScaleXXXView,可以用来设定View本身的比例大小

TODO
1、将DownloadManagerActivity也处理成Fragment
2、其他界面也慢慢处理成Fragment
2017-06-17 15:52:42 +08:00
5e668d9e13 fix deprecated 2017-06-16 16:12:28 +08:00
b3d63c5698 1、处理viewholder
2、处理adapter
3、
2017-06-16 15:39:45 +08:00
079c160268 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2017-06-16 14:11:25 +08:00
f5425c2bea 1、统一所有fragment初始化流程,继承自BaseFragment
2、统一大部分viewholder
3、TODO fragment adapter viewholder的分包还没处理完成
2017-06-16 14:11:18 +08:00
1803 changed files with 93535 additions and 46247 deletions

4
.gitignore vendored
View File

@ -5,4 +5,6 @@ local.properties
# sign.properties
.DS_Store
captures/
build/
build/
release-app/
scripts/apk-channel/

4
.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "libraries/LGLibrary"]
path = libraries/LGLibrary
url = git@gitlab.ghzhushou.com:client/client-common.git
branch = master

17
CHANGELOG.md Normal file
View File

@ -0,0 +1,17 @@
### Ver 3.1
### Ver 3.0
* 升级账号系统(登录流程/用户信息相关/用户账号相关操作(评论,礼包...))
* 新增收藏功能(文章/工具箱)
* 删除用户相关的所有本地数据库
* 重做总开服表
* 重做首页插件化模块
* 礼包重复领取机制改变(可重复领取的礼包,领取后立刻显示再领一个/再淘一个)
* 游戏下载平台面板修改(加快弹出速度,不再读取本地平台图片)
* 接入bugly(tinker)
### Ver 2.6
* xx
### Ver 2.5
* 此处写本次更新所做的业务和代码修改

View File

@ -1,23 +1,66 @@
# 光环助手Android客户端
### 多渠道打包配置
* 使用[ApkChannelPackage](https://github.com/ltlovezh/ApkChannelPackage)的方案
### APK打包配置
* 正式打包命令:请使用./gradlew channelRelease打包渠道包
* 使用[ApkChannelPackage](https://github.com/ltlovezh/ApkChannelPackage)的方案
* 打包命令,视情况使用:
> 打包Tinker基准包`./scripts/tinker_release_base.sh`
> 以Tinker基准包打渠道包`./scripts/tinker_release_channel.sh`
> 以Tinker基准包打补丁包`./scripts/tinker_release_patch.sh`
### 混淆配置
* 配置文件Android默认配置+proguard-rules.txt等
* 参考libraries下每个项目独立的配置文件``proguard-project.txt``
* 参考libraries下每个项目独立的配置文件`proguard-project.txt`
### apk大小优化
* 限制resConfig资源集
* 开启ShrinkResources
* 开启混淆使用minifyEnabled(仅在release开启
* pngquant对png压缩、png/jpg->webp(未尝试)
### 第三方appkey等配置
* 修改``gradle.properties``文件将各种key填入其中实现统一管理
* 修改`gradle.properties`文件将各种key填入其中实现统一管理
* 通过gradle文件内的resValue/buildConfigField/manifestPlaceHolder方式实现编译期间修改具体情况请参考``./build.gradle``和``./app/build.gradle``配置
### Ver 2.5
* 此处写本次更新所做的业务和代码修改
### 拉取代码步骤
1. 拉取主项目代码: `git clone -b dev git@gitlab.ghzhushou.com:halo/assistant-android.git`
2. 初始化公用类库: `bash ./scripts/submodules_init.sh`
### submodule管理方式(只拉取master)
* 提交代码需要cd到submodule文件夹去做修改
* 更新远端代码,`bash ./scripts/submodules_update.sh`
### TODO
* GSON 序列化用统一的一个, GsonUtil fromJson
* CleanApkAdapter 转化字符串size工具函数 比如SpeedUtils
* getString 解决 字符串hardcode问题
* ~~Adapter 里面clicklistener 用接口传参将点击操作委托给controller~~
* ~~Adapter ViewHolder的功能部分重写到ViewHolder类本身~~
* ~~activity 统一入口未完成(外部入口相关)去除多余activity使用统一toolbar~~
* ~~release / debug compile不同的类库不需要再做什么开关~~
* ~~Toolbar分离有图形按钮/没有图形按钮~~
### TODO Since 3.1
- 解决 Utils 工具类引发的内存泄漏问题
- 把原有 EventBus 的消息 Type 统一到一个文件内
- 将实现细节从 View(Fragment、Activity) 剥离并以 MVVM 结构改造
- ~~将 ListViewModel 所对应的 ListRepository 合并到 ListViewModel 中~~
- 依照光环助手界面功能以大模块 - 小模块的方式去修改包结构,包内文件建议以包名摘要作为前缀
- ~~使用 RxJava 的 Debounce 和 Map 操作优化搜索触发机制 参考资料:[1](https://proandroiddev.com/building-an-autocompleting-edittext-using-rxjava-f69c5c3f5a40),[2](https://medium.com/@kurtisnusbaum/rxandroid-basics-part-2-6e877af352)~~
- ~~把 ListViewModel 的数据结构类型转换方式换为抽象方法,让继承的类实现,避免出现无响应的问题~~
- ~~rxjava2 如果接口返回为空 会发生异常:java.lang.NullPointerException: Null is not a valid element (答案编辑) 解决方法->com.gh.gamecenter.retrofit.Response~~
- constraintLayout 1.1.2 导致布局出现异常(问题编辑标签选择弹窗)

View File

@ -1,29 +1,40 @@
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
//tinker插件
//apply plugin: 'com.tencent.tinker.patch'
apply plugin: 'org.jetbrains.kotlin.android.extensions'
apply plugin: 'kotlin-android' // kotlin
apply plugin: 'kotlin-kapt'
// apkChannelPackage
apply plugin: 'channel'
apply from: 'tinker-support.gradle'
android {
androidExtensions {
experimental = true
}
dataBinding {
enabled = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
dexOptions {
jumboMode = true
// jumboMode = true
javaMaxHeapSize "4g"
}
defaultConfig {
multiDexEnabled true
javaCompileOptions {
annotationProcessorOptions {
arguments = [ eventBusIndex : 'com.bandeng.MyEventBusIndex' ]
arguments = [eventBusIndex: 'com.gh.EventBusIndex']
}
}
@ -40,35 +51,24 @@ android {
// 由于app只针对中文用户所以仅保留zh资源其他删掉
resConfigs "zh"
// jackOptions {
// enabled true
// }
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
applicationId rootProject.ext.applicationId
multiDexEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt'
/**
* All third-party appid/appkey
*/
buildConfigField "String", "WECHAT_APPID", "\"${WECHAT_APPID}\""
buildConfigField "String", "WECHAT_SECRET", "\"${WECHAT_SECRET}\""
buildConfigField "String", "TENCENT_APPID", "\"${TENCENT_APPID}\""
buildConfigField "String", "WEIBO_APPKEY", "\"${WEIBO_APPKEY}\""
buildConfigField "String", "MIPUSH_APPID", "\"${MIPUSH_APPID}\""
buildConfigField "String", "MIPUSH_APPKEY", "\"${MIPUSH_APPKEY}\""
buildConfigField "String", "MTA_APPKEY", "\"${MTA_APPKEY}\""
buildConfigField "String", "TD_APPID", "\"${TD_APPID}\""
buildConfigField "String", "UMENG_APPKEY", "\"${UMENG_APPKEY}\""
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${UMENG_MESSAGE_SECRET}\""
buildConfigField "String", "DEBUG_UMENG_APPKEY", "\"${DEBUG_UMENG_APPKEY}\""
buildConfigField "String", "DEBUG_UMENG_MESSAGE_SECRET", "\"${DEBUG_UMENG_MESSAGE_SECRET}\""
buildConfigField "String", "DEBUG_MIPUSH_APPID", "\"${DEBUG_MIPUSH_APPID}\""
buildConfigField "String", "DEBUG_MIPUSH_APPKEY", "\"${DEBUG_MIPUSH_APPKEY}\""
buildConfigField "String", "PATCH_VERSION_NAME", "\"${PATCH_VERSION_NAME}\""
}
@ -89,7 +89,10 @@ android {
debuggable true
minifyEnabled false
zipAlignEnabled false
versionNameSuffix "-debug"
signingConfig signingConfigs.debug
buildConfigField "String", "EXPOSURE_REPO", "\"test\""
buildConfigField "String", "EXPOSURE_VERSION", "\"E1\""
}
release {
debuggable false
@ -97,45 +100,61 @@ android {
zipAlignEnabled true
shrinkResources true
signingConfig signingConfigs.release
buildConfigField "String", "EXPOSURE_REPO", "\"exposure\""
buildConfigField "String", "EXPOSURE_VERSION", "\"E1\""
}
}
flavorDimensions "nonsense"
/**
* 多渠道打包所有渠道值均通过java code设置
* 多渠道打包,渠道请参考"channel.txt"文件,所有渠道值均通过java code设置
*/
// productFlavors {
// GH_100 {}
// GH_101 {}
// GH_102 {}
// GH_103 {}
// GH_104 {}
// GH_106 {}
// GH_107 {}
// GH_108 {}
// GH_109 {}
// GH_110 {}
// GH_111 {}
// GH_113 {}
// GH_114 {}
// GH_115 {}
// GH_116 {}
// GH_117 {}
// GH_118 {}
// GH_119 {}
// GH_120 {}
// GH_121 {}
// GH_123 {}
// GH_127 {}
// GH_200 {}
// GH_201 {}
// GH_202 {}
// GH_203 {}
// GH_204 {}
// GH_205 {}
// GH_222 {}
// GH_307 {}
// GH_TEST {}
// }
productFlavors {
// publish release host
publish {
dimension "nonsense"
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
buildConfigField "String", "USER_HOST", "\"${USER_HOST}\""
buildConfigField "String", "COMMENT_HOST", "\"${COMMENT_HOST}\""
buildConfigField "String", "LIBAO_HOST", "\"${LIBAO_HOST}\""
buildConfigField "String", "MESSAGE_HOST", "\"${MESSAGE_HOST}\""
buildConfigField "String", "DATA_HOST", "\"${DATA_HOST}\""
buildConfigField "String", "UMENG_APPKEY", "\"${UMENG_APPKEY}\""
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${UMENG_MESSAGE_SECRET}\""
buildConfigField "String", "MIPUSH_APPID", "\"${MIPUSH_APPID}\""
buildConfigField "String", "MIPUSH_APPKEY", "\"${MIPUSH_APPKEY}\""
buildConfigField "String", "MEIZUPUSH_APPID", "\"${MEIZUPUSH_APPID}\""
buildConfigField "String", "MEIZUPUSH_APPKEY", "\"${MEIZUPUSH_APPKEY}\""
buildConfigField "String", "BUGLY_APPID", "\"${BUGLY_APPID}\""
}
// internal test dev host
internal {
dimension "nonsense"
versionNameSuffix "-debug"
buildConfigField "String", "API_HOST", "\"${DEV_API_HOST}\""
buildConfigField "String", "USER_HOST", "\"${DEV_USER_HOST}\""
buildConfigField "String", "COMMENT_HOST", "\"${DEV_COMMENT_HOST}\""
buildConfigField "String", "LIBAO_HOST", "\"${DEV_LIBAO_HOST}\""
buildConfigField "String", "MESSAGE_HOST", "\"${DEV_MESSAGE_HOST}\""
buildConfigField "String", "DATA_HOST", "\"${DEV_DATA_HOST}\""
buildConfigField "String", "UMENG_APPKEY", "\"${DEBUG_UMENG_APPKEY}\""
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${DEBUG_UMENG_MESSAGE_SECRET}\""
buildConfigField "String", "MIPUSH_APPID", "\"${DEBUG_MIPUSH_APPID}\""
buildConfigField "String", "MIPUSH_APPKEY", "\"${DEBUG_MIPUSH_APPKEY}\""
buildConfigField "String", "MEIZUPUSH_APPID", "\"${DEBUG_MEIZUPUSH_APPID}\""
buildConfigField "String", "MEIZUPUSH_APPKEY", "\"${DEBUG_MEIZUPUSH_APPKEY}\""
buildConfigField "String", "BUGLY_APPID", "\"${DEBUG_BUGLY_APPID}\""
}
}
// productFlavors.all { flavor ->
// flavor.manifestPlaceholders = [CHANNEL_VALUE: name]//命令 gradlew assembleRelease
// }
@ -150,12 +169,6 @@ channel {
apkNameFormat = '${appName}-${versionName}-${versionCode}-${flavorName}-${buildType}'
}
apt {
arguments {
eventBusIndex "com.bandeng.MyEventBusIndex"
}
}
rebuildChannel {
// baseDebugApk = 已有Debug APK
// baseReleaseApk = 已有Release APK
@ -166,83 +179,108 @@ rebuildChannel {
}
dependencies {
testCompile test.junit
compile fileTree(include: '*.jar', dir: 'libs')
compile libs.supportMultidex
compile libs.supportDesign
compile libs.supportAppCompat
compile libs.supportAnnotation
compile libs.supportPercent
compile libs.supportDesign
compile libs.switchButton
implementation fileTree(include: '*.jar', dir: 'libs')
compile libs.systemBarTint
debugImplementation "com.squareup.leakcanary:leakcanary-android:${leakcanary}"
debugImplementation "com.facebook.stetho:stetho:${stetho}"
debugImplementation "com.facebook.stetho:stetho-okhttp3:${stetho}"
debugImplementation "com.squareup.okhttp3:logging-interceptor:${okHttp}"
compile libs.fresco
compile libs.frescoAnimatedGif
implementation "com.android.support:multidex:${multidex}"
implementation "com.android.support:design:${androidSupport}"
implementation "com.android.support:support-v4:${androidSupport}"
implementation "com.android.support:appcompat-v7:${androidSupport}"
implementation "com.android.support:cardview-v7:${androidSupport}"
implementation "com.android.support:support-annotations:${androidSupport}"
implementation "com.android.support:percent:${androidSupport}"
implementation "com.android.support.constraint:constraint-layout:${constraintLayout}"
implementation "com.kyleduo.switchbutton:library:${switchButton}"
compile libs.okHttp
compile libs.okHttpLogInterceptor
implementation "com.facebook.fresco:fresco:${fresco}"
implementation "com.facebook.fresco:animated-gif:${fresco}"
compile libs.apkChannelPackage
implementation "com.squareup.okhttp3:okhttp:${okHttp}"
// debugCompile libs.stetho
// debugCompile libs.stethoWithOkHttp
implementation "com.leon.channel:helper:${apkChannelPackage}"
compile libs.retrofit
compile libs.retrofitWithGson // include gson 2.7
compile libs.retrofitWithRxJava
// compile libs.gson
implementation "com.squareup.retrofit2:retrofit:${retrofit}"
implementation "com.squareup.retrofit2:converter-gson:${retrofit}" // include gson 2.7
implementation "com.squareup.retrofit2:adapter-rxjava2:${retrofit}"
compile libs.ormliteAndroid
compile libs.ormliteCore
implementation "com.j256.ormlite:ormlite-android:${ormlite}"
implementation "com.j256.ormlite:ormlite-core:${ormlite}"
compile libs.butterKnife
apt libs.butterKnifeApt
implementation "com.jakewharton:butterknife:${butterKnife}"
annotationProcessor "com.jakewharton:butterknife-compiler:${butterKnife}"
kapt "com.jakewharton:butterknife-compiler:${butterKnife}"
implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
compile libs.rxJava
compile libs.rxAndroid
compile libs.rxBinding
compile libs.zxing
compile libs.zxingAndroid
implementation "org.greenrobot:eventbus:${eventbus}"
annotationProcessor "org.greenrobot:eventbus-annotation-processor:${eventbusApt}"
compile libs.swipeLayout
compile(libs.autoScrollViewPager) {
implementation "io.reactivex.rxjava2:rxjava:${rxJava2}"
implementation "io.reactivex.rxjava2:rxandroid:${rxAndroid2}"
implementation "com.jakewharton.rxbinding2:rxbinding:${rxBinding2}"
implementation "com.google.zxing:core:${zxing}"
implementation "com.google.zxing:android-core:${zxing}"
implementation "com.daimajia.swipelayout:library:${swipeLayout}"
implementation("cn.trinea.android.view.autoscrollviewpager:android-auto-scroll-view-pager:${autoScrollViewPager}") {
exclude module: 'support-v4'
}
// tinker
// provided libs.tinker_anno
// compile libs.tinker_lib
implementation "com.sina.weibo.sdk:core:${weiboSDK}"
compile libs.eventbus
apt libs.eventbusApt
// compile project(':libraries:EventBus')
compile project(':libraries:MiPush')
compile project(':libraries:MTA')
compile project(':libraries:QQShare')
compile project(':libraries:TalkingData')
compile project(':libraries:UmengPush')
compile project(':libraries:WechatShare')
compile project(':libraries:WeiboShare')
compile project(':libraries:iosched')
// bugly with tinker support
implementation "com.tencent.bugly:crashreport_upgrade:${buglyTinkerSupport}"
implementation "pub.devrel:easypermissions:${easypermissions}"
// mvvm
implementation "android.arch.lifecycle:runtime:${archLifecycleVersion}"
kapt "android.arch.lifecycle:compiler:${archLifecycleVersion}"
implementation "android.arch.lifecycle:extensions:${archLifecycleVersion}"
implementation "android.arch.persistence.room:runtime:${archRoomVersion}"
kapt "android.arch.persistence.room:compiler:${archRoomVersion}"
implementation 'com.google.android:flexbox:0.2.2'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
kapt 'com.android.databinding:compiler:3.1.3'
implementation 'com.contrarywind:Android-PickerView:4.1.3'
implementation "com.scwang.smartrefresh:SmartRefreshLayout:${smartRefreshLayout}"
implementation "net.cachapa.expandablelayout:expandablelayout:${expandableLayout}"
implementation "top.zibin:Luban:${luban}"
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:iosched')
implementation project(':libraries:LogHub')
implementation project(':libraries:im')
}
File propFile = file('sign.properties');
File propFile = file('sign.properties')
if (propFile.exists()) {
def Properties props = new Properties()
Properties props = new Properties()
props.load(new FileInputStream(propFile))
if (props.containsKey('keyAlias') && props.containsKey('keyPassword') &&
props.containsKey('storeFile') && props.containsKey('storePassword')) {
android.signingConfigs {
// debug {
// keyAlias props.get('keyAlias')
// keyPassword props.get('keyPassword')
// storeFile file(props.get('storeFile'))
// storePassword props.get('storePassword')
// }
// debug 不要使用正式签名这样tinker才不会打补丁。
debug {
keyAlias props.get('keyAlias')
keyPassword props.get('keyPassword')
storeFile file(props.get('storeFile'))
storePassword props.get('storePassword')
}
release {
keyAlias props.get('keyAlias')
keyPassword props.get('keyPassword')
@ -256,3 +294,31 @@ if (propFile.exists()) {
} else {
android.buildTypes.release.signingConfig = null
}
// 用于测试读取 META-INF 里的 JSON 的代码
//task generateMetaJson {
// def resDir = new File(buildDir, 'generated/FILES_FOR_META_INF/')
// def destDir = new File(resDir, 'META-INF/')
// // Add resDir as a resource directory so that it is automatically included in the APK.
// android {
// sourceSets {
// main.resources {
// srcDir resDir
// }
// }
// }
//
// doLast {
// if (!destDir.exists()) destDir.mkdirs()
// copy {
// into destDir
// from new File('generated/FILES_FOR_META_INF/META-INF/halo_skip.json')
// }
// }
//}
//// Specify when put_files_in_META_INF should run
//project.afterEvaluate {
// tasks.findAll { task ->
// task.name.startsWith('merge') && task.name.endsWith('Resources')
// }.each { t -> t.dependsOn generateMetaJson }
//}

View File

@ -16,9 +16,23 @@
# public *;
#}
#--------- remove logs start ----------------
-assumenosideeffects class com.lightgame.config.CommonDebug {
private static String getLogTag(...);
private static String getMethodName();
public static void logMethodName(...);
public static void logParams(...);
public static void logFields(...);
public static void logMethodWithParams(...);
}
#-assumenosideeffects class com.lightgame.config.CommonDebug {*;}
#-dontoptimize
#--------- remove logs end ----------------
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod
-dontwarn InnerClasses
-dontoptimize
# OrmLite uses reflection
-keep class com.j256.**
@ -117,11 +131,16 @@
<init>(java.lang.Throwable);
}
# weiboSdk
-keep class com.sina.weibo.sdk.** { *; }
-dontwarn android.webkit.WebView
-dontwarn android.webkit.WebViewClient
# app models
-keep class com.gh.common.view.** {*;}
-keep class com.gh.gamecenter.db.info.** {*;}
-keep class com.gh.gamecenter.entity.** {*;}
-keep class com.gh.gamecenter.qa.entity.** {*;}
-keep class com.gh.gamecenter.retrofit.** {*;}
-keep class com.gh.gamecenter.eventbus.** {*;}
-keep class * extends rx.Subscriber
@ -157,4 +176,25 @@
-keepclassmembers enum * { *; }
##---------------End: proguard configuration for Gson ----------
##---------------End: proguard configuration for Gson ----------
# ------ bugly ---------
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
# easypermission
-keepclassmembers class * {
@pub.devrel.easypermissions.AfterPermissionGranted <methods>;
}
# 重命名文件为SourceFile再配合mapping符号表可以拿到真实的类名
-renamesourcefileattribute SourceFile
# 保留源文件行号
-keepattributes SourceFile,LineNumberTable
-ignorewarnings
-keep @android.support.annotation.Keep class *
-keepclassmembers class ** {
@android.support.annotation.Keep *;
}

View File

@ -1,13 +0,0 @@
package com.gh.gamecenter;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

View File

@ -0,0 +1,46 @@
package com.gh.gamecenter;
import android.app.Application;
import com.facebook.stetho.Stetho;
import com.facebook.stetho.okhttp3.StethoInterceptor;
import com.squareup.leakcanary.LeakCanary;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
/**
* @author CsHeng
* @Date 03/09/2017
* @Time 4:34 PM
*/
public class Injection {
public static boolean appInit(Application application) {
// init leakcanary
if (LeakCanary.isInAnalyzerProcess(application)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return false;
}
LeakCanary.install(application);
// init stetho
Stetho.initializeWithDefaults(application);
return true;
}
public static OkHttpClient.Builder provideRetrofitBuilder() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.addNetworkInterceptor(interceptor);
builder.addNetworkInterceptor(new StethoInterceptor());
return builder;
}
}

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android = "http://schemas.android.com/apk/res/android"
xmlns:tools = "http://schemas.android.com/tools"
package = "com.gh.gamecenter" >
<!-- 允许应用程序访问网络连接 -->
@ -39,6 +40,14 @@
<!-- 修改系统设置的权限 -->
<uses-permission android:name = "android.permission.WRITE_SETTINGS" />
<!-- bugly with tinker -->
<uses-permission android:name = "android.permission.READ_PHONE_STATE" />
<uses-permission android:name = "android.permission.INTERNET" />
<uses-permission android:name = "android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name = "android.permission.READ_LOGS" />
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
<supports-screens
android:anyDensity = "true"
android:largeScreens = "true"
@ -48,35 +57,42 @@
<!--android:largeHeap = "true"-->
<application
android:name = "com.gh.base.AppController"
android:name = "com.halo.assistant.TinkerApp"
android:allowBackup = "true"
android:icon = "@drawable/logo"
android:label = "@string/app_name"
android:theme = "@style/AppCompatTheme" >
android:resizeableActivity = "true"
android:theme = "@style/AppCompatTheme.APP"
tools:targetApi = "n" >
<!--android:launchMode = "singleTask"-->
<activity
android:name = "com.gh.gamecenter.SplashScreenActivity"
android:configChanges = "keyboardHidden|orientation|screenSize"
android:noHistory = "true"
android:screenOrientation = "portrait"
android:theme = "@style/AppGuideTheme"
android:uiOptions = "splitActionBarWhenNarrow" >
android:theme = "@style/AppGuideTheme" >
<intent-filter >
<action android:name = "android.intent.action.MAIN" />
<category android:name = "android.intent.category.LAUNCHER" />
</intent-filter >
</activity >
<activity
android:name = "com.gh.gamecenter.MainActivity"
android:launchMode = "singleTop"
android:launchMode = "singleTask"
android:screenOrientation = "portrait"
android:windowSoftInputMode = "stateAlwaysHidden|adjustResize" />
<activity
android:name = "com.gh.gamecenter.DownloadManagerActivity"
android:launchMode = "singleTask"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.ViewImageActivity"
android:theme = "@android:style/Theme.Black.NoTitleBar.Fullscreen" />
<!--android:theme = "@android:style/Theme.Black.NoTitleBar.Fullscreen" 退出时屏幕抖动 -->
<activity android:name = "com.gh.gamecenter.ViewImageActivity" />
<activity
android:name = "com.gh.gamecenter.SearchActivity"
android:configChanges = "keyboardHidden"
@ -91,7 +107,7 @@
android:name = "com.gh.gamecenter.ConcernActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.SubjectActivity"
android:name = "com.gh.gamecenter.subject.refactor.SubjectActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.PluginActivity"
@ -99,7 +115,7 @@
<activity
android:name = "com.gh.gamecenter.NewsSearchActivity"
android:screenOrientation = "portrait"
android:windowSoftInputMode="stateHidden"/>
android:windowSoftInputMode = "stateHidden" />
<activity
android:name = "com.gh.gamecenter.GameNewsActivity"
android:screenOrientation = "portrait" />
@ -121,7 +137,7 @@
<activity
android:name = "com.gh.gamecenter.LibaoActivity"
android:screenOrientation = "portrait"
android:windowSoftInputMode="stateHidden"/>
android:windowSoftInputMode = "stateHidden" />
<activity
android:name = "com.gh.gamecenter.LibaoDetailActivity"
android:screenOrientation = "portrait" />
@ -155,9 +171,6 @@
<activity
android:name = "com.gh.gamecenter.AboutActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.KaiFuActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.CommentDetailActivity"
android:screenOrientation = "portrait" />
@ -169,8 +182,7 @@
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.SuggestionActivity"
android:screenOrientation = "portrait"
android:windowSoftInputMode = "stateHidden|adjustResize" />
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.VoteActivity"
android:screenOrientation = "portrait"
@ -178,7 +190,166 @@
<activity
android:name = "com.gh.gamecenter.ToolBoxActivity"
android:screenOrientation = "portrait"
android:windowSoftInputMode="stateHidden"/>
android:windowSoftInputMode = "stateHidden" />
<activity
android:name = "com.gh.gamecenter.WeiBoShareActivity"
android:screenOrientation = "portrait"
android:windowSoftInputMode = "stateHidden" />
<activity
android:name = "com.gh.gamecenter.InstallActivity"
android:screenOrientation = "portrait" />
<activity
android:name = ".category.CategoryDirectoryActivity"
android:screenOrientation = "portrait" />
<activity
android:name = ".category.CategoryListActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.LoginActivity"
android:screenOrientation = "portrait"
android:windowSoftInputMode = "stateHidden" />
<activity
android:name = "com.gh.gamecenter.UserInfoActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.UserRegionActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.CollectionActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.MessageActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.UserInfoEditActivity"
android:screenOrientation = "portrait"
android:windowSoftInputMode = "stateHidden" />
<activity
android:name = "com.gh.gamecenter.KaiFuActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.search.AskSearchActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity"
android:screenOrientation = "portrait" />
<activity
android:name = ".qa.answer.fold.AnswerFoldActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.answer.edit.AnswerEditActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.ConcernInfoActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.InfoActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.MessageKeFuActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.select.CommunitiesSelectActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.subject.CommunitySubjectActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.MessageInviteActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.MessageVoteActivity"
android:screenOrientation = "portrait" />
<activity
android:name = ".qa.questions.invite.QuestionsInviteActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.myqa.MyAskActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.column.order.AskTabOrderActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.questions.edit.QuestionEditActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.kaifu.add.AddKaiFuActivity"
android:screenOrientation = "portrait"
android:windowSoftInputMode = "stateHidden" />
<activity
android:name = "com.gh.gamecenter.kaifu.patch.PatchKaifuActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.BlockActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.NetworkDiagnosisActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.personalhome.fans.FansActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.personalhome.fans.FollowersActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.PersonalHomeActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.personalhome.answer.PersonalAnswerActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.personalhome.question.PersonalQuestionActivity"
android:screenOrientation = "portrait" />
<!-- 使用小米/华为推送弹窗功能提高推送成功率-->
<activity
android:name = "com.gh.gamecenter.PushProxyActivity"
android:exported = "true"
android:theme = "@android:style/Theme.Translucent" />
<activity
android:name = "com.gh.gamecenter.SkipActivity"
android:theme = "@style/Theme.AppCompat.Light.Fullscreen.Transparent" >
@ -191,6 +362,10 @@
</intent-filter >
</activity >
<activity
android:name = ".CommonActivity"
android:screenOrientation = "portrait" />
<receiver android:name = "com.gh.gamecenter.receiver.InstallAndUninstallReceiver" >
<intent-filter >
<action android:name = "android.intent.action.PACKAGE_ADDED" />
@ -200,13 +375,7 @@
<data android:scheme = "package" />
</intent-filter >
</receiver >
<receiver
android:name = "com.gh.gamecenter.receiver.NotificationReceiver"
android:exported = "false" >
<intent-filter >
<action android:name = "com.gh.gamecenter.NOTIFICATION" />
</intent-filter >
</receiver >
<receiver
android:name = "com.gh.gamecenter.receiver.DownloadReceiver"
android:exported = "false" >
@ -235,9 +404,41 @@
</intent-filter >
</receiver >
<service android:name = "com.gh.download.DownloadService" />
<receiver android:name = "com.gh.gamecenter.receiver.UmengMessageReceiver" >
<intent-filter >
<action android:name = "com.gh.gamecenter.UMENG" />
</intent-filter >
</receiver >
<service android:name = "com.gh.gamecenter.statistics.AppStaticService" />
<!--魅族push应用定义消息receiver声明 -->
<receiver android:name="com.gh.gamecenter.receiver.MeizuPushReceiver">
<intent-filter>
<!-- 接收push消息 -->
<action android:name="com.meizu.flyme.push.intent.MESSAGE" />
<!-- 接收register消息 -->
<action android:name="com.meizu.flyme.push.intent.REGISTER.FEEDBACK" />
<!-- 接收unregister消息-->
<action android:name="com.meizu.flyme.push.intent.UNREGISTER.FEEDBACK" />
<!-- 兼容低版本Flyme3推送服务配置 -->
<action android:name="com.meizu.c2dm.intent.REGISTRATION" />
<action android:name="com.meizu.c2dm.intent.RECEIVE" />
<category android:name="${applicationId}"/>
</intent-filter>
</receiver>
<receiver
android:name="com.gh.common.im.ImReceiver"
android:enabled="true">
<intent-filter android:priority="2147483647">
<action android:name="com.gh.im"/>
<action android:name="action_finish"/>
</intent-filter>
</receiver>
<service android:name = "com.gh.base.GHUmengNotificationService" />
<!--<service android:name = "com.gh.gamecenter.statistics.AppStaticService" />-->
</application >

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
function requestContentFocus() {
$('#editor').focus();
}
function setupWhenContentEditable() {
var editor = $('#editor');
if (!editor[0].hasAttribute('contenteditable')) {
return;
}
// paste 回调只会获取粘贴之前的光标位置,需要自己手动加上粘贴文本的长度,并保证粘贴的是纯文本
editor.on('paste', function(e) {
e.preventDefault();
var text = (e.originalEvent || e).clipboardData.getData('text/plain');
text = text.replace(/\n/g, '<br>');
if("" != text) {
document.execCommand("insertHTML", false, text);
} else {
window.onPasteListener.onPaste();
}
});
requestContentFocus();
}
$(document).ready(function() {
setupWhenContentEditable();
});

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="user-scalable=no">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="normalize.css">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="editor" contenteditable="true"></div>
<script type="text/javascript" src="zepto.min.js"></script>
<script type="text/javascript" src="rich_editor.js"></script>
<script type="text/javascript" src="content.js"></script>
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/vanilla-lazyload/10.15.0/lazyload.min.js"></script>-->
</body>
</html>

View File

@ -0,0 +1,40 @@
emoji_kf_1.png,:smile:
emoji_kf_2.png,:smiley:
emoji_kf_3.png,:laughing:
emoji_kf_4.png,:blush:
emoji_kf_5.png,:heart_eyes:
emoji_kf_6.png,:smirk:
emoji_kf_7.png,:flushed:
emoji_kf_8.png,:kissing_heart:
emoji_kf_9.png,:grin:
emoji_kf_10.png,:wink:
emoji_kf_11.png,:stuck_out_tongue_winking_eye:
emoji_kf_12.png,:stuck_out_tongue_closed eyes:
emoji_kf_13.png,:worried:
emoji_kf_14.png,:sleeping:
emoji_kf_15.png,:expressionless:
emoji_kf_16.png,:sweat_smile:
emoji_kf_17.png,:joy:
emoji_kf_18.png,:cold_sweat:
emoji_kf_19.png,:sob:
emoji_kf_20.png,:angry:
emoji_kf_21.png,:mask:
emoji_kf_22.png,:scream:
emoji_kf_23.png,:sunglasses:
emoji_kf_24.png,:heart:
emoji_kf_25.png,:broken_heart:
emoji_kf_26.png,:star:
emoji_kf_27.png,:anger:
emoji_kf_28.png,:exclamation:
emoji_kf_29.png,:question:
emoji_kf_30.png,:zzz:
emoji_kf_31.png,:thumbsup:
emoji_kf_32.png,:thumbsdown:
emoji_kf_33.png,:ok_hand:
emoji_kf_34.png,:punch:
emoji_kf_35.png,:yeah:
emoji_kf_36.png,:clap:
emoji_kf_37.png,:muscle:
emoji_kf_38.png,:pray:
emoji_kf_39.png,:skull:
emoji_kf_40.png,:trollface:

Binary file not shown.

View File

@ -0,0 +1,5 @@
# This is a simple Microlog configuration file
microlog.level=DEBUG
microlog.appender=LogCatAppender;FileAppender
microlog.formatter=PatternFormatter
microlog.formatter.PatternFormatter.pattern=%c [%P] %m %T

413
app/src/main/assets/normalize.css vendored Normal file
View File

@ -0,0 +1,413 @@
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
/**
* 1. Set default font family to sans-serif.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-family: sans-serif; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/**
* Remove default margin.
*/
body {
margin: 0;
}
/* HTML5 display definitions
========================================================================== */
/**
* Correct `block` display not defined for any HTML5 element in IE 8/9.
* Correct `block` display not defined for `details` or `summary` in IE 10/11
* and Firefox.
* Correct `block` display not defined for `main` in IE 11.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
display: block;
}
/**
* 1. Correct `inline-block` display not defined in IE 8/9.
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
*/
audio,
canvas,
progress,
video {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address `[hidden]` styling not present in IE 8/9/10.
* Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
*/
[hidden],
template {
display: none;
}
/* Links
========================================================================== */
/**
* Remove the gray background color from active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* Text-level semantics
========================================================================== */
/**
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/**
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
*/
b,
strong {
font-weight: bold;
}
/**
* Address styling not present in Safari and Chrome.
*/
dfn {
font-style: italic;
}
/**
* Address variable `h1` font-size and margin within `section` and `article`
* contexts in Firefox 4+, Safari, and Chrome.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/**
* Address styling not present in IE 8/9.
*/
mark {
background: #ff0;
color: #000;
}
/**
* Address inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* Embedded content
========================================================================== */
/**
* Remove border when inside `a` element in IE 8/9/10.
*/
img {
border: 0;
}
/**
* Correct overflow not hidden in IE 9/10/11.
*/
svg:not(:root) {
overflow: hidden;
}
/* Grouping content
========================================================================== */
/**
* Address margin not present in IE 8/9 and Safari.
*/
figure {
margin: 1em 40px;
}
/**
* Address differences between Firefox and other browsers.
*/
hr {
box-sizing: content-box;
height: 0;
}
/**
* Contain overflow in all browsers.
*/
pre {
overflow: auto;
}
/**
* Address odd `em`-unit font size rendering in all browsers.
*/
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
/* Forms
========================================================================== */
/**
* Known limitation: by default, Chrome and Safari on OS X allow very limited
* styling of `select`, unless a `border` property is set.
*/
/**
* 1. Correct color not being inherited.
* Known issue: affects color of disabled elements.
* 2. Correct font properties not being inherited.
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
*/
button,
input,
optgroup,
select,
textarea {
color: inherit; /* 1 */
font: inherit; /* 2 */
margin: 0; /* 3 */
}
/**
* Address `overflow` set to `hidden` in IE 8/9/10/11.
*/
button {
overflow: visible;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
* Correct `select` style inheritance in Firefox.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
input {
line-height: normal;
}
/**
* It's recommended that you don't attempt to style these elements.
* Firefox's implementation doesn't respect box-sizing, padding, or width.
*
* 1. Address box sizing set to `content-box` in IE 8/9/10.
* 2. Remove excess padding in IE 8/9/10.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
* `font-size` values of the `input`, it causes the cursor style of the
* decrement button to change from `default` to `text`.
*/
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
* Safari (but not Chrome) clips the cancel button when the search input has
* padding (and `textfield` appearance).
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct `color` not being inherited in IE 8/9/10/11.
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
*/
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}
/**
* Remove default vertical scrollbar in IE 8/9/10/11.
*/
textarea {
overflow: auto;
}
/**
* Don't inherit the `font-weight` (applied by a rule above).
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
*/
optgroup {
font-weight: bold;
}
/* Tables
========================================================================== */
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
}

View File

@ -0,0 +1,434 @@
/**
* Copyright (C) 2017 Wasabeef
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var RE = {};
RE.currentSelection = {
"startContainer": 0,
"startOffset": 0,
"endContainer": 0,
"endOffset": 0};
RE.editor = document.getElementById('editor');
document.addEventListener("selectionchange", function() { RE.backuprange(); });
// Initializations
RE.callback = function() {
window.location.href = "re-callback://" + encodeURI(RE.getHtml());
}
RE.setHtml = function(contents) {
RE.editor.innerHTML = decodeURIComponent(contents.replace(/\+/g, '%20'));
}
RE.getHtml = function() {
return RE.editor.innerHTML;
}
RE.getText = function() {
return RE.editor.innerText;
}
RE.setBaseTextColor = function(color) {
RE.editor.style.color = color;
}
RE.setBaseFontSize = function(size) {
RE.editor.style.fontSize = size;
}
RE.setPadding = function(left, top, right, bottom) {
RE.editor.style.paddingLeft = left;
RE.editor.style.paddingTop = top;
RE.editor.style.paddingRight = right;
RE.editor.style.paddingBottom = bottom;
}
RE.setBackgroundColor = function(color) {
document.body.style.backgroundColor = color;
}
RE.setBackgroundImage = function(image) {
RE.editor.style.backgroundImage = image;
}
RE.setWidth = function(size) {
RE.editor.style.minWidth = size;
}
RE.setHeight = function(size) {
RE.editor.style.height = size;
}
RE.setTextAlign = function(align) {
RE.editor.style.textAlign = align;
}
RE.setVerticalAlign = function(align) {
RE.editor.style.verticalAlign = align;
}
RE.setPlaceholder = function(placeholder) {
RE.editor.setAttribute("placeholder", placeholder);
}
RE.setEditorFocus = function() {
RE.editor.focus();
}
RE.setInputEnabled = function(inputEnabled) {
RE.editor.contentEditable = String(inputEnabled);
}
RE.setFocusByEnd = function() {
//alert("111111")
// var txt =RE.editor.createTextRange();
// ("22222")
// txt.moveStart('character',-1);
// ("333333")
// txt.collapse(true);
// ("444444")
// txt.select();
// alert("ddddddd")
}
RE.undo = function() {
document.execCommand('undo', false, null);
}
RE.redo = function() {
document.execCommand('redo', false, null);
}
RE.setBold = function() {
document.execCommand('bold', false, null);
}
RE.setItalic = function() {
document.execCommand('italic', false, null);
}
RE.setSubscript = function() {
document.execCommand('subscript', false, null);
}
RE.setSuperscript = function() {
document.execCommand('superscript', false, null);
}
RE.setStrikeThrough = function() {
document.execCommand('strikeThrough', false, null);
}
RE.setUnderline = function() {
document.execCommand('underline', false, null);
}
RE.setBullets = function() {
document.execCommand('insertUnorderedList', false, null);
}
RE.setNumbers = function() {
document.execCommand('insertOrderedList', false, null);
}
RE.setTextColor = function(color) {
RE.restorerange();
document.execCommand("styleWithCSS", null, true);
document.execCommand('foreColor', false, color);
document.execCommand("styleWithCSS", null, false);
}
RE.setTextBackgroundColor = function(color) {
RE.restorerange();
document.execCommand("styleWithCSS", null, true);
document.execCommand('hiliteColor', false, color);
document.execCommand("styleWithCSS", null, false);
}
RE.setFontSize = function(fontSize){
document.execCommand("fontSize", false, fontSize);
}
RE.setHeading = function(heading) {
document.execCommand('formatBlock', false, '<h'+heading+'>');
}
RE.setIndent = function() {
document.execCommand('indent', false, null);
}
RE.setOutdent = function() {
document.execCommand('outdent', false, null);
}
RE.setJustifyLeft = function() {
document.execCommand('justifyLeft', false, null);
}
RE.setJustifyCenter = function() {
document.execCommand('justifyCenter', false, null);
}
RE.setJustifyRight = function() {
document.execCommand('justifyRight', false, null);
}
RE.setBlockquote = function() {
document.execCommand('formatBlock', false, '<blockquote>');
}
RE.insertImage = function(url) {
var html = "<div><img src =\"" + url + "\" style=\" max-width: 100%; display:block; margin:15px auto; height: auto;\"></div><br>"
RE.insertHTML(html);
}
//RE.lazyLoad = function() {
// var myLazyLoad = new LazyLoad({
// elements_selector: ".lazy"
// })
//}
// 替换成缩略图
RE.replaceTbImage = function(imgRuleFlag, gifRuleFlag) {
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
if(img.src.indexOf("?") > 0) continue;
var tbImg
if(img.src.indexOf(".gif") > 0) {
tbImg = img.src + gifRuleFlag
} else {
tbImg = img.src + imgRuleFlag
}
img.style.cssText = "max-width: 60%; display:block; margin:15px auto; height: auto;"
img.src = tbImg;
if (i == 0) {
var bigImg = document.createElement('img');
bigImg.src = "file:///android_asset/web_load_dfimg_icon.png";
bigImg.style.cssText = "max-width: 20%; margin:15px 0 0 0; height: auto;"
img.parentNode.insertBefore(bigImg, img.parentNode.childNodes[0]);
i++;
}
}
}
// 替换成默认图
RE.replaceAllDfImage = function(imgRuleFlag, gifRuleFlag) {
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
if(img.src.indexOf("web_load_dfimg_icon") > 0) {
img.parentNode.removeChild(img.parentNode.childNodes[0]);
i--;
} else {
if(img.src.indexOf(".gif") > 0) {
if(gifRuleFlag.indexOf(",default") > 0) {
img.style.cssText = "max-width: 100%; display:block; margin:8px auto; height: auto;"
img.src = img.src.split("?")[0] + gifRuleFlag
}
} else {
img.style.cssText = "max-width: 100%; display:block; margin:8px auto; height: auto;"
img.src = img.src.split("?")[0] + imgRuleFlag
}
}
}
}
// 去除显示大图
RE.hideShowBigPic = function() {
var imgs = document.getElementsByTagName("img");
var j = 0;
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
if(img.src.indexOf(",thumbnail") > 0 && img.src.indexOf(".gif") == -1) {
j++;
}
}
// 去除显示大图
if (j == 0) {
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
if(img.src.indexOf("web_load_dfimg_icon") > 0) {
img.parentNode.removeChild(img.parentNode.childNodes[0]);
break;
}
}
}
}
RE.replaceDfImageByUrl = function(imgUrl, imgRuleFlag, gifRuleFlag) {
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
if (img.src.indexOf(imgUrl) != -1) {
img.style.cssText = "max-width: 100%; display:block; margin:8px auto; height: auto;"
if(img.src.indexOf(".gif") > 0) {
img.src = img.src.split("?")[0] + gifRuleFlag
} else {
img.src = img.src.split("?")[0] + imgRuleFlag
}
}
}
RE.hideShowBigPic();
}
RE.ImageClickListener = function() {
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
window.imagelistener.imageArr(img.src);
img.onclick = function() {
window.imagelistener.imageClick(this.src);
}
}
}
RE.insertHTML = function(html) {
RE.restorerange();
document.execCommand('insertHTML', false, html);
}
RE.insertLink = function(url, title) {
RE.restorerange();
var sel = document.getSelection();
if (sel.toString().length == 0) {
document.execCommand("insertHTML",false,"<a href='"+url+"'>"+title+"</a>");
} else if (sel.rangeCount) {
var el = document.createElement("a");
el.setAttribute("href", url);
el.setAttribute("title", title);
var range = sel.getRangeAt(0).cloneRange();
range.surroundContents(el);
sel.removeAllRanges();
sel.addRange(range);
}
RE.callback();
}
RE.setTodo = function(text) {
var html = '<input type="checkbox" name="'+ text +'" value="'+ text +'"/> &nbsp;';
document.execCommand('insertHTML', false, html);
}
RE.prepareInsert = function() {
RE.backuprange();
}
RE.backuprange = function(){
var selection = window.getSelection();
if (selection.rangeCount > 0) {
var range = selection.getRangeAt(0);
RE.currentSelection = {
"startContainer": range.startContainer,
"startOffset": range.startOffset,
"endContainer": range.endContainer,
"endOffset": range.endOffset};
}
}
RE.restorerange = function(){
var selection = window.getSelection();
selection.removeAllRanges();
var range = document.createRange();
range.setStart(RE.currentSelection.startContainer, RE.currentSelection.startOffset);
range.setEnd(RE.currentSelection.endContainer, RE.currentSelection.endOffset);
selection.addRange(range);
}
RE.enabledEditingItems = function(e) {
var items = [];
if (document.queryCommandState('bold')) {
items.push('bold');
}
if (document.queryCommandState('italic')) {
items.push('italic');
}
if (document.queryCommandState('subscript')) {
items.push('subscript');
}
if (document.queryCommandState('superscript')) {
items.push('superscript');
}
if (document.queryCommandState('strikeThrough')) {
items.push('strikeThrough');
}
if (document.queryCommandState('underline')) {
items.push('underline');
}
if (document.queryCommandState('insertOrderedList')) {
items.push('orderedList');
}
if (document.queryCommandState('insertUnorderedList')) {
items.push('unorderedList');
}
if (document.queryCommandState('justifyCenter')) {
items.push('justifyCenter');
}
if (document.queryCommandState('justifyFull')) {
items.push('justifyFull');
}
if (document.queryCommandState('justifyLeft')) {
items.push('justifyLeft');
}
if (document.queryCommandState('justifyRight')) {
items.push('justifyRight');
}
if (document.queryCommandState('insertHorizontalRule')) {
items.push('horizontalRule');
}
var formatBlock = document.queryCommandValue('formatBlock');
if (formatBlock.length > 0) {
items.push(formatBlock);
}
window.location.href = "re-state://" + encodeURI(items.join(','));
}
RE.focus = function() {
var range = document.createRange();
range.selectNodeContents(RE.editor);
range.collapse(false);
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
RE.editor.focus();
}
RE.blurFocus = function() {
RE.editor.blur();
}
RE.removeFormat = function() {
document.execCommand('removeFormat', false, null);
}
// Event Listeners
RE.editor.addEventListener("input", RE.callback);
RE.editor.addEventListener("keyup", function(e) {
var KEY_LEFT = 37, KEY_RIGHT = 39;
if (e.which == KEY_LEFT || e.which == KEY_RIGHT) {
RE.enabledEditingItems(e);
}
});
RE.editor.addEventListener("click", RE.enabledEditingItems);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 KiB

View File

@ -0,0 +1,43 @@
/**
* Copyright (C) 2017 Wasabeef
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@charset "UTF-8";
html {
height: 100%;
}
body {
overflow: scroll;
display: table;
table-layout: fixed;
width: 100%;
min-height:100%;
}
#editor {
display: table-cell;
outline: 0px solid transparent;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
#editor[placeholder]:empty:not(:focus):before {
content: attr(placeholder);
opacity: .5;
}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

2
app/src/main/assets/zepto.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,242 +0,0 @@
package com.gh.base;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.Application;
import android.content.Context;
import android.os.Process;
import android.support.multidex.MultiDex;
import android.support.v4.util.ArrayMap;
import android.text.TextUtils;
import android.util.Log;
import com.bandeng.MyEventBusIndex;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.gh.common.constant.Config;
import com.gh.common.util.DataUtils;
import com.gh.common.util.HttpsUtils;
import com.gh.common.util.StringUtils;
import com.gh.common.util.TokenUtils;
import com.gh.common.util.Utils;
import com.gh.gamecenter.BuildConfig;
import com.leon.channel.helper.ChannelReaderUtil;
import com.umeng.message.IUmengRegisterCallback;
import com.umeng.message.PushAgent;
import com.umeng.message.UTrack;
import com.xiaomi.channel.commonutils.logger.LoggerInterface;
import com.xiaomi.mipush.sdk.Logger;
import com.xiaomi.mipush.sdk.MiPushClient;
import com.xiaomi.mipush.sdk.MiPushCommandMessage;
import org.greenrobot.eventbus.EventBus;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
public static final String KEY_FILE_INFO = "FileInfo";
//快传文件发送单线程
public static Executor FILE_SENDER_EXECUTOR = Executors.newSingleThreadExecutor();
//快传文件发送主要的线程池
public static Executor MAIN_EXECUTOR = Executors.newCachedThreadPool();
private static AppController mInstance;
private static ArrayMap<String, Object> objectMap = new ArrayMap<>();
private String mChannel;
public static void put(String key, Object object) {
if (objectMap == null) {
objectMap = new ArrayMap<>();
}
objectMap.put(key, object);
}
public static Object get(String key, boolean isRemove) {
if (objectMap == null) {
return null;
}
if (isRemove) {
return objectMap.remove(key);
} else {
return objectMap.get(key);
}
}
public static void remove(String key) {
if (objectMap == null) {
return;
}
objectMap.remove(key);
}
public static String getProcessName(Context cxt, int pid) {
ActivityManager am = (ActivityManager) cxt.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
if (runningApps == null) {
return null;
}
for (RunningAppProcessInfo procInfo : runningApps) {
if (procInfo.pid == pid) {
return procInfo.processName;
}
}
return null;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public String getChannel() {
return mChannel;
}
@Override
public void onCreate() {
super.onCreate();
MultiDex.install(this);
mInstance = this;
//TODO 强烈不建议开发阶段开启这个Handler必须处理错误
if (!BuildConfig.DEBUG) {
AppUncaughtHandler appUncaughtHandler = new AppUncaughtHandler(this);
Thread.setDefaultUncaughtExceptionHandler(appUncaughtHandler);
}
mChannel = ChannelReaderUtil.getChannel(this);
if (TextUtils.isEmpty(mChannel)) {
//默认用Android Studio run时并没有写入channel magic number到apk包里面所以需要fallback
mChannel = "GH_TEST";
}
Log.e("CHANNEL_ID", mChannel);
//初始化Fresco
Fresco.initialize(this);
DataUtils.init(this, BuildConfig.DEBUG, mChannel);
//测试MTA崩溃的坑爹
// if (BuildConfig.DEBUG) {
// StatConfig.setDebugEnable(true);
// StatConfig.setStatSendStrategy(StatReportStrategy.DEVELOPER);
// throw new RuntimeException("test again");
// }
HttpsUtils.initHttpsUrlConnection(this);
// if (BuildConfig.DEBUG) {
// Stetho.initializeWithDefaults(this);
// }
/**
* 注册push服务注册成功后会向{@link GHPushMessageReceiver}发送广播
* 可以从{@link GHPushMessageReceiver#onCommandResult(Context, MiPushCommandMessage)}
* 的{@link MiPushCommandMessage} 对象参数中获取注册信息
*/
if (shouldInit()) {
MiPushClient.registerPush(this, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY);
if (BuildConfig.DEBUG) {
MiPushClient.registerPush(this, Config.DEBUG_MIPUSH_APPID, Config.DEBUG_MIPUSH_APPKEY);
}
}
if (BuildConfig.DEBUG) {
LoggerInterface newLogger = new LoggerInterface() {
@Override
public void setTag(String tag) {
// ignore
}
@Override
public void log(String content) {
Log.d(TAG, content);
}
@Override
public void log(String content, Throwable t) {
Log.d(TAG, content, t);
}
};
Logger.setLogger(this, newLogger);
}
//友盟推送
final PushAgent pushAgent = PushAgent.getInstance(this);
pushAgent.setAppkeyAndSecret(Config.UMENG_APPKEY, Config.UMENG_MESSAGE_SECRET);
if (BuildConfig.DEBUG) {
// 设置debug的key覆盖掉原值非debug build这个if分支会被去掉
pushAgent.setAppkeyAndSecret(Config.DEBUG_UMENG_APPKEY, Config.DEBUG_UMENG_MESSAGE_SECRET);
}
//注册推送服务每次调用register方法都会回调该接口
pushAgent.register(new IUmengRegisterCallback() {
@Override
public void onSuccess(String deviceToken) {
//注册成功会返回device token
Utils.log("deviceToken::" + deviceToken);
//设置别名
pushAgent.addExclusiveAlias(TokenUtils.getDeviceId(getApplicationContext()),
"GHDID", new UTrack.ICallBack() {
@Override
public void onMessage(boolean b, String s) {
Utils.log(StringUtils.buildString("ExclusiveAlias::", String.valueOf(b), "==", s));
}
});
}
@Override
public void onFailure(String s, String s1) {
Utils.log("deviceToken::" + "注册失败");
}
});
// 友盟推送数据处理
pushAgent.setNotificationClickHandler(new GHUmengNotificationClickHandler());
// // 监听屏幕状态广播
// if (shouldInit()) {
// UnlockScreenReceiver unlockScreenReceiver = new UnlockScreenReceiver();
// IntentFilter intentFilter = new IntentFilter();
// intentFilter.addAction(Intent.ACTION_SCREEN_ON);
// intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
// registerReceiver(unlockScreenReceiver, intentFilter);
//
// // 用户App运行数据统计服务
// Intent intent = new Intent(getApplicationContext(), AppStaticService.class);
// startService(intent);
//
// AppRunTimeDao dao = new AppRunTimeDao(getApplicationContext());
// for (AppRunTimeInfo appRunTimeInfo : dao.getAll()) {
// Utils.log(appRunTimeInfo.getPackageName() + "====1111=====" + appRunTimeInfo.getRunTime());
// }
// }
// 启用EventBus3.0加速功能
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
}
private boolean shouldInit() {
ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));
List<RunningAppProcessInfo> processInfos = am.getRunningAppProcesses();
String mainProcessName = getPackageName();
Log.d(TAG, mainProcessName);
int myPid = Process.myPid();
for (RunningAppProcessInfo info : processInfos) {
if (info.pid == myPid && mainProcessName.equals(info.processName)) {
return true;
}
}
return false;
}
}

View File

@ -1,51 +0,0 @@
//package com.gh.base;
//
//
//import android.annotation.TargetApi;
//import android.app.Application;
//import android.content.Context;
//import android.content.Intent;
//import android.os.Build;
//import android.support.multidex.MultiDex;
//
//import com.tencent.tinker.lib.listener.DefaultPatchListener;
//import com.tencent.tinker.lib.listener.PatchListener;
//import com.tencent.tinker.lib.patch.AbstractPatch;
//import com.tencent.tinker.lib.patch.UpgradePatch;
//import com.tencent.tinker.lib.reporter.DefaultLoadReporter;
//import com.tencent.tinker.lib.reporter.DefaultPatchReporter;
//import com.tencent.tinker.lib.reporter.LoadReporter;
//import com.tencent.tinker.lib.reporter.PatchReporter;
//import com.tencent.tinker.lib.tinker.TinkerInstaller;
//import com.tencent.tinker.loader.app.DefaultApplicationLike;
//
//public class AppControllerLike extends DefaultApplicationLike {
//
// public AppControllerLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag,
// long applicationStartElapsedTime, long applicationStartMillisTime,
// Intent tinkerResultIntent) {
// super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime,
// applicationStartMillisTime, tinkerResultIntent);
// }
//
// @Override
// public void onBaseContextAttached(Context base) {
// super.onBaseContextAttached(base);
// MultiDex.install(base);
//
// LoadReporter loadReporter = new DefaultLoadReporter(getApplication());
// PatchReporter patchReporter = new DefaultPatchReporter(getApplication());
// PatchListener patchListener = new DefaultPatchListener(getApplication());
// AbstractPatch upgradePatchProcessor = new UpgradePatch();
//
// TinkerInstaller.install(this, loadReporter, patchReporter, patchListener,
// AppTinkerResultService.class, upgradePatchProcessor);
//// TinkerInstaller.install(this);
// }
//
// @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
// public void registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks callback) {
// getApplication().registerActivityLifecycleCallbacks(callback);
// }
//
//}

View File

@ -1,29 +0,0 @@
//package com.gh.base;
//
//import com.gh.common.util.Utils;
//import com.tencent.tinker.lib.service.DefaultTinkerResultService;
//import com.tencent.tinker.lib.service.PatchResult;
//import com.tencent.tinker.lib.util.TinkerServiceInternals;
//
//import java.io.File;
//
//
//public class AppTinkerResultService extends DefaultTinkerResultService {
//
// @Override
// public void onPatchResult(PatchResult result) {
// if (result == null) {
// return;
// }
// Utils.log(result);
//
// //first, we want to kill the recover process
// TinkerServiceInternals.killTinkerPatchServiceProcess(getApplicationContext());
//
// if (result.isSuccess) {
// Utils.log("Tinkder Success");
// deleteRawPatchFile(new File(result.rawPatchFilePath));
// }
// }
//
//}

View File

@ -6,15 +6,17 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
import com.gh.common.constant.Config;
import com.gh.common.util.AppManager;
import com.gh.common.util.DataCollectionUtils;
import com.gh.common.util.FileUtils;
import com.gh.common.util.DataUtils;
import com.gh.gamecenter.SplashScreenActivity;
import com.tencent.stat.StatService;
import com.lightgame.config.CommonDebug;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.AppManager;
import com.lightgame.utils.Utils;
import java.io.File;
import java.io.FileWriter;
@ -26,84 +28,58 @@ import java.util.Locale;
public class AppUncaughtHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler mDefaultHandler;
private AppController mAppController;
private Context mContext;
public AppUncaughtHandler(AppController appController) {
public AppUncaughtHandler(Context context) {
// 获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
mAppController = appController;
mContext = context;
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
// 如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
} else {
AppController.MAIN_EXECUTOR.execute(new Runnable() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(mAppController.getApplicationContext(),
"\"光环助手\"发生错误", Toast.LENGTH_SHORT).show();
Looper.loop();
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Utils.toast(mContext.getApplicationContext(), "\"光环助手\"发生错误");
Looper.loop();
}
// 防止重复奔溃导致助手一直重启20秒内不做处理
SharedPreferences sp = mAppController.getApplicationContext().getSharedPreferences(
Config.PREFERENCE, Context.MODE_PRIVATE);
long time = sp.getLong("last_restart_time", 0);
if (System.currentTimeMillis() - time > 20 * 1000) {
sp.edit().putLong("last_restart_time", System.currentTimeMillis()).apply();
Intent intent = new Intent(mAppController.getApplicationContext(), SplashScreenActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent restartIntent = PendingIntent.getActivity(
mAppController.getApplicationContext(), 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
// 退出程序并重启
AlarmManager mgr = (AlarmManager) mAppController.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); // 1秒钟后重启应用
}
AppManager.getInstance().finishAllActivity();
}
});
saveLocalLog(mContext, ex);
restart(mContext);
}
/**
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
*
* @param ex
* @return true:如果处理了该异常信息;否则返回false.
*/
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
public static void restart(final Context context) {
// 防止重复奔溃导致助手一直重启20秒内不做处理
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
long curTime = System.currentTimeMillis();
long time = sp.getLong("last_restart_time", 0);
if (curTime - time > 20 * 1000) {
sp.edit().putLong("last_restart_time", curTime).apply();
Intent intent = new Intent(context, SplashScreenActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent restartIntent = PendingIntent.getActivity(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
// 退出程序并重启
AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, curTime + 3000, restartIntent); // 1秒钟后重启应用
}
saveLog(ex);
return true;
//error restart
// System.exit(2);
AppManager.getInstance().finishAllActivity();
}
// 保存log到本地
private void saveLog(Throwable ex) {
public static void saveLocalLog(Context context, Throwable ex) {
String errorMsg = Log.getStackTraceString(ex);
// MTA主动上传错误
// StatService.reportError(mAppController.getApplicationContext(), errorMsg);
StatService.reportException(mAppController, ex);
// 上传错误数据
DataCollectionUtils.uploadError(mAppController, errorMsg);
Config.setExceptionMsg(context, errorMsg);
// 保存到本地
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault());
File file = new File(FileUtils.getLogPath(mAppController.getApplicationContext(),
File file = new File(FileUtils.getLogPath(context.getApplicationContext(),
format.format(new Date()) + "_gh_assist" + ".log"));
FileWriter writer = null;
try {
@ -124,4 +100,25 @@ public class AppUncaughtHandler implements UncaughtExceptionHandler {
}
}
/**
* 下次应用启动再上报
*
* @param context
* @param throwable
*/
public static void reportException(Context context, Throwable throwable) {
CommonDebug.logMethodWithParams(context, "ERRMSG", throwable);
// 上传错误数据
try {
DataCollectionUtils.uploadError(context, Log.getStackTraceString(throwable));
} catch (Exception e) {
}
DataUtils.onError(context, throwable);
}
}

View File

@ -1,186 +1,211 @@
package com.gh.base;
import android.content.Context;
import android.os.Build;
import android.app.Activity;
import android.arch.lifecycle.Lifecycle;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.view.Window;
import com.gh.common.constant.Config;
import com.gh.common.util.AppManager;
import com.gh.common.util.DataUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.FileUtils;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.RunningUtils;
import com.gh.common.util.ShareUtils;
import com.gh.download.DownloadManager;
import com.gh.common.util.StringUtils;
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.listener.OnCallBackListener;
import com.readystatesoftware.systembartint.SystemBarTintManager.SystemBarConfig;
import com.gh.gamecenter.suggest.SuggestType;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.Utils;
import com.tencent.tauth.Tencent;
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.util.ArrayList;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import butterknife.ButterKnife;
import pub.devrel.easypermissions.EasyPermissions;
import static com.gh.common.util.EntranceUtils.KEY_DATA;
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
public abstract class BaseActivity extends BaseAppCompatToolBarActivity implements OnCallBackListener {
public abstract class BaseActivity extends BaseToolBarActivity implements EasyPermissions.PermissionCallbacks {
protected String mEntrance;
private boolean mIsPause;
private boolean mIsExistLogoutDialog;
protected final Handler mBaseHandler = new BaseHandler(this);
protected static class BaseHandler extends Handler {
private final WeakReference<BaseActivity> mActivityWeakReference;
BaseHandler(BaseActivity activity) {
mActivityWeakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
BaseActivity activity = mActivityWeakReference.get();
if (activity != null) activity.handleMessage(msg);
}
}
protected void handleMessage(Message msg) {
}
//接收QQ或者QQ空间分享回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == com.tencent.connect.common.Constants.REQUEST_QQ_SHARE
|| requestCode == com.tencent.connect.common.Constants.REQUEST_QZONE_SHARE) {
Tencent.onActivityResultData(requestCode, resultCode, data, ShareUtils.getInstance(this).QqShareListener);
}
}
// 小米沉浸式黑色字体
public void setStatusBarDarkMode(boolean darkmode, Activity activity) {
Class<? extends Window> clazz = activity.getWindow().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(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
} catch (Exception ignore) {
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init(mContentView);
AppManager.getInstance().addActivity(this);
setStatusBarDarkMode(true, this);
EventBus.getDefault().register(this);
ButterKnife.bind(this);
mEntrance = getIntent().getStringExtra(KEY_ENTRANCE);
if (getIntent().getBundleExtra(KEY_DATA) != null) {
mEntrance = getIntent().getBundleExtra(KEY_DATA).getString(KEY_ENTRANCE);
}
}
@Override
protected void onDestroy() {
EventBus.getDefault().unregister(this);
mBaseHandler.removeCallbacksAndMessages(null);
super.onDestroy();
}
@Override
protected boolean onNavigationIconClicked() {
return false;
}
private void init(View contentView) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
SystemBarConfig config = getTintManager().getConfig();
contentView.setPadding(0, config.getPixelInsetTop(false), 0, config.getPixelInsetBottom());
}
setContentView(contentView);
ButterKnife.bind(this);
View reuse_actionbar = findViewById(R.id.reuse_actionbar);
if (reuse_actionbar != null) {
int actionbar_height = getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE)
.getInt("actionbar_height", DisplayUtils.dip2px(getApplicationContext(), 55));
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, actionbar_height);
reuse_actionbar.setLayoutParams(lparams);
findViewById(R.id.actionbar_rl_back).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}
protected void init(String title) {
TextView actionbar_tv_title = (TextView) findViewById(R.id.actionbar_tv_title);
actionbar_tv_title.setText(title);
// setNavigationTitle(title);
onBackPressed();
return true;
}
public void toast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
Utils.toast(this, msg);
}
public void toast(int msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
toast(getString(msg));
}
//如果是游戏分享newsTitle默认为空
public void showShare(String url, String gameName, String icon, String newsTitle, ArrayList<String> tag, boolean isToolsBox) {
public void showShare(String url, String icon, String shareTitle, String shareSummary, ShareUtils.ShareType shareType) {
//判断是否是官方版
boolean isPlugin = false;
if (tag != null) {
for (String s : tag) {
if (!"官方版".equals(s)) {
isPlugin = true;
}
}
}
ShareUtils.getInstance(this).showShareWindows(this, getWindow().getDecorView(), url, icon, shareTitle, shareSummary, shareType);
ShareUtils.getInstance(this).showShareWindows(getWindow().getDecorView(), url, gameName, icon, newsTitle, isPlugin, true, isToolsBox);
if (newsTitle == null) {
DataUtils.onEvent(this, "内容分享", gameName);
if (shareType == ShareUtils.ShareType.game || shareType == ShareUtils.ShareType.plugin) {
DataUtils.onEvent(this, "内容分享", shareTitle + shareSummary);
} else {
DataUtils.onEvent(this, "内容分享", newsTitle);
DataUtils.onEvent(this, "内容分享", shareTitle);
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(final EBShowDialog showDialog) {
if (!mIsPause && this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
if ("hijack".equals(showDialog.getType())) {
DialogUtils.showQqSessionDialog(this, null);// 建议用户联系客服
DialogUtils.showQqSessionDialog(this, "2586716223");// 建议用户联系客服
} else if ("plugin".equals(showDialog.getType())) {
DialogUtils.showPluginDialog(this, new DialogUtils.ConfirmListener() {
@Override
public void onConfirm() {
if (FileUtils.isEmptyFile(showDialog.getPath())) {
Toast.makeText(BaseActivity.this, "解析包出错(可能被误删了),请重新下载", Toast.LENGTH_SHORT).show();
toast(R.string.install_failure_hint);
} else {
startActivity(PackageUtils.getUninstallIntent(BaseActivity.this, showDialog.getPath()));
}
}
});
} else if ("loginException".equals(showDialog.getType())) {
if (mIsExistLogoutDialog) return;
mIsExistLogoutDialog = true;
try {
JSONObject object = new JSONObject(showDialog.getPath());
JSONObject device = object.getJSONObject("device");
String manufacturer = device.getString("manufacturer");
String model = device.getString("model");
DialogUtils.showAlertDialog(this, "你的账号已在另外一台设备登录"
, StringUtils.buildString("", manufacturer, " - ", model, "")
, "知道了", "重新登录"
, null
, () -> startActivity(LoginActivity.getIntent(BaseActivity.this))
);
mBaseHandler.postDelayed(() -> mIsExistLogoutDialog = false, 5000);
} catch (JSONException e) {
e.printStackTrace();
}
} else if ("notfound".equals(showDialog.getType())) {
DialogUtils.showAlertDialog(this, "下载失败", "下载链接已失效,建议提交反馈"
, "立即反馈", "取消"
, () -> {
SuggestionActivity.startSuggestionActivity(this, SuggestType.gameQuestion,
null, showDialog.getPath() + ",问题反馈:下载链接失效");
}, null);
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
AppManager.getInstance().finishActivity(this);
}
@Override
protected void onPause() {
super.onPause();
DataUtils.onPause(this);
mIsPause = true;
}
@Override
protected void onResume() {
super.onResume();
DataUtils.onResume(this);
mIsPause = false;
DownloadManager.getInstance(this).initGameMap();
}
@Override
public void loadDone() {
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
}
@Override
public void loadDone(Object obj) {
public void onPermissionsGranted(int requestCode, List<String> perms) {
}
@Override
public void loadError() {
}
@Override
public void loadEmpty() {
}
}

View File

@ -1,325 +0,0 @@
package com.gh.base;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import com.gh.common.util.AppDebugConfig;
import com.gh.common.util.AppManager;
import com.gh.common.util.Util_System_Keyboard;
import com.gh.gamecenter.R;
/**
* @author CsHeng
*/
public abstract class BaseAppCompatActivity extends BaseAppCompatActivityLog implements FragmentNavigationDelegate,
OnBackPressedListener {
protected static final String ARGS_FRAGMENT_NAME = "frgName";
protected static final String ARGS_FRAGMENT_BUNDLE = "frgBundle";
protected View mContentView;
protected static Intent clearTop(Context context, Class<? extends Activity> cls) {
final Intent intent = getReorderToFrontIntent(context, cls);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return intent;
}
protected static Intent getReorderToFrontIntent(Context context, Class<? extends Activity> cls) {
final Intent intent = new Intent(context, cls);
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent;
}
protected static void showActivity(Context context, Class<? extends Activity> cls) {
final Intent intent = getReorderToFrontIntent(context, cls);
context.startActivity(intent);
}
protected static void startFragmentForResult(Context context, Class<? extends Activity> activity,
Class<? extends Fragment> fragment, Bundle bundle, int requestCode) {
if (context instanceof Activity) {
((Activity) context).startActivityForResult(getFragmentIntent(context, activity, fragment, bundle),
requestCode);
}
}
/**
* 根据传进来的fragment class和bundle extra来决定跳转到哪一个fragment
*
* @param context
* @param fragment fragment.getCanonicalName()
* @param bundle fragment的构造参数
* @return
*/
protected static Intent getFragmentIntent(Context context, Class<? extends Activity> activity,
Class<? extends Fragment> fragment, Bundle bundle) {
final Intent intent = getReorderToFrontIntent(context, activity);
intent.putExtra(ARGS_FRAGMENT_NAME, fragment.getCanonicalName());
intent.putExtra(ARGS_FRAGMENT_BUNDLE, bundle);
return intent;
}
protected static void startFragment(Context context, Class<? extends Activity> activity,
Class<? extends Fragment> fragment) {
startFragment(context, activity, fragment, null);
}
/**
* 启动Fragment
*
* @param context
* @param fragment
* @param bundle
*/
protected static void startFragment(Context context, Class<? extends Activity> activity,
Class<? extends Fragment> fragment, Bundle bundle) {
context.startActivity(getFragmentIntent(context, activity, fragment, bundle));
}
private void handleRedirectFromUri(Uri uri) {
try {
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodWithParams(this, uri, uri.getHost(), uri.getPath(), uri.getEncodedQuery());
}
// switch (uri.getPath()) {
// case SchemeConstants.PATH_OPEN_GAME: {
// /**
// * 对于联运游戏传入的game_id为0game_url为对应的游戏链接aid传联运游戏的aid
// * 对于非联运游戏传入非联运游戏的game_idgame_url不传aid传0
// */
// GameModel game = new GameModel();
// int gameId = Integer.parseInt(uri.getQueryParameter(SchemeConstants.PARAMS_GAMEID));
// game.setId(gameId);
//// if (AppDebugConfig.IS_DEBUG) {
//// int debugId = 1049;
//// game.setId(debugId);
//// }
// if (gameId == 0) {
// // cooperate
// int aid = Integer.parseInt(uri.getQueryParameter(SchemeConstants.PARAMS_AID));
// game.setAid(aid);
// String gameUrl = uri.getQueryParameter(SchemeConstants.PARAMS_GAMEURL);
// game.setUrl(gameUrl);
// }
// ApiRequester.requestGameDetail(this, game);
//
// break;
// }
// case SchemeConstants.PATH_OPEN_ARTICLE: {
//
// String url = uri.getQueryParameter(SchemeConstants.PARAMS_ARTICLE_URL);
// String title = uri.getQueryParameter(SchemeConstants.PARAMS_ARTICLE_TITLE);
//
// if (!TextUtils.isEmpty(url) && !TextUtils.isEmpty(title)) {
// Bundle args = new Bundle();
// args.putString(Fragment_Browser_Web.ARGS_URL, url);
// args.putString(Fragment_Browser_Web.ARGS_TITLE, getString(R.string.title_article_detail));
// CommonActivity.startFragment(this, Fragment_Browser_Web.class, args);
// }
//
// break;
// }
// default:
// break;
// }
} catch (Exception e) {
if (AppDebugConfig.IS_DEBUG) {
// Debug_SDK.e(e);
}
}
}
@Override
public boolean onHandleBackPressed() {
onBackPressed();
return true;
}
protected boolean handleBackPressed() {
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodWithParams(this);
}
final Fragment curFragment = getTopFragment();
if (curFragment instanceof OnBackPressedListener &&
((OnBackPressedListener) curFragment).onHandleBackPressed()) {
return true;
}
if (popFragment()) {
return true;
}
return false;
}
public Fragment getTopFragment() {
return getSupportFragmentManager().findFragmentById(R.id.layout_activity_content);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final int layoutId = getLayoutId();
if (layoutId != 0) {
mContentView = getLayoutInflater().inflate(layoutId, null);
setContentView(mContentView);
}
if (savedInstanceState == null) {
handleRedirectIntent(getIntent());
}
AppManager.getInstance().addActivity(this);
}
protected abstract int getLayoutId();
/**
* 1、判断当前是否存在某Fragment例如下载管理器已经在栈中则不重新启动而将其带到最上层 (FindFragmentWithTag)
* 2、支持URI调用
* 是否需要重新导向到其他Activity
*/
protected void handleRedirectIntent(Intent intent) {
try {
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodWithParams(this, intent.toUri(Intent.URI_INTENT_SCHEME));
}
// 1、根据从网页抓取到的Intent跳转进来处理custom uri
// final Uri uri = intent.getData();
// if (uri != null && SchemeConstants.SCHEME_FFSS.equals(uri.getScheme())) {
// handleRedirectFromUri(uri);
// return;
// }
//
// // 2、根据序列化的数据来重新构建Fragment实例若没有则是旧的形式来决定传参
// final String fragmentName = intent.getStringExtra(ARGS_FRAGMENT_NAME);
// if (AppDebugConfig.IS_DEBUG) {
// AppDebugConfig.logMethodWithParams(this, fragmentName);
// }
// if (!TextUtils.isEmpty(fragmentName)) {
// final Bundle args = intent.getBundleExtra(ARGS_FRAGMENT_BUNDLE);
// final Fragment fragment = Fragment.instantiate(this, fragmentName, args);
// if (fragment instanceof DialogFragment) {
// ((DialogFragment) fragment).show(getSupportFragmentManager(), fragmentName);
// } else {
// getSupportFragmentManager().beginTransaction().replace(R.id.layout_activity_content, fragment)
// .commitAllowingStateLoss();
// }
// }
} catch (Throwable e) {
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodWithParams(this, e);
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
AppManager.getInstance().finishActivity(this);
}
@Override
public void addFragment(Fragment fragment) {
getSupportFragmentManager().beginTransaction().add(R.id.layout_activity_content, fragment)
.addToBackStack(fragment.toString()).commitAllowingStateLoss();
Util_System_Keyboard.hideSoftKeyboard(this);
}
@Override
public void replaceFragment(Fragment toReplace) {
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.layout_activity_content, toReplace).addToBackStack(toReplace.toString());
ft.commitAllowingStateLoss();
Util_System_Keyboard.hideSoftKeyboard(this);
}
@Override
public void removeFragment(Fragment toRemove) {
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.layout_activity_content, toRemove).addToBackStack(toRemove.toString());
ft.commitAllowingStateLoss();
Util_System_Keyboard.hideSoftKeyboard(this);
}
@Override
public void showFragment(Fragment toShow) {
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.show(toShow).addToBackStack(toShow.toString());
ft.commitAllowingStateLoss();
Util_System_Keyboard.hideSoftKeyboard(this);
}
@Override
public void hideFragment(Fragment toHide) {
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.show(toHide).addToBackStack(toHide.toString());
ft.commitAllowingStateLoss();
Util_System_Keyboard.hideSoftKeyboard(this);
}
@Override
public boolean popFragment() {
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodWithParams(this, getSupportFragmentManager().getBackStackEntryCount());
}
final int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
if (backStackCount > 0) {
Util_System_Keyboard.hideSoftKeyboard(this);
getSupportFragmentManager().popBackStack();
return true;
}
return false;
}
@Override
public void popFragmentToBase() {
getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
/**
* forward ActivityResultListener to fragments this activity hosts
*
* @param requestCode
* @param resultCode
* @param data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodWithParams(this, requestCode, resultCode, data);
}
final Fragment fragment = getTopFragment();
if (fragment != null) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void onBackPressed() {
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodWithParams(this);
}
if (handleBackPressed()) {
return;
}
// default finish activity
Util_System_Keyboard.hideSoftKeyboard(this);
finish();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
handleRedirectIntent(intent);
}
}

View File

@ -1,94 +0,0 @@
package com.gh.base;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.gh.common.util.AppDebugConfig;
/**
* @author: CsHeng (csheng1204[at]gmail[dot]com)
* Date: 13-7-25
* Time: 下午8:42
*/
public class BaseAppCompatActivityLog extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodName(this);
}
}
@Override
protected void onStop() {
super.onStop();
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodName(this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodName(this);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodName(this);
}
}
@Override
public void onLowMemory() {
super.onLowMemory();
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodName(this);
}
}
@Override
protected void onPause() {
super.onPause();
try {
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodName(this);
}
} catch (Throwable e) {
}
}
@Override
protected void onResume() {
super.onResume();
try {
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodName(this);
}
} catch (Throwable e) {
}
}
@Override
protected void onStart() {
super.onStart();
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodName(this);
}
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (AppDebugConfig.IS_DEBUG) {
AppDebugConfig.logMethodName(this);
}
}
}

View File

@ -1,138 +0,0 @@
package com.gh.base;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
import com.gh.gamecenter.R;
import com.readystatesoftware.systembartint.SystemBarTintManager;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Created by csheng on 15-10-12.
*/
public abstract class BaseAppCompatToolBarActivity extends BaseAppCompatActivity implements ToolbarController {
private Toolbar mToolbar;
private SystemBarTintManager mTintManager;
// TODO 获取沉浸栏管理,要进行版本判断或者判断是否为空
protected SystemBarTintManager getTintManager() {
return mTintManager;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initToolbar();
// Util_Window.initStatusBarColor(getWindow(), ContextCompat.getColor(this, R.color.theme));
initStatusBar();
}
private void initToolbar() {
mToolbar = (Toolbar) findViewById(R.id.toolbar_navigation);
if (mToolbar != null) {
mToolbar.setTitle("");
setSupportActionBar(mToolbar);
}
}
private void initStatusBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
setTranslucentStatus(true);
mTintManager = new SystemBarTintManager(this);
mTintManager.setStatusBarTintEnabled(true);
// mTintManager.setNavigationBarTintEnabled(true);
if (Build.MANUFACTURER.equals("Meizu") || Build.MANUFACTURER.equals("Xiaomi")) {
mTintManager.setStatusBarTintColor(Color.WHITE);
} else {
mTintManager.setStatusBarTintColor(Color.BLACK);
}
switch (Build.MANUFACTURER) {
case "Meizu":
try {
Window window = getWindow();
if (window != null) {
WindowManager.LayoutParams lp = window.getAttributes();
Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
darkFlag.setAccessible(true);
meizuFlags.setAccessible(true);
int bit = darkFlag.getInt(null);
int value = meizuFlags.getInt(lp);
value |= bit;
meizuFlags.setInt(lp, value);
window.setAttributes(lp);
}
} catch (Exception e) {
e.printStackTrace();
}
break;
case "Xiaomi":
try {
Window window = getWindow();
if (window != null) {
Class<?> clazz = window.getClass();
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
int darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
extraFlagField.invoke(window, darkModeFlag, darkModeFlag);
}
} catch (Exception e) {
e.printStackTrace();
}
break;
default:
break;
}
}
}
protected void setTranslucentStatus(boolean status) {
Window window = getWindow();
WindowManager.LayoutParams winParams = window.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
if (status) {
winParams.flags |= bits;
} else {
winParams.flags &= ~bits;
}
window.setAttributes(winParams);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
return onNavigationIconClicked();
}
return super.onOptionsItemSelected(item);
}
protected abstract boolean onNavigationIconClicked();
@Override
public void setNavigationTitle(int res) {
mToolbar.setTitle(res);
}
@Override
public void setNavigationTitle(CharSequence res) {
mToolbar.setTitle(res);
}
@Override
public Toolbar getToolBar() {
return mToolbar;
}
}

View File

@ -1,394 +0,0 @@
package com.gh.base;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.gh.common.constant.Config;
import com.gh.common.util.ApkActiveUtils;
import com.gh.common.util.DataUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.FileUtils;
import com.gh.common.util.GameUtils;
import com.gh.common.util.NetworkUtils;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.ShareUtils;
import com.gh.common.view.DownloadDialog;
import com.gh.download.DataWatcher;
import com.gh.download.DownloadEntity;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.eventbus.EBDownloadStatus;
import com.gh.gamecenter.eventbus.EBPackage;
import com.gh.gamecenter.manager.PackageManager;
import com.tencent.tauth.Tencent;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
/**
* Created by Administrator on 2016/9/19.
* 游戏详情、新闻详情基类(控制底部下载栏)
*/
public abstract class BaseDetailActivity extends BaseActivity implements View.OnClickListener {
protected TextView actionbar_tv_title;
protected RecyclerView detail_rv_show;
protected LinearLayout detail_ll_bottom;
protected TextView detail_tv_download;
protected ProgressBar detail_pb_progressbar;
protected TextView detail_tv_per;
protected LinearLayout reuse_ll_loading;
protected LinearLayout reuse_no_connection;
protected LinearLayout reuse_none_data;
protected TextView reuse_tv_none_data;
protected ImageView iv_share;
protected GameEntity gameEntity;
protected DownloadEntity mDownloadEntity;
protected String name;
protected String title;
protected String downloadAddWord;
protected String downloadOffText;
private DataWatcher dataWatcher = new DataWatcher() {
@Override
public void onDataChanged(DownloadEntity downloadEntity) {
if (gameEntity != null && gameEntity.getApk().size() == 1) {
String url = gameEntity.getApk().get(0).getUrl();
if (url.equals(downloadEntity.getUrl())) {
if (!"pause".equals(DownloadManager.getInstance(BaseDetailActivity.this).
getStatus(downloadEntity.getUrl()))) {
mDownloadEntity = downloadEntity;
invalidate();
}
}
}
}
};
@Override
protected int getLayoutId() {
return R.layout.activity_detail;
}
//接收QQ或者QQ空间分享回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == com.tencent.connect.common.Constants.REQUEST_QQ_SHARE
|| requestCode == com.tencent.connect.common.Constants.REQUEST_QZONE_SHARE) {
Tencent.onActivityResultData(requestCode, resultCode, data, ShareUtils.getInstance(this).QqShareListener);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// View contentView = View.inflate(this, R.layout.activity_detail, null);
// 添加分享图标
iv_share = new ImageView(this);
iv_share.setImageResource(R.drawable.ic_share);
iv_share.setOnClickListener(this);
iv_share.setVisibility(View.GONE);
iv_share.setPadding(DisplayUtils.dip2px(this, 13), DisplayUtils.dip2px(this, 11)
, DisplayUtils.dip2px(this, 11), DisplayUtils.dip2px(this, 13));
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
DisplayUtils.dip2px(this, 48), DisplayUtils.dip2px(this, 48));
params.addRule(RelativeLayout.CENTER_VERTICAL);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
RelativeLayout reuse_actionbar = (RelativeLayout) mContentView.findViewById(
R.id.reuse_actionbar);
reuse_actionbar.addView(iv_share, params);
// init(contentView);
actionbar_tv_title = (TextView) findViewById(R.id.actionbar_tv_title);
detail_rv_show = (RecyclerView) findViewById(R.id.detail_rv_show);
detail_ll_bottom = (LinearLayout) findViewById(R.id.detail_ll_bottom);
detail_tv_download = (TextView) findViewById(R.id.detail_tv_download);
detail_pb_progressbar = (ProgressBar) findViewById(R.id.detail_pb_progressbar);
detail_tv_per = (TextView) findViewById(R.id.detail_tv_per);
reuse_ll_loading = (LinearLayout) findViewById(R.id.reuse_ll_loading);
reuse_no_connection = (LinearLayout) findViewById(R.id.reuse_no_connection);
reuse_none_data = (LinearLayout) findViewById(R.id.reuse_none_data);
reuse_tv_none_data = (TextView) findViewById(R.id.reuse_tv_none_data);
detail_ll_bottom.setOnClickListener(this);
detail_tv_download.setOnClickListener(this);
detail_pb_progressbar.setOnClickListener(this);
detail_tv_per.setOnClickListener(this);
reuse_no_connection.setOnClickListener(this);
}
@Override
protected void onPause() {
super.onPause();
DownloadManager.getInstance(this).removeObserver(dataWatcher);
}
@Override
protected void onResume() {
super.onResume();
if (gameEntity != null
&& gameEntity.getApk() != null
&& gameEntity.getApk().size() == 1) {
initDownload(true);
}
DownloadManager.getInstance(this).addObserver(dataWatcher);
}
protected void initDownload(boolean isCheck) {
if (Config.isShow(this)) {
detail_ll_bottom.setVisibility(View.VISIBLE);
detail_rv_show.setPadding(0, 0, 0,
DisplayUtils.dip2px(getApplicationContext(), 60));
} else {
detail_ll_bottom.setVisibility(View.GONE);
detail_rv_show.setPadding(0, 0, 0, 0);
}
if (gameEntity != null && "光环助手".equals(gameEntity.getName())) {
detail_ll_bottom.setVisibility(View.GONE);
detail_rv_show.setPadding(0, 0, 0, 0);
} else if (gameEntity == null || gameEntity.getApk().isEmpty()) {
detail_tv_download.setVisibility(View.VISIBLE);
detail_pb_progressbar.setVisibility(View.GONE);
detail_tv_per.setVisibility(View.GONE);
if (TextUtils.isEmpty(downloadOffText)) {
detail_tv_download.setText("暂无下载");
} else {
detail_tv_download.setText(downloadOffText);
}
detail_tv_download.setBackgroundResource(R.drawable.game_item_btn_pause_style);
detail_tv_download.setTextColor(0xFF999999);
detail_tv_download.setClickable(false);
} else {
detail_tv_download.setVisibility(View.VISIBLE);
detail_pb_progressbar.setVisibility(View.GONE);
detail_tv_per.setVisibility(View.GONE);
boolean isInstalled = false;
if (gameEntity.getApk() != null && gameEntity.getApk().size() == 1
&& PackageManager.isInstalled(gameEntity.getApk().get(0).getPackageName())) {
isInstalled = true;
}
if (isInstalled) {
if (PackageManager.isCanUpdate(gameEntity.getId(), gameEntity.getApk().get(0).getPackageName())) {
if (TextUtils.isEmpty(downloadAddWord)) {
detail_tv_download.setBackgroundResource(
R.drawable.game_item_btn_download_style);
detail_tv_download.setText(String.format("更新《%s》",
gameEntity.getName()));
} else {
detail_tv_download.setBackgroundResource(
R.drawable.game_item_btn_download_style);
detail_tv_download.setText(String.format("更新《%s》%s",
gameEntity.getName(), downloadAddWord));
}
} else {
if (gameEntity.getTag() != null && gameEntity.getTag().size() != 0
&& !TextUtils.isEmpty(gameEntity.getApk().get(0).getGhVersion())
&& !PackageUtils.isSignature(this, gameEntity.getApk().get(0).getPackageName())) {
if (TextUtils.isEmpty(downloadAddWord)) {
detail_tv_download.setBackgroundResource(
R.drawable.game_item_btn_plugin_style);
detail_tv_download.setText(String.format("插件化《%s》",
gameEntity.getName()));
} else {
detail_tv_download.setBackgroundResource(
R.drawable.game_item_btn_plugin_style);
detail_tv_download.setText(String.format("插件化《%s》%s",
gameEntity.getName(), downloadAddWord));
}
} else {
if (TextUtils.isEmpty(downloadAddWord)) {
detail_tv_download.setBackgroundResource(
R.drawable.game_item_btn_launch_style);
detail_tv_download.setText(String.format("启动《%s》",
gameEntity.getName()));
} else {
detail_tv_download.setBackgroundResource(
R.drawable.game_item_btn_launch_style);
detail_tv_download.setText(String.format("启动《%s》%s",
gameEntity.getName(), downloadAddWord));
}
}
}
} else {
String status = GameUtils.getDownloadBtnText(this, gameEntity);
if ("插件化".equals(status)) {
detail_tv_download.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
} else if ("打开".equals(status)) {
detail_tv_download.setBackgroundResource(R.drawable.game_item_btn_launch_style);
} else {
detail_tv_download.setBackgroundResource(R.drawable.game_item_btn_download_style);
}
if (TextUtils.isEmpty(downloadAddWord)) {
detail_tv_download.setText(String.format(status + "《%s》",
gameEntity.getName()));
} else {
detail_tv_download.setText(String.format(status + "《%s》%s",
gameEntity.getName(), downloadAddWord));
}
}
}
if (isCheck && gameEntity != null
&& gameEntity.getApk() != null
&& gameEntity.getApk().size() == 1) {
String url = gameEntity.getApk().get(0).getUrl();
DownloadEntity downloadEntity = DownloadManager.getInstance(getApplicationContext()).get(url);
if (downloadEntity != null) {
mDownloadEntity = downloadEntity;
detail_tv_download.setVisibility(View.GONE);
detail_pb_progressbar.setVisibility(View.VISIBLE);
detail_tv_per.setVisibility(View.VISIBLE);
invalidate();
}
}
}
private void invalidate() {
detail_pb_progressbar.setProgress((int) (mDownloadEntity.getPercent() * 10));
detail_tv_per.setTextColor(0xFFFFFFFF);
switch (mDownloadEntity.getStatus()) {
case downloading:
case pause:
case timeout:
case neterror:
case waiting:
detail_tv_per.setText("下载中");
break;
case done:
detail_tv_per.setText("安装");
if (mDownloadEntity.isPluggable()
&& PackageManager.isInstalled(mDownloadEntity.getPackageName())) {
detail_pb_progressbar.setProgressDrawable(getResources().getDrawable(R.drawable.progressbar_plugin_radius_style));
} else {
detail_pb_progressbar.setProgressDrawable(getResources().getDrawable(R.drawable.progressbar_normal_radius_style));
}
break;
case cancel:
case hijack:
case notfound:
initDownload(false);
break;
default:
break;
}
}
// 接收下载被删除消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(EBDownloadStatus status) {
if ("delete".equals(status.getStatus())
&& gameEntity != null
&& gameEntity.getApk() != null
&& gameEntity.getApk().size() == 1) {
String url = gameEntity.getApk().get(0).getUrl();
if (url.equals(status.getUrl())) {
initDownload(false);
}
}
}
// 接受安装、卸载消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBPackage busFour) {
if (gameEntity != null
&& gameEntity.getApk() != null
&& gameEntity.getApk().size() > 0) {
for (ApkEntity apkEntity : gameEntity.getApk()) {
String packageName = apkEntity.getPackageName();
if (packageName.equals(busFour.getPackageName())) {
ApkActiveUtils.filterHideApk(gameEntity);
initDownload(false);
}
}
}
}
@Override
public void onClick(View v) {
if (v == detail_tv_download) {
if (gameEntity != null && !gameEntity.getApk().isEmpty()) {
if (gameEntity.getApk().size() == 1) {
if (NetworkUtils.isWifiConnected(this)) {
download();
} else {
DialogUtils.showDownloadDialog(this, new DialogUtils.ConfirmListener() {
@Override
public void onConfirm() {
download();
}
});
}
} else {
DownloadDialog.getInstance(this).showPopupWindow(v, gameEntity, mEntrance, name + ":" + title);
}
} else {
toast("稍等片刻~!游戏正在上传中...");
}
} else if (v == detail_pb_progressbar || v == detail_tv_per) {
String str = detail_tv_per.getText().toString();
if ("下载中".equals(str)) {
DownloadManagerActivity.startDownloadManagerActivity(this, gameEntity.getApk().get(0).getUrl()
, mEntrance + "+(" + name + "[" + title + "])");
} else if ("安装".equals(str)) {
PackageUtils.launchSetup(this, mDownloadEntity.getPath());
}
}
}
private void download() {
String str = detail_tv_download.getText().toString();
if (str.contains("启动")) {
DataUtils.onGameLaunchEvent(this, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), name);
PackageUtils.launchApplicationByPackageName(this, gameEntity.getApk().get(0).getPackageName());
} else {
String method;
if (str.contains("更新")) {
method = "更新";
} else if (str.contains("插件化")) {
method = "插件化";
} else {
method = "下载";
}
ApkEntity apkEntity = gameEntity.getApk().get(0);
String msg = FileUtils.isCanDownload(this, apkEntity.getSize());
if (TextUtils.isEmpty(msg)) {
DataUtils.onGameDownloadEvent(this, gameEntity.getName(), apkEntity.getPlatform(), mEntrance, "下载开始");
DownloadManager.createDownload(this, apkEntity, gameEntity, method, mEntrance, name + ":" + title);
detail_tv_download.setVisibility(View.GONE);
detail_pb_progressbar.setVisibility(View.VISIBLE);
detail_tv_per.setVisibility(View.VISIBLE);
detail_pb_progressbar.setProgress(0);
detail_tv_per.setText("0.0%");
DownloadManager.getInstance(BaseDetailActivity.this).putStatus(apkEntity.getUrl(), "downloading");
} else {
toast(msg);
}
}
}
}

View File

@ -1,100 +0,0 @@
package com.gh.base;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.gh.common.util.EntranceUtils;
import com.gh.gamecenter.listener.OnCallBackListener;
import org.greenrobot.eventbus.EventBus;
import butterknife.ButterKnife;
/**
* Created by LGT on 2016/9/4.
* Fragment 基类
*/
public class BaseFragment extends Fragment implements OnCallBackListener {
protected View view;
protected boolean isEverpause;
protected String mEntrance;
protected void init(int layout) {
view = View.inflate(getActivity(), layout, null);
ButterKnife.bind(this, view);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mEntrance = getActivity().getIntent().getStringExtra(EntranceUtils.KEY_ENTRANCE);
isEverpause = false;
EventBus.getDefault().register(this);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
if (container != null) {
container.removeView(view);
}
return view;
}
@Override
public void onResume() {
super.onResume();
isEverpause = false;
}
@Override
public void onPause() {
super.onPause();
isEverpause = true;
}
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
public void toast(String msg) {
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
}
public boolean isEverpause() {
return isEverpause;
}
@Override
public void loadDone() {
}
@Override
public void loadDone(Object obj) {
}
@Override
public void loadError() {
}
@Override
public void loadEmpty() {
}
}

View File

@ -1,206 +0,0 @@
//package com.gh.base;
//
//import android.annotation.TargetApi;
//import android.content.Context;
//import android.graphics.Color;
//import android.os.Build;
//import android.os.Bundle;
//import android.support.v4.app.FragmentActivity;
//import android.view.*;
//import android.view.View.OnClickListener;
//import android.view.ViewGroup.LayoutParams;
//import android.widget.*;
//import butterknife.ButterKnife;
//import com.gh.common.constant.Config;
//import com.gh.common.util.*;
//import com.gh.download.DownloadManager;
//import com.gh.gamecenter.R;
//import com.gh.gamecenter.eventbus.EBShowDialog;
//import com.readystatesoftware.systembartint.SystemBarTintManager;
//import com.readystatesoftware.systembartint.SystemBarTintManager.SystemBarConfig;
//import de.greenrobot.event.EventBus;
//
//import java.lang.reflect.Field;
//import java.lang.reflect.Method;
//import java.util.ArrayList;
//
//public class BaseFragmentActivity extends FragmentActivity {
//
// protected String mEntrance;
//
// private boolean isPause;
//
// @Override
// protected void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
// AppManager.getInstance().addActivity(this);
// EventBus.getDefault().register(this);
// mEntrance = getIntent().getStringExtra("mEntrance");
// if (getIntent().getBundleExtra("data") != null) {
// mEntrance = getIntent().getBundleExtra("data").getString("mEntrance");
// }
// }
//
// public void init(View contentView, String title) {
// init(contentView);
// TextView actionbar_tv_title = (TextView) findViewById(R.id.actionbar_tv_title);
// actionbar_tv_title.setText(title);
// }
//
// public void init(View contentView) {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// setTheme(R.style.AppTheme);
// setTranslucentStatus(true);
// SystemBarTintManager tintManager = new SystemBarTintManager(this);
// tintManager.setStatusBarTintEnabled(true);
// if (Build.MANUFACTURER.equals("Meizu") || Build.MANUFACTURER.equals("Xiaomi")) {
// tintManager.setStatusBarTintColor(Color.WHITE);
// } else {
// tintManager.setStatusBarTintColor(Color.BLACK);
// }
// SystemBarConfig config = tintManager.getConfig();
// contentView.setPadding(0, config.getPixelInsetTop(false), 0,
// config.getPixelInsetBottom());
//
// if (Build.MANUFACTURER.equals("Meizu")) {
// try {
// Window window = getWindow();
// if (window != null) {
// WindowManager.LayoutParams lp = window.getAttributes();
// Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
// Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
// darkFlag.setAccessible(true);
// meizuFlags.setAccessible(true);
// int bit = darkFlag.getInt(null);
// int value = meizuFlags.getInt(lp);
// value |= bit;
// meizuFlags.setInt(lp, value);
// window.setAttributes(lp);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// } else if (Build.MANUFACTURER.equals("Xiaomi")) {
// try {
// Window window = getWindow();
// if (window != null) {
// Class<?> clazz = window.getClass();
// Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
// Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
// int darkModeFlag = field.getInt(layoutParams);
// Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
// extraFlagField.invoke(window, darkModeFlag, darkModeFlag);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
// }
//
// setContentView(contentView);
//
// ButterKnife.bind(this);
//
// int actionbar_height = getSharedPreferences(Config.PREFERENCE,
// Context.MODE_PRIVATE).getInt("actionbar_height",
// DisplayUtils.dip2px(getApplicationContext(), 48));
//
// RelativeLayout reuse_actionbar = (RelativeLayout) findViewById(R.id.reuse_actionbar);
// LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
// LayoutParams.MATCH_PARENT, actionbar_height);
// reuse_actionbar.setLayoutParams(params);
//
// findViewById(R.id.actionbar_rl_back).setOnClickListener(
// new OnClickListener() {
// @Override
// public void onClick(View v) {
// finish();
// }
// });
// }
//
// public void toast(String msg) {
// Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
// }
//
// public void toast(int msg) {
// Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
// }
//
// @TargetApi(19)
// protected void setTranslucentStatus(boolean status) {
// Window window = getWindow();
// WindowManager.LayoutParams winParams = window.getAttributes();
// final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
// if (status) {
// winParams.flags |= bits;
// } else {
// winParams.flags &= ~bits;
// }
// window.setAttributes(winParams);
// }
//
// //如果是游戏分享newsTitle默认为空
// public void showShare(String url, String gameName, String icon, String newsTitle, ArrayList<String> tag) {
//
// //判断是否是官方版
// boolean isPlugin = false;
// if (tag != null) {
// for (String s : tag) {
// if (!"官方版".equals(s)) {
// isPlugin = true;
// }
// }
// }
//
// ShareUtils.getInstance(this).showShareWindows(new View(this), url, gameName, icon, newsTitle, isPlugin, true);
//
// if (newsTitle == null) {
// DataUtils.onEvent(this, "内容分享", gameName);
// } else {
// DataUtils.onEvent(this, "内容分享", newsTitle);
// }
// }
//
// public void onEventMainThread(final EBShowDialog showDialog) {
// if (!isPause && this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
// if ("hijack".equals(showDialog.getType())) {
// DialogUtils.showQqSessionDialog(this, null);// 建议用户联系客服
// } else if ("plugin".equals(showDialog.getType())) {
// DialogUtils.showPluginDialog(this, new DialogUtils.ConfirmListener() {
// @Override
// public void onConfirm() {
// if (FileUtils.isEmptyFile(showDialog.getPath())) {
// Toast.makeText(BaseFragmentActivity.this, "解析包出错(可能被误删了),请重新下载", Toast.LENGTH_SHORT).show();
// } else {
// startActivity(PackageUtils.getUninstallIntent(BaseFragmentActivity.this, showDialog.getPath()));
// }
// }
// });
// }
// }
// }
//
// @Override
// protected void onDestroy() {
// super.onDestroy();
// EventBus.getDefault().unregister(this);
// AppManager.getInstance().finishActivity(this);
// }
//
// @Override
// protected void onPause() {
// super.onPause();
// DataUtils.onPause(this);
// isPause = true;
// }
//
// @Override
// protected void onResume() {
// super.onResume();
// DataUtils.onResume(this);
// isPause = false;
// DownloadManager.getInstance(this).initGameMap();
// }
//
//}

View File

@ -0,0 +1,57 @@
package com.gh.base;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import butterknife.ButterKnife;
/**
* 目前仅提供butterknife bind方法
*
* @author CsHeng
* @Date 16/06/2017
* @Time 9:55 AM
*/
public abstract class BaseRecyclerViewHolder<T> extends RecyclerView.ViewHolder implements View.OnClickListener {
private T mData;
private OnListClickListener mListClickListener;
public BaseRecyclerViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
/**
* 具体的设置监听在childViewHolder 设置
*
* @param itemView
* @param data 一般情况下只传列表数据
* @param listClickListener 列表事件接口
*/
public BaseRecyclerViewHolder(View itemView, T data, OnListClickListener listClickListener) {
this(itemView);
this.mData = data;
this.mListClickListener = listClickListener;
}
public BaseRecyclerViewHolder(View itemView, OnListClickListener listClickListener) {
this(itemView);
this.mListClickListener = listClickListener;
}
public void setClickData(T clickData) {
this.mData = clickData;
}
@Override
public void onClick(View view) {
try {
mListClickListener.onListClick(view, getAdapterPosition(), mData);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,124 @@
package com.gh.base;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.gh.common.util.DisplayUtils;
import com.gh.gamecenter.R;
import com.gh.gamecenter.normal.ToolbarController;
import com.lightgame.BaseAppCompatActivity;
import com.lightgame.OnTitleClickListener;
import java.util.List;
/**
* Created by csheng on 15-10-12.
*/
public abstract class BaseToolBarActivity extends BaseAppCompatActivity implements ToolbarController, Toolbar.OnMenuItemClickListener {
private Toolbar mToolbar;
private TextView mTitleTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initToolbar();
}
private void initToolbar() {
mToolbar = findViewById(R.id.normal_toolbar);
mTitleTv = findViewById(R.id.normal_title);
if (mToolbar != null) {
// setSupportActionBar(mToolbar); // 替换actionBar后 toolBar无法控制
mToolbar.setNavigationIcon(provideNavigationIcon());
mToolbar.setNavigationOnClickListener(view -> onBackPressed());
mTitleTv.setOnClickListener(view -> {
final List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
for (Fragment fragment : fragmentList) {
if (fragment instanceof OnTitleClickListener) {
((OnTitleClickListener) fragment).onTitleClick();
}
}
});
}
}
@DrawableRes
public int provideNavigationIcon() {
return R.drawable.ic_bar_back; // default navigation icon
}
@Override
public void setNavigationTitle(String title) {
if (mTitleTv != null) mTitleTv.setText(title);
}
@Override
public void setNavigationTitle(@StringRes int res) {
setNavigationTitle(getString(res));
}
@Override
public void setToolbarMenu(int res) {
if (mToolbar == null) return;
mToolbar.inflateMenu(res);
mToolbar.setOnMenuItemClickListener(this);
Menu menu = mToolbar.getMenu();
for (int i = 0; i < menu.size(); i++) {
MenuItem menuItem = menu.getItem(i);
// menu设置actionLayout后无法捕捉点击事件以icon为tag如果icon is null 手动设置menuItem点击事件
if (menuItem != null && menuItem.getIcon() == null) {
if (menuItem.getActionView() != null) {
menuItem.getActionView().setOnClickListener((v) -> this.onMenuItemClick(menuItem));
}
}
}
// 限制标题实际宽度 防止标题挡住toolbar menu按钮
if (menu.size() > 2 && mTitleTv != null) {
ViewGroup.LayoutParams layoutParams = mTitleTv.getLayoutParams();
if (layoutParams instanceof RelativeLayout.LayoutParams) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) layoutParams;
params.setMargins(DisplayUtils.dip2px(90), 0, DisplayUtils.dip2px(90), 0);
mTitleTv.setLayoutParams(params);
}
}
}
@Override
public MenuItem getMenuItem(int res) {
if (mToolbar == null) return null; //后续页面做好判断
return mToolbar.getMenu().findItem(res);
}
public Menu getMenu() {
return mToolbar.getMenu();
}
@Override
public boolean onMenuItemClick(MenuItem item) {
return false;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
return onNavigationIconClicked();
}
return super.onOptionsItemSelected(item);
}
protected abstract boolean onNavigationIconClicked();
}

View File

@ -0,0 +1,19 @@
package com.gh.base
import android.app.Activity
object CurrentActivityHolder {
@JvmStatic
val activitySet = HashSet<Activity>()
@JvmStatic
fun getCurrentActivity(): Activity? {
return if (activitySet.isEmpty()) {
null
} else {
activitySet.iterator().next()
}
}
}

View File

@ -1,26 +0,0 @@
package com.gh.base;
import android.support.v4.app.Fragment;
/**
* @author CsHeng
* @Date 15-9-29
* @Time 上午10:24
*/
public interface FragmentNavigationDelegate {
void addFragment(Fragment toAdd);
void replaceFragment(Fragment toReplace);
void removeFragment(Fragment toRemove);
void showFragment(Fragment toShow);
void hideFragment(Fragment toHide);
boolean popFragment();
void popFragmentToBase();
}

View File

@ -4,6 +4,12 @@ import android.app.Activity;
import android.app.Application.ActivityLifecycleCallbacks;
import android.os.Bundle;
import com.gh.common.im.ImManager;
import com.gh.common.notifier.Notifier;
import com.gh.common.util.DataUtils;
import com.gh.download.DownloadManager;
import com.lightgame.utils.AppManager;
/**
* 1、写点针对生命周期的统计代码
* 2、写点通用的逻辑
@ -15,10 +21,10 @@ import android.os.Bundle;
*/
public class GHActivityLifecycleCallbacksImpl implements ActivityLifecycleCallbacks {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
AppManager.getInstance().addActivity(activity);
}
@Override
@ -29,16 +35,27 @@ public class GHActivityLifecycleCallbacksImpl implements ActivityLifecycleCallba
@Override
public void onActivityResumed(Activity activity) {
DataUtils.onResume(activity);
CurrentActivityHolder.getActivitySet().add(activity);
ImManager.updateFloatingWindow();
//FIXME 这里应该只是部分Activity需要
try {
// 初始化gameMap
DownloadManager.getInstance(activity).initGameMap();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onActivityPaused(Activity activity) {
DataUtils.onPause(activity);
CurrentActivityHolder.getActivitySet().remove(activity);
}
@Override
public void onActivityStopped(Activity activity) {
Notifier.hide();
}
@Override
@ -48,7 +65,7 @@ public class GHActivityLifecycleCallbacksImpl implements ActivityLifecycleCallba
@Override
public void onActivityDestroyed(Activity activity) {
AppManager.getInstance().finishActivity(activity);
}
}

View File

@ -1,312 +0,0 @@
package com.gh.base;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v4.util.ArrayMap;
import android.text.TextUtils;
import android.widget.RemoteViews;
import com.gh.common.util.AppDebugConfig;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.FileUtils;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.TokenUtils;
import com.gh.common.util.Utils;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.R;
import com.xiaomi.mipush.sdk.ErrorCode;
import com.xiaomi.mipush.sdk.MiPushClient;
import com.xiaomi.mipush.sdk.MiPushCommandMessage;
import com.xiaomi.mipush.sdk.MiPushMessage;
import com.xiaomi.mipush.sdk.PushMessageReceiver;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import static com.gh.common.util.EntranceUtils.ENTRANCE_MIPUSH;
import static com.gh.common.util.EntranceUtils.HOST_ARTICLE;
import static com.gh.common.util.EntranceUtils.HOST_GAME;
import static com.gh.common.util.EntranceUtils.HOST_WEB;
import static com.gh.common.util.EntranceUtils.HOSt_COLUMN;
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
import static com.gh.common.util.EntranceUtils.KEY_GAMEID;
import static com.gh.common.util.EntranceUtils.KEY_ID;
import static com.gh.common.util.EntranceUtils.KEY_NEWSID;
import static com.gh.common.util.EntranceUtils.KEY_TARGET;
import static com.gh.common.util.EntranceUtils.KEY_TO;
import static com.gh.common.util.EntranceUtils.KEY_TYPE;
import static com.gh.common.util.EntranceUtils.KEY_URL;
/**
* 1、PushMessageReceiver是个抽象类该类继承了BroadcastReceiver。
* 2、需要将自定义的DemoMessageReceiver注册在AndroidManifest.xml文件中 <receiver
* android:exported="true"
* android:name="com.xiaomi.mipushdemo.DemoMessageReceiver"> <intent-filter>
* <action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE" /> </intent-filter>
* <intent-filter> <action android:name="com.xiaomi.mipush.ERROR" />
* </intent-filter> <intent-filter> <action
* android:name="com.xiaomi.mipush.MESSAGE_ARRIVED" /></intent-filter>
* </receiver>
* 3、DemoMessageReceiver的onReceivePassThroughMessage方法用来接收服务器向客户端发送的透传消息
* 4、DemoMessageReceiver的onNotificationMessageClicked方法用来接收服务器向客户端发送的通知消息
* 这个回调方法会在用户手动点击通知后触发
* 5、DemoMessageReceiver的onNotificationMessageArrived方法用来接收服务器向客户端发送的通知消息
* 这个回调方法是在通知消息到达客户端时触发。另外应用在前台时不弹出通知的通知消息到达客户端也会触发这个回调函数
* 6、DemoMessageReceiver的onCommandResult方法用来接收客户端向服务器发送命令后的响应结果
* 7、DemoMessageReceiver的onReceiveRegisterResult方法用来接收客户端向服务器发送注册命令后的响应结果
* 8、以上这些方法运行在非UI线程中
*
* @author mayixiang
* //TODO 请勿更改此类路径,若需更改时请注意更改./libraries/MiPush/proguard-library.txt混淆对应配置
*/
public class GHPushMessageReceiver extends PushMessageReceiver {
private String mAlias;
@Override
public void onReceivePassThroughMessage(Context context, MiPushMessage message) {
if (BuildConfig.DEBUG) {
AppDebugConfig.logMethodWithParams(this, message);
}
// 1判断notifyid是否为4
try {
//TODO what is magic number 4?
if (message.getNotifyId() == 4) {
JSONObject jsonObject = new JSONObject(message.getContent());
Utils.log(jsonObject.toString());
String channel = jsonObject.getString("channel");
Utils.log("channel = " + channel);
// 1判断渠道号是否一致或是否为ALL
String packageChannel = AppController.getInstance().getChannel();
if ("ALL".equals(channel) || channel.equalsIgnoreCase(packageChannel)) {
String type = jsonObject.getString(KEY_TYPE);
Utils.log("type = " + type);
if ("NEWS".equals(type)) {
// 新闻推送
JSONArray jsonArray = jsonObject.getJSONArray("package");
ArrayMap<String, Boolean> map = getInstalledMapFromLocal(context);
for (int i = 0; i < jsonArray.length(); i++) {
Boolean b = map.get(jsonArray.getString(i));
if (b != null) {
// 显示推送的消息
showNotification(context, jsonObject, 0);
break;
}
}
} else if ("PLUGIN_UPDATE".equals(type)) {
// 插件更新推送
JSONArray jsonArray = jsonObject.getJSONArray("apk");
ArrayMap<String, Boolean> map = getInstalledMapFromLocal(context);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject apk = jsonArray.getJSONObject(i);
String packageName = apk.getString("package");
Boolean b = map.get(packageName);
if (b != null) {
// 判断是否gh_version是否相同
String gh_version = (String) PackageUtils
.getMetaData(context, packageName, "gh_version");
if (gh_version != null) {
gh_version = gh_version.substring(2);
// 判断gh_version是否相同
if (gh_version.equals(apk.getString("gh_version"))) {
// 判断version是否相同
String version = PackageUtils.getVersionByPackage(context, packageName);
if (apk.getString("version").equals(version)) {
// 版本相同,无需显示插件更新,继续查看是否有可更新的游戏包
continue;
}
}
}
// 显示推送的消息
showNotification(context, jsonObject, 1);
break;
}
}
} else if ("NEW_GAME".equals(type)) {
// 新游推送
showNotification(context, jsonObject, 2);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
private ArrayMap<String, Boolean> getInstalledMapFromLocal(Context context) {
ArrayMap<String, Boolean> map = new ArrayMap<>();
ArrayList<String> list = getAllPackageName(context);
for (String str : list) {
map.put(str, true);
}
return map;
}
private void showNotification(Context context, JSONObject jsonObject, int id) throws JSONException {
Intent intent = new Intent();
intent.setAction("com.gh.gamecenter.NOTIFICATION");
intent.putExtra("notifyId", id);
intent.putExtra("notifyData", jsonObject.toString());
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_ONE_SHOT);
NotificationManager nManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.logo)
.setTicker(jsonObject.getString("pushTitle"))
.setContentTitle(jsonObject.getString("pushTitle"))
.setContentText(jsonObject.getString("pushDesc"))
.setContentIntent(pendingIntent).build();
RemoteViews remoteViews = null;
if (Build.MANUFACTURER.equals("Meizu") &&
(Build.MODEL.startsWith("m") || Build.MODEL.startsWith("MX"))) {
remoteViews = new RemoteViews(context.getPackageName(), R.layout.notification_meizu);
SimpleDateFormat format = new SimpleDateFormat("HH:mm", Locale.getDefault());
remoteViews.setTextViewText(R.id.time, format.format(new Date()));
} else if (Build.MANUFACTURER.equals("Xiaomi") &&
(Build.MODEL.startsWith("MI") || Build.MODEL.startsWith("HM") || Build.MODEL.startsWith("Redmi"))) {
// 小米系统
remoteViews = new RemoteViews(context.getPackageName(), R.layout.notification_xiaomi);
SimpleDateFormat format = new SimpleDateFormat("ah:mm", Locale.getDefault());
remoteViews.setTextViewText(R.id.time, format.format(new Date()));
} else if (Build.MANUFACTURER.equals("HUAWEI")) {
// 华为系统
remoteViews = new RemoteViews(context.getPackageName(), R.layout.notification_huawei);
}
String url = jsonObject.getString("icon");
String path = context.getCacheDir() + File.separator + url.substring(url.lastIndexOf("/") + 1);
int result = FileUtils.downloadFile(url, path);
if (result != 200) {
// 下载出错使用光环logo
path = null;
}
if (remoteViews != null) {
if (path == null) {
remoteViews.setImageViewBitmap(R.id.icon, BitmapFactory.decodeResource(context.getResources(), R.drawable.logo));
} else {
remoteViews.setImageViewBitmap(R.id.icon, BitmapFactory.decodeFile(path));
}
remoteViews.setTextViewText(R.id.title, jsonObject.getString("pushTitle"));
remoteViews.setTextViewText(R.id.intro, jsonObject.getString("pushDesc"));
notification.contentView = remoteViews;
} else {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.logo_black)
.setTicker(jsonObject.getString("pushTitle"))
.setContentTitle(jsonObject.getString("pushTitle"))
.setContentText(jsonObject.getString("pushDesc"))
.setContentIntent(pendingIntent);
if (path == null) {
builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.logo));
} else {
builder.setLargeIcon(BitmapFactory.decodeFile(path));
}
notification = builder.build();
}
notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音
notification.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时通知将被清除。
nManager.notify(((int) System.currentTimeMillis() / 1000), notification);// 通过通知管理器来发起通知。如果id不同则每click在status哪里增加一个提示
}
private ArrayList<String> getAllPackageName(Context context) {
ArrayList<String> list = new ArrayList<>();
List<PackageInfo> packageInfos = context.getPackageManager().getInstalledPackages(0);
for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
list.add(packageInfo.packageName);
}
}
return list;
}
@Override
public void onNotificationMessageClicked(Context context, MiPushMessage message) {
if (BuildConfig.DEBUG) {
AppDebugConfig.logMethodWithParams(this, message);
}
try {
String content = message.getContent();
JSONObject response = new JSONObject(content);
Bundle bundle = new Bundle();
bundle.putString(KEY_ENTRANCE, ENTRANCE_MIPUSH);
String type = response.getString(KEY_TYPE);
String target = response.getString(KEY_TARGET);
if (HOST_ARTICLE.equals(type)) {
bundle.putString(KEY_TO, "NewsDetailActivity");
bundle.putString(KEY_NEWSID, target);
} else if (HOST_GAME.equals(type)) {
bundle.putString(KEY_TO, "GameDetailActivity");
bundle.putString(KEY_GAMEID, target);
} else if (HOSt_COLUMN.equals(type)) {
bundle.putString(KEY_TO, "SubjectActivity");
bundle.putString(KEY_ID, target);
} else if (HOST_WEB.equals(type)) {
bundle.putString(KEY_TO, "WebActivity");
bundle.putString(KEY_URL, target);
}
EntranceUtils.jumpActivity(context, bundle);
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onNotificationMessageArrived(Context context,
MiPushMessage message) {
if (BuildConfig.DEBUG) {
AppDebugConfig.logMethodWithParams(this, message);
}
}
@Override
public void onReceiveRegisterResult(Context context, MiPushCommandMessage message) {
if (BuildConfig.DEBUG) {
AppDebugConfig.logMethodWithParams(this, message);
}
}
@Override
public void onCommandResult(Context context, MiPushCommandMessage message) {
if (BuildConfig.DEBUG) {
AppDebugConfig.logMethodWithParams(this, message);
}
String command = message.getCommand();
List<String> arguments = message.getCommandArguments();
if (MiPushClient.COMMAND_SET_ALIAS.equals(command)) {
if (message.getResultCode() == ErrorCode.SUCCESS) {
mAlias = arguments.get(0);
}
}
if (TextUtils.isEmpty(mAlias)) {
//添加别名
MiPushClient.setAlias(context, TokenUtils.getDeviceId(context), null);
}
}
}

View File

@ -4,6 +4,10 @@ import android.content.Context;
import android.os.Bundle;
import com.gh.common.util.EntranceUtils;
import com.gh.gamecenter.GameDetailActivity;
import com.gh.gamecenter.NewsDetailActivity;
import com.gh.gamecenter.WebActivity;
import com.gh.gamecenter.subject.refactor.SubjectActivity;
import com.umeng.message.UmengNotificationClickHandler;
import com.umeng.message.entity.UMessage;
@ -24,18 +28,23 @@ public class GHUmengNotificationClickHandler extends UmengNotificationClickHandl
bundle.putString(EntranceUtils.KEY_ENTRANCE, EntranceUtils.ENTRANCE_UMENG);
String type = response.getString(EntranceUtils.KEY_TYPE);
String target = response.getString(EntranceUtils.KEY_TARGET);
if (EntranceUtils.HOST_ARTICLE.equals(type)) {
bundle.putString(EntranceUtils.KEY_TO, "NewsDetailActivity");
bundle.putString(EntranceUtils.KEY_NEWSID, target);
} else if (EntranceUtils.HOST_GAME.equals(type)) {
bundle.putString(EntranceUtils.KEY_TO, "GameDetailActivity");
bundle.putString(EntranceUtils.KEY_GAMEID, target);
} else if (EntranceUtils.HOSt_COLUMN.equals(type)) {
bundle.putString(EntranceUtils.KEY_TO, "SubjectActivity");
bundle.putString(EntranceUtils.KEY_ID, target);
} else if (EntranceUtils.HOST_WEB.equals(type)) {
bundle.putString(EntranceUtils.KEY_TO, "WebActivity");
bundle.putString(EntranceUtils.KEY_URL, target);
switch (type) {
case EntranceUtils.HOST_ARTICLE:
bundle.putString(EntranceUtils.KEY_TO, NewsDetailActivity.class.getSimpleName());
bundle.putString(EntranceUtils.KEY_NEWSID, target);
break;
case EntranceUtils.HOST_GAME:
bundle.putString(EntranceUtils.KEY_TO, GameDetailActivity.class.getSimpleName());
bundle.putString(EntranceUtils.KEY_GAMEID, target);
break;
case EntranceUtils.HOST_COLUMN:
bundle.putString(EntranceUtils.KEY_TO, SubjectActivity.class.getName());
bundle.putString(EntranceUtils.KEY_ID, target);
break;
case EntranceUtils.HOST_WEB:
bundle.putString(EntranceUtils.KEY_TO, WebActivity.class.getSimpleName());
bundle.putString(EntranceUtils.KEY_URL, target);
break;
}
EntranceUtils.jumpActivity(context, bundle);
} catch (JSONException e) {

View File

@ -0,0 +1,232 @@
package com.gh.base
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 android.os.Bundle
import android.preference.PreferenceManager
import android.support.v4.app.NotificationCompat
import android.text.TextUtils
import android.view.View
import com.gh.common.notifier.Notifier
import com.gh.common.util.DataUtils
import com.gh.common.util.EntranceUtils
import com.gh.common.util.PackageUtils
import com.gh.common.util.StringUtils
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.PushEntity
import com.gh.gamecenter.entity.PushMessageEntity
import com.gh.gamecenter.entity.PushMessageUnreadEntity
import com.gh.gamecenter.entity.PushNotificationEntity
import com.gh.gamecenter.message.MessageUnreadRepository
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
import com.gh.gamecenter.receiver.UmengMessageReceiver
import com.gh.gamecenter.receiver.UmengMessageReceiver.Companion.TYPE_CLICK
import com.gh.gamecenter.receiver.UmengMessageReceiver.Companion.TYPE_REMOVE
import com.google.gson.Gson
import com.halo.assistant.HaloApp
import com.umeng.message.UmengMessageService
import org.android.agoo.common.AgooConstants
import java.util.*
class GHUmengNotificationService : UmengMessageService() {
companion object {
const val ACTION_UMENG = "com.gh.gamecenter.UMENG"
const val MESSAGE_FROM_SYSTEM = "message_from_system"
const val HALO_MESSAGE_DIALOG = "HALO_MESSAGE_DIALOG"
const val HALO_MESSAGE_CENTER = "HALO_MESSAGE_CENTER"
const val ANSWER = "answer"
const val FOLLOW_QUESTION = "follow_question"
const val NOTIFICATION_ID = 2015
const val DISPLAY_TYPE_NOTIFICATION = "notification"
const val DISPLAY_TYPE_CUSTOM = "custom"
}
val notificationTags = arrayOf("GH_UMENG_TAG_1", "GH_UMENG_TAG_2", "GH_UMENG_TAG_3")
val gson = Gson()
override fun onMessage(context: Context, intent: Intent) {
val message = intent.getStringExtra(AgooConstants.MESSAGE_BODY)
val isMessageFromSystem = intent.getBooleanExtra(MESSAGE_FROM_SYSTEM, false)
try {
val pushData = gson.fromJson(message, PushEntity::class.java)
pushData?.let { handlePushData(context, it, message, isMessageFromSystem) }
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun handlePushData(context: Context, pushData: PushEntity, message: String, isMessageFromSystem: Boolean) {
val notificationManager = context.applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (pushData.displayType == DISPLAY_TYPE_NOTIFICATION) {
// 其它类型的透传信息
// 显示到通知栏
val msg = gson.fromJson(message, PushNotificationEntity::class.java)
val data = msg?.extra?.data
// 系统推送,直接处理跳转
if (isMessageFromSystem) {
val intent = Intent()
intent.setClass(context, UmengMessageReceiver::class.java)
intent.putExtra(EntranceUtils.KEY_DATA, data?.link)
intent.putExtra(EntranceUtils.KEY_TYPE, UmengMessageReceiver.DIRECT_ONLY)
intent.putExtra(EntranceUtils.KEY_MESSAGE, message)
context.sendBroadcast(intent)
return
}
// 判断是否过滤该消息
if (validatePush(data?.condition)) {
val clickIntent = Intent()
val removeIntent = Intent()
clickIntent.setClass(context, UmengMessageReceiver::class.java)
clickIntent.putExtra(EntranceUtils.KEY_DATA, data?.link)
clickIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
clickIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_CLICK)
removeIntent.setClass(context, UmengMessageReceiver::class.java)
removeIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_REMOVE)
removeIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
val clickPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(),
clickIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val deletePendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt() + 1,
removeIntent, PendingIntent.FLAG_UPDATE_CURRENT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel("Halo_Push", "Halo_Push", NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(channel)
}
val notification = NotificationCompat.Builder(context, "Halo_Push")
.setSmallIcon(R.drawable.ic_notification)
.setTicker(pushData.body?.ticker)
.setContentTitle(pushData.body?.title)
.setContentText(pushData.body?.text)
.setContentIntent(clickPendingIntent)
.setDeleteIntent(deletePendingIntent)
.build()
notification.flags = notification.flags or Notification.FLAG_AUTO_CANCEL
notificationManager.notify(getNotificationTag(context), NOTIFICATION_ID, notification)
}
} else {
if (HALO_MESSAGE_DIALOG == pushData.body?.custom) {
// 回答了问题或者关注了问题的消息
val msg = gson.fromJson(message, PushMessageEntity::class.java)
val data = msg?.extra?.data
val type = if (ANSWER == data?.type) {
"回答了你的问题"
} else {
"回答了你关注的问题"
}
val userName = StringUtils.shrinkStringWithDot(data?.userEntity?.name, 8)
val displayText = userName + type
if (Notifier.isActivityValid(CurrentActivityHolder.getCurrentActivity()) &&
Notifier.shouldShowNotifier(data?.answer?.id + displayText)) {
Notifier.create(CurrentActivityHolder.getCurrentActivity())
.setText(displayText)
.setDuration(5000)
.setIcon(data?.userEntity?.icon)
.setOnClickListener(View.OnClickListener { _ ->
val bundle = Bundle()
bundle.putString(EntranceUtils.KEY_ANSWER_ID, data?.answer?.id)
bundle.putString(EntranceUtils.KEY_ENTRANCE, EntranceUtils.ENTRANCE_UMENG)
bundle.putString(EntranceUtils.KEY_TO, AnswerDetailActivity::class.java.name)
EntranceUtils.jumpActivity(context, bundle)
DataUtils.onMtaEvent(context, "消息弹窗",
type, "")
Notifier.hide()
})
.show(false)
Notifier.tagNotifierAsShowed(data?.answer?.id + displayText)
}
} else if (HALO_MESSAGE_CENTER == pushData.body?.custom) {
// 消息中心逻辑
val msg = gson.fromJson(message, PushMessageUnreadEntity::class.java)
val data = msg?.extra?.data
data?.let { MessageUnreadRepository.loadMessageUnreadData() }
}
}
}
private fun validatePush(condition: PushNotificationEntity.Data.Condition?): Boolean {
if (condition == null) return true
// 校验渠道是否匹配
condition.ghzs?.channel?.let {
if (it.isNotEmpty() && it != HaloApp.getInstance().channel) {
return false
}
}
// 校验光环版本版本是否匹配
condition.ghzs?.version?.let {
if (it.isNotEmpty() && !BuildConfig.VERSION_NAME.contains(it)) {
return false
}
}
// 校验已安装的应用里是否存在条件的包名
if (condition.packageName.isNotEmpty()) {
val installedPackageList = PackageUtils.getAllPackageName(HaloApp.getInstance().application)
for (packageName in installedPackageList) {
if (condition.packageName == packageName) {
return true
}
}
return false
}
return true
}
/**
* 规则:最多三条消息,以旧换新
*
* @return NotificationTag
*/
private fun getNotificationTag(context: Context): String {
val sp = PreferenceManager.getDefaultSharedPreferences(context)
val edit = sp.edit()
val timeTagMap = HashMap<Long, String>()
for (tag in notificationTags) {
val time = sp.getLong(tag, 0)
if (time == 0L) {
edit.putLong(tag, System.currentTimeMillis()).apply()
return tag
} else {
timeTagMap[time] = tag
}
}
val minTime = Collections.min(timeTagMap.keys)
val tag = timeTagMap[minTime]
edit.putLong(tag, System.currentTimeMillis()).apply()
return if (TextUtils.isEmpty(tag)) notificationTags[0] else tag!!
}
}

View File

@ -1,275 +0,0 @@
package com.gh.base;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.gh.common.constant.Config;
import com.gh.common.util.DataCollectionUtils;
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.ConcernActivity;
import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.SearchActivity;
import com.gh.gamecenter.eventbus.EBDownloadStatus;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.manager.PackageManager;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
/**
* Created by LGT on 2016/9/9.
* 工具栏 搜索控制
*/
public class HomeFragment extends Fragment implements View.OnClickListener, SearchBarHint {
protected View view;
private TextView downloadHint;
private TextView searchHint;
private AlphaAnimation mAlphaAnimation;
private ArrayList<String> hintList;
private int hintIndex;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
hintList = savedInstanceState.getStringArrayList("hint");
}
hintIndex = 0;
view = View.inflate(getActivity(), R.layout.fragment_home, null);
// SharedPreferences sp = getActivity().getSharedPreferences(
// Config.PREFERENCE, Context.MODE_PRIVATE);
LinearLayout home_actionbar = (LinearLayout) view.findViewById(R.id.home_actionbar);
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(getActivity(), 55));
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// int top = DisplayUtils.getStatusBarHeight(getResources());
// home_actionbar.setPadding(0, top, 0, 0);
// lparams.height += top;
// }
home_actionbar.setLayoutParams(lparams);
initActionBar();
final ScaleAnimation scaleAnimation = new ScaleAnimation(0.4f, 1.0f, 0.4f, 1.0f
, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(500);
mAlphaAnimation = new AlphaAnimation(1f, 0.2f);
mAlphaAnimation.setDuration(300);
mAlphaAnimation.setStartOffset(5000);
scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (mAlphaAnimation != null) {
searchHint.setAnimation(mAlphaAnimation);
mAlphaAnimation.start();
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
mAlphaAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
// 切换数据
if (hintIndex > hintList.size() - 1) {
hintIndex = 0;
}
searchHint.setHint(hintList.get(hintIndex));
hintIndex++;
if (scaleAnimation != null) {
searchHint.setAnimation(scaleAnimation);
scaleAnimation.start();
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
if (hintList != null && hintList.size() > 0) {
if (hintList.size() > 1) {
searchHint.setAnimation(mAlphaAnimation);
} else {
String hint = hintList.get(0);
searchHint.setHint(hint);
}
}
EventBus.getDefault().register(this);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
if (container != null) {
container.removeView(view);
}
return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (hintList != null && !hintList.isEmpty()) {
outState.putStringArrayList("hint", hintList);
}
}
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
private void initActionBar() {
view.findViewById(R.id.actionbar_rl_download).setOnClickListener(this);
view.findViewById(R.id.actionbar_iv_search).setOnClickListener(this);
view.findViewById(R.id.actionbar_notification).setOnClickListener(this);
view.findViewById(R.id.actionbar_search_rl).setOnClickListener(this);
if (Config.isShow(getActivity())) {
view.findViewById(R.id.actionbar_rl_download).setVisibility(View.VISIBLE);
} else {
view.findViewById(R.id.actionbar_rl_download).setVisibility(View.GONE);
}
downloadHint = (TextView) view.findViewById(R.id.action_tip);
int updateSize = PackageManager.getUpdateListSize();
int downloadSize = DownloadManager.getInstance(getActivity()).getAll().size();
if (downloadSize != 0) {
downloadHint.setVisibility(View.VISIBLE);
downloadHint.setText(String.valueOf(downloadSize));
} else if (updateSize != 0) {
downloadHint.setVisibility(View.VISIBLE);
downloadHint.setText(String.valueOf(updateSize));
} else {
downloadHint.setVisibility(View.GONE);
}
searchHint = (TextView) view.findViewById(R.id.actionbar_search_input);
searchHint.setOnClickListener(this);
}
@Override
public void onClick(View v) {
final int id = v.getId();
if (id == R.id.actionbar_rl_download) {
DataUtils.onEvent(getActivity(), "主页", "下载图标");
DataCollectionUtils.uploadClick(getActivity(), "下载图标", "主页");
DownloadManagerActivity.startDownloadManagerActivity(getContext(), null, "(工具栏)");
} else if (id == R.id.actionbar_iv_search) {
DataUtils.onEvent(getActivity(), "主页", "搜索图标");
DataCollectionUtils.uploadClick(getActivity(), "搜索图标", "主页");
Intent intent = new Intent(getActivity(), SearchActivity.class);
intent.putExtra("clicked", true);
intent.putExtra("hint", searchHint.getHint().toString());
intent.putExtra(EntranceUtils.KEY_ENTRANCE, "(工具栏)");
startActivity(intent);
} else if (id == R.id.actionbar_search_input || id == R.id.actionbar_search_rl) {
DataUtils.onEvent(getActivity(), "主页", "搜索框");
DataCollectionUtils.uploadClick(getActivity(), "搜索框", "主页");
Intent intent = new Intent(getActivity(), SearchActivity.class);
intent.putExtra("clicked", false);
intent.putExtra("hint", searchHint.getHint().toString());
intent.putExtra(EntranceUtils.KEY_ENTRANCE, "(工具栏)");
startActivity(intent);
} else if (id == R.id.actionbar_notification) {
DataUtils.onEvent(getActivity(), "主页", "关注图标");
DataCollectionUtils.uploadClick(getActivity(), "关注图标", "主页");
Intent intent = new Intent(getActivity(), ConcernActivity.class);
intent.putExtra(EntranceUtils.KEY_ENTRANCE, "(工具栏)");
startActivity(intent);
}
}
// 打开下载按钮事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBReuse reuse) {
if ("Refresh".equals(reuse.getType())) {
if (Config.isShow(getActivity())) {
view.findViewById(R.id.actionbar_rl_download).setVisibility(View.VISIBLE);
} else {
view.findViewById(R.id.actionbar_rl_download).setVisibility(View.GONE);
}
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBDownloadStatus status) {
int updateSize = PackageManager.getUpdateListSize();
int downloadSize = DownloadManager.getInstance(getActivity()).getAll().size();
if (downloadSize != 0) {
downloadHint.setVisibility(View.VISIBLE);
downloadHint.setText(String.valueOf(downloadSize));
} else if (updateSize != 0) {
downloadHint.setVisibility(View.VISIBLE);
downloadHint.setText(String.valueOf(updateSize));
} else {
downloadHint.setVisibility(View.GONE);
}
}
@Override
public void setHint(ArrayList<String> hint) {
if (hint != null && hint.size() > 0) {
hintList = hint;
if (hint.size() == 1 && searchHint != null) {
searchHint.setHint(hintList.get(0));
} else if (mAlphaAnimation != null && searchHint != null) {
searchHint.setAnimation(mAlphaAnimation);
}
}
}
}

View File

@ -1,9 +0,0 @@
package com.gh.base;
/**
* Forward activity onBackPressed() events to fragment
* (If nested fragments need this, just forward again)
*/
public interface OnBackPressedListener {
public boolean onHandleBackPressed();
}

View File

@ -0,0 +1,19 @@
package com.gh.base;
import android.view.View;
/**
* Created by khy on 26/09/17.
*/
public interface OnListClickListener {
/**
*
* @param view
* @param position list position
* @param data list data (直接强转 如果列表传入不同数据类型 请做好判断)
* @param <T>
*/
<T> void onListClick(View view, int position, T data);
}

View File

@ -1,13 +1,13 @@
package com.gh.gamecenter.listener;
package com.gh.base;
/**
* Created by Administrator on 2016/9/8.
*/
public interface OnCallBackListener {
public interface OnRequestCallBackListener<T> {
void loadDone();
void loadDone(Object obj);
void loadDone(T obj);
void loadError();

View File

@ -0,0 +1,7 @@
package com.gh.base;
import android.view.View;
public interface OnViewClickListener {
void onClick(View v, Object data);
}

View File

@ -1,48 +0,0 @@
package com.gh.base;
import java.io.Serializable;
public enum SuggestionType implements Serializable {
FEEDBACK("普通反馈", 1),
SUGGESTION("功能建议", 2),
CRASH("发生闪退", 3),
GAME("游戏问题", 4),
COLLECT("游戏收录", 5),
POST("文章投稿", 6);
private String mName;
private int mIndex;
private SuggestionType(String name, int index) {
mName = name;
mIndex = index;
}
public static String getName(int index) {
for (SuggestionType c : SuggestionType.values()) {
if (c.mIndex == index) {
return c.mName;
}
}
return "";
}
public static int getIndex(String name) {
for (SuggestionType c : SuggestionType.values()) {
if (c.mName == name) {
return c.mIndex;
}
}
return -1;
}
public int getIndex() {
return mIndex;
}
public String getName() {
return mName;
}
}

View File

@ -1,17 +0,0 @@
package com.gh.base;
import android.support.annotation.StringRes;
import android.support.v7.widget.Toolbar;
/**
* Created by csheng on 15-10-12.
*/
public interface ToolbarController {
void setNavigationTitle(@StringRes int res);
void setNavigationTitle(CharSequence res);
Toolbar getToolBar();
}

View File

@ -0,0 +1,49 @@
package com.gh.base.adapter;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.List;
/**
* Created by LGT on 2016/11/17.
* ViewPager FragmentAdapter
*/
public class FragmentAdapter extends FragmentPagerAdapter {
private List<Fragment> mFragmentList;
private List<String> mTitleList;
public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
super(fm);
this.mFragmentList = fragmentList;
}
public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList, List<String> titleList) {
super(fm);
this.mFragmentList = fragmentList;
this.mTitleList = titleList;
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
if (mTitleList != null && mTitleList.size() > position) {
return mTitleList.get(position);
}
return super.getPageTitle(position);
}
}

View File

@ -1,20 +1,19 @@
package com.gh.gamecenter.adapter;
package com.gh.base.adapter;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import java.util.List;
/**
* Created by LGT on 2016/11/17.
* ViewPager FragmentAdapter
* Created by khy on 7/12/28.
*/
public class FragmentAdapter extends FragmentPagerAdapter {
public class FragmentStateAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragmentList;
public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
public FragmentStateAdapter(FragmentManager fm, List<Fragment> fragmentList) {
super(fm);
this.mFragmentList = fragmentList;
}

View File

@ -0,0 +1,63 @@
package com.gh.base.fragment;
import android.app.Dialog;
import android.arch.lifecycle.Lifecycle;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.v4.app.DialogFragment;
import android.view.KeyEvent;
import com.gh.common.util.ClickUtils;
import com.gh.gamecenter.R;
import com.lightgame.utils.RuntimeUtils;
import com.lightgame.utils.Utils;
/**
* @author CsHeng
* @Date 17/05/2017
* @Time 4:30 PM
*/
public class BaseDialogFragment extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Dialog dialog = new Dialog(getActivity(), R.style.DialogWindowTransparent);
dialog.setCanceledOnTouchOutside(false);
dialog.setOnKeyListener((dialog1, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK && ClickUtils.isFastDoubleClick()) { //会多次响应??
return onBack();
}
return false;
});
dialog.setCancelable(false);
return dialog;
}
public void toast(@StringRes int res) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
toast(getString(res));
}
public void toast(String msg) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
Utils.toast(getContext(), msg);
}
public void toastLong(@StringRes int msg) {
toastLong(getString(msg));
}
public void toastLong(String msg) {
RuntimeUtils.getInstance().toastLong(getContext(), msg);
}
public boolean onBack() {
return false;
}
}

View File

@ -0,0 +1,65 @@
package com.gh.base.fragment;
import android.app.Dialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.gh.gamecenter.R;
/**
* Wrap another fragment with dialog fragment.
*/
public class BaseDialogWrapperFragment extends BaseDialogFragment {
private Fragment mFragmentToWrap;
public static BaseDialogWrapperFragment getInstance(Fragment fragmentToWrap) {
BaseDialogWrapperFragment fragment = new BaseDialogWrapperFragment();
fragment.mFragmentToWrap = fragmentToWrap;
return fragment;
}
public static BaseDialogWrapperFragment getInstance(Fragment fragmentToWrap, boolean isCancelable) {
BaseDialogWrapperFragment fragment = new BaseDialogWrapperFragment();
fragment.mFragmentToWrap = fragmentToWrap;
fragment.setCancelable(isCancelable);
return fragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_dialog_wrapper, null);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mFragmentToWrap != null) {
getChildFragmentManager().beginTransaction().replace(R.id.fragment_placeholder, mFragmentToWrap).commitNowAllowingStateLoss();
}
}
@Override
public void onStart() {
super.onStart();
getDialog().getWindow().setGravity(Gravity.BOTTOM);
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.setCanceledOnTouchOutside(true);
return dialog;
}
}

View File

@ -0,0 +1,237 @@
package com.gh.base.fragment;
import android.arch.lifecycle.Lifecycle;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.gh.base.OnListClickListener;
import com.gh.base.OnRequestCallBackListener;
import com.gh.gamecenter.eventbus.EBMiPush;
import com.lightgame.OnTitleClickListener;
import com.lightgame.utils.RuntimeUtils;
import com.lightgame.utils.Utils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.lang.ref.WeakReference;
import java.util.List;
import butterknife.ButterKnife;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
/**
* Created by LGT on 2016/9/4.
* Fragment 基类
*/
public abstract class BaseFragment<T> extends Fragment implements OnRequestCallBackListener<T>,
View.OnClickListener, OnListClickListener, OnTitleClickListener {
protected View mCachedView;
protected boolean isEverPause;
protected String mEntrance;
protected final Handler mBaseHandler = new BaseFragment.BaseHandler(this);
protected static class BaseHandler extends Handler {
private final WeakReference<BaseFragment> mFragmentWeakReference;
BaseHandler(BaseFragment fragment) {
mFragmentWeakReference = new WeakReference<>(fragment);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
BaseFragment fragment = mFragmentWeakReference.get();
if (fragment != null) fragment.handleMessage(msg);
}
}
protected void handleMessage(Message msg) {
}
@LayoutRes
protected abstract int getLayoutId();
/**
* 提供 Inflated 的 view ,可用于 data binding.
*/
protected View getInflatedLayout() {
return null;
}
/**
* 责任链谁处理了就返回true否则返回super.handleOnClick(View view)
*
* @return
*/
protected boolean handleOnClick(View view) {
return true;
}
@Override
public void onClick(View v) {
handleOnClick(v);
}
protected void initView(View view) {
}
protected void postRunnable(Runnable runnable) {
RuntimeUtils.getInstance().runOnUiThread(runnable);
}
// 定时任务全部改用这个方法, 在onDestroy做统一取消定时
protected void postDelayedRunnable(Runnable runnable, long delayMillis) {
RuntimeUtils.getInstance().runOnUiThread(runnable, delayMillis);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getActivity().getIntent();
mEntrance = intent.getStringExtra(KEY_ENTRANCE);
if (TextUtils.isEmpty(mEntrance) && getArguments() != null) {
mEntrance = getArguments().getString(KEY_ENTRANCE);
}
isEverPause = false;
EventBus.getDefault().register(this);
// For data binding.
if (getInflatedLayout() != null) {
mCachedView = getInflatedLayout();
} else {
mCachedView = View.inflate(getContext(), getLayoutId(), null);
}
ButterKnife.bind(this, mCachedView);
initView(mCachedView);
}
//TODO 尴尬必须的有subscribe才能register
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onDummyEvent(EBMiPush push) {
//
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (container != null) {
container.removeView(mCachedView);
}
return mCachedView;
}
@Override
public void onResume() {
super.onResume();
isEverPause = false;
}
@Override
public void onPause() {
super.onPause();
isEverPause = true;
}
@Override
public void onDestroy() {
super.onDestroy();
mBaseHandler.removeCallbacksAndMessages(null);
RuntimeUtils.getInstance().removeRunnable();
EventBus.getDefault().unregister(this);
}
public void toast(@StringRes int res) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
toast(getString(res));
}
public void toast(String msg) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
Utils.toast(getContext(), msg);
}
public void toastLong(@StringRes int msg) {
toastLong(getString(msg));
}
public void toastLong(String msg) {
RuntimeUtils.getInstance().toastLong(getContext(), msg);
}
public boolean isEverPause() {
return isEverPause;
}
@Override
public void loadDone() {
}
@Override
public void loadDone(T obj) {
}
@Override
public void loadError() {
}
@Override
public void loadEmpty() {
}
@Override
public <LIST> void onListClick(View view, int position, LIST data) {
}
protected <K> Observable<K> asyncCall(Observable<K> observable) {
return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
// 将所有的Fragment都置为隐藏状态。
protected void hideFragments(FragmentTransaction transaction) {
List<Fragment> list = getChildFragmentManager().getFragments();
for (Fragment fragment : list) {
transaction.hide(fragment);
}
}
@Override
public void onTitleClick() {
List<Fragment> list = getChildFragmentManager().getFragments();
for (Fragment fragment : list) {
if (fragment instanceof OnTitleClickListener) {
((OnTitleClickListener) fragment).onTitleClick();
}
}
}
}

View File

@ -0,0 +1,118 @@
package com.gh.base.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.View;
import com.gh.base.adapter.FragmentAdapter;
import com.gh.common.view.TabIndicatorView;
import com.gh.gamecenter.R;
import com.gh.gamecenter.normal.NormalFragment;
import com.lightgame.view.NoScrollableViewPager;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
/**
* Created by khy on 15/03/18.
*/
public abstract class BaseFragment_TabLayout extends NormalFragment implements ViewPager.OnPageChangeListener {
public static final String PAGE_INDEX = "PAGE_INDEX";
@BindView(R.id.fragment_tab_layout)
protected TabLayout mTabLayout;
@BindView(R.id.fragment_view_pager)
protected NoScrollableViewPager mViewPager;
@BindView(R.id.fragment_tab_indicator)
protected TabIndicatorView mTabIndicatorView;
protected List<Fragment> mFragmentsList;
protected List<String> mTabTitleList;
protected int mCheckedIndex = 0;
protected abstract void initFragmentList(List<Fragment> fragments);
protected abstract void initTabTitleList(List<String> tabTitleList);
protected int provideIndicatorWidth() {
return 65;
}
protected View provideTabView(int position, String tabTitle) {
return null;
}
@Override
protected int getLayoutId() {
return R.layout.fragment_taglyout_viewpager;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) mCheckedIndex = getArguments().getInt(PAGE_INDEX, 0);
mFragmentsList = new ArrayList<>();
initFragmentList(mFragmentsList);
mTabTitleList = new ArrayList<>();
initTabTitleList(mTabTitleList);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mViewPager.setOffscreenPageLimit(mFragmentsList.size());
mViewPager.addOnPageChangeListener(this);
mViewPager.setAdapter(new FragmentAdapter(getChildFragmentManager(), mFragmentsList, mTabTitleList));
mViewPager.setCurrentItem(mCheckedIndex);
mTabLayout.setupWithViewPager(mViewPager);
mTabIndicatorView.setupWithTabLayout(mTabLayout);
mTabIndicatorView.setupWithViewPager(mViewPager);
mTabIndicatorView.setIndicatorWidth(provideIndicatorWidth());
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
TabLayout.Tab tab = mTabLayout.getTabAt(i);
if (tab == null) continue;
View tabView = provideTabView(i, tab.getText() != null ? tab.getText().toString() : "");
if (tabView == null) continue;
tab.setCustomView(tabView);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
}

View File

@ -0,0 +1,126 @@
/**
* project: OPlay
* <p/>
* <p/>
* ========================================================================
* amend date amend user amend reason
* 2013-3-6 CsHeng
*/
package com.gh.base.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import com.gh.gamecenter.normal.NormalFragment;
import com.lightgame.adapter.BaseFragmentPagerAdapter;
import com.lightgame.config.CommonDebug;
import com.lightgame.view.DoubleTapTextView;
import java.util.ArrayList;
import java.util.List;
/**
* ViewPager 配合RadioGroup实现双切换<br/>
* 记得自己控制onCreateView返回和radioGroup里面radiobutton个数,Viewpager的布局<br/>
*
* @author CsHeng
* @date 2013-3-6
*/
public abstract class BaseFragment_ViewPager extends NormalFragment implements DoubleTapTextView.OnDoubleTapListener {
public static final String ARGS_INDEX = "index";
protected int mCheckedIndex = 0;
protected PagerAdapter mAdapter;
protected List<Fragment> mFragmentsList;
protected ViewPager mViewPager;
@LayoutRes
protected abstract int getLayoutId();
@IdRes
protected abstract int getViewPagerId();
protected abstract void initFragmentList(List<Fragment> fragments);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mFragmentsList = new ArrayList<>();
initFragmentList(mFragmentsList);
mAdapter = BaseFragmentPagerAdapter.newInstance(getChildFragmentManager(), mFragmentsList);
final Bundle args = getArguments();
if (args != null) {
mCheckedIndex = args.getInt(ARGS_INDEX);
}
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mViewPager = (ViewPager) view.findViewById(getViewPagerId());
mViewPager.setOffscreenPageLimit(mFragmentsList.size());
mViewPager.setAdapter(mAdapter);
if (mCheckedIndex < mFragmentsList.size()) {
mViewPager.setCurrentItem(mCheckedIndex, false);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (getArguments() != null) {
getArguments().putInt(ARGS_INDEX, mCheckedIndex);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (mViewPager != null) {
mViewPager.setAdapter(null);
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mFragmentsList != null) {
mFragmentsList.clear();
}
}
@Override
public boolean onDoubleTap() {
final Fragment fragment = mFragmentsList.get(mViewPager.getCurrentItem());
return fragment instanceof DoubleTapTextView.OnDoubleTapListener && ((DoubleTapTextView.OnDoubleTapListener)
fragment).onDoubleTap();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (CommonDebug.IS_DEBUG) {
CommonDebug.logMethodWithParams(this, requestCode, resultCode, data);
}
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
}
public int getCurrentItem() {
return mViewPager != null ? mViewPager.getCurrentItem() : 0;
}
}

View File

@ -0,0 +1,109 @@
/**
* project: OPlay
* <p/>
* <p/>
* ========================================================================
* amend date amend user amend reason
* 2013-3-6 CsHeng
*/
package com.gh.base.fragment;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Checkable;
/**
* ViewPager 配合ViewGroup Checkable实现双切换<br/>
* 记得自己控制onCreateView返回和ViewGroup里面Checkable个数,ViewPager的布局<br/>
*
* @author CsHeng
* @date 2013-3-6
* @update 2014-09-29
*/
public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_ViewPager implements
ViewPager.OnPageChangeListener {
protected ViewGroup mCheckableGroup;
@IdRes
protected abstract int getCheckableGroupId();
protected boolean getSmoothScroll() {
return false;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mCheckableGroup = (ViewGroup) view.findViewById(getCheckableGroupId());
for (int i = 0, size = mCheckableGroup.getChildCount(); i < size; i++) {
mCheckableGroup.getChildAt(i).setOnClickListener(this);
}
mViewPager.addOnPageChangeListener(this);
}
@Override
public void onDestroyView() {
super.onDestroyView();
mViewPager.removeOnPageChangeListener(this);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
checkIndex(mCheckedIndex);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int index) {
onPageChanged(index);
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
protected boolean handleOnClick(View view) {
final int toCheck = mCheckableGroup.indexOfChild(view);
if (toCheck != -1) {
mViewPager.setCurrentItem(toCheck, getSmoothScroll());
return true;
}
return super.handleOnClick(view);
}
protected void checkIndex(int index) {
final int childCount = mCheckableGroup.getChildCount();
if (index < childCount && mCheckedIndex < childCount) {
final View toChecked = mCheckableGroup.getChildAt(index);
if (toChecked instanceof Checkable) {
((Checkable) toChecked).setChecked(true);
}
if (index != mCheckedIndex) {
final View checkedChild = mCheckableGroup.getChildAt(mCheckedIndex);
if (checkedChild instanceof Checkable) {
((Checkable) checkedChild).setChecked(false);
}
}
mCheckedIndex = index;
}
}
protected void onPageChanged(int index) {
checkIndex(index);
}
}

View File

@ -0,0 +1,5 @@
package com.gh.base.fragment;
public interface OnDialogBackListener {
void onBack();
}

View File

@ -0,0 +1,106 @@
package com.gh.base.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.gh.gamecenter.R;
/**
* @author CsHeng
* @Date 17/05/2017
* @Time 4:27 PM
*/
public class WaitingDialogFragment extends BaseDialogFragment {
public static final String KEY_MSG = "msg";
private OnDialogBackListener mBackListener;
private TextView message;
public static WaitingDialogFragment newInstance(String message) {
Bundle args = new Bundle();
args.putString(KEY_MSG, message);
WaitingDialogFragment fragment = new WaitingDialogFragment();
fragment.setArguments(args);
return fragment;
}
public static WaitingDialogFragment newInstance(String message, boolean isCancelable) {
Bundle args = new Bundle();
args.putString(KEY_MSG, message);
WaitingDialogFragment fragment = new WaitingDialogFragment();
fragment.setArguments(args);
fragment.setCancelable(isCancelable);
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.set_wait_dialog, null);
message = (TextView) view.findViewById(R.id.set_wait_message);
message.setText(getArguments().getString(KEY_MSG));
return view;
}
@Override
public void show(FragmentManager manager, String tag) {
try {
super.show(manager, tag);
} catch (Exception e) {
e.printStackTrace();
}
}
public void show(FragmentManager manager, String tag, OnDialogBackListener backListener) {
show(manager, tag);
this.mBackListener = backListener;
}
public void uploadWaitingHint(String hint) {
if (message != null) message.setText(hint);
}
@Override
public boolean onBack() {
if (mBackListener != null) {
mBackListener.onBack();
return true;
}
return super.onBack();
}
public static class WaitingDialogData {
private String msg;
private boolean isShow;
public WaitingDialogData(String msg, boolean isShow) {
this.msg = msg;
this.isShow = isShow;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public boolean isShow() {
return isShow;
}
public void setShow(boolean show) {
isShow = show;
}
}
}

View File

@ -0,0 +1,33 @@
package com.gh.base;
import android.content.Context;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by khy on 25/04/18.
*/
public abstract class onDoubleTapListener implements View.OnTouchListener {
private GestureDetector mGestureDetector;
public onDoubleTapListener(Context context) {
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
onDoubleTapListener.this.onDoubleTap();
return true;
}
});
}
@Override
public boolean onTouch(View v, MotionEvent event) {
mGestureDetector.onTouchEvent(event);
return true;
}
public abstract void onDoubleTap();
}

View File

@ -0,0 +1,21 @@
package com.gh.common
import android.os.Handler
import android.os.Looper
import java.util.concurrent.Executor
import java.util.concurrent.Executors
object AppExecutor {
@JvmStatic
var ioExecutor = Executors.newSingleThreadExecutor()
@JvmStatic
var uiExecutor = MainThreadExecutor()
class MainThreadExecutor : Executor {
private val mainThreadHandler = Handler(Looper.getMainLooper())
override fun execute(command: Runnable) {
mainThreadHandler.post(command)
}
}
}

View File

@ -0,0 +1,39 @@
package com.gh.common
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import com.gh.common.im.ImManager
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.m7.imkfsdk.chat.ChatActivity
import io.reactivex.schedulers.Schedulers
/**
* 可使用 [LocalBroadcastManager] 来进行简单的模块间消息通知
*/
class LocalBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
intent?.let {
when (intent.action) {
ChatActivity.ACTION_DISMISS_FLOATING_WINDOW -> {
ImManager.dismissFloatingWindow()
RetrofitManager.getInstance(HaloApp.getInstance().application).api.postImEnding(UserManager.getInstance().userId)
.subscribeOn(Schedulers.io())
.subscribe()
}
ChatActivity.ACTION_HIDE_UNREAD_DOT -> {
ImManager.updateShouldShowFloatingWindowDot(false)
}
else -> return
}
}
}
}

View File

@ -0,0 +1,137 @@
package com.gh.common
import android.preference.PreferenceManager
import com.gh.base.GHUmengNotificationService
import com.gh.common.constant.Config
import com.gh.common.exposure.meta.MetaUtil
import com.gh.common.util.edit
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.entity.AliasEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.google.gson.Gson
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import com.umeng.commonsdk.UMConfigure
import com.umeng.message.IUmengRegisterCallback
import com.umeng.message.PushAgent
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import org.android.agoo.huawei.HuaWeiRegister
import org.android.agoo.mezu.MeizuRegister
import org.android.agoo.xiaomi.MiPushRegistar
import org.json.JSONObject
object PushManager {
var gson = Gson()
var deviceToken: String? = ""
var previousAlias: AliasEntity? = null
var application = HaloApp.getInstance().application
const val SP_PUSH_ALIAS = "push_alias"
@JvmStatic
fun init(channel: String) {
//初始化友盟推送
UMConfigure.init(application,
Config.UMENG_APPKEY, channel,
UMConfigure.DEVICE_TYPE_PHONE,
Config.UMENG_MESSAGE_SECRET)
// 注册小米、华为和魅族通道
MiPushRegistar.register(application, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY)
HuaWeiRegister.register(application)
MeizuRegister.register(application, BuildConfig.MEIZUPUSH_APPID, BuildConfig.MEIZUPUSH_APPKEY)
//友盟推送
val pushAgent = PushAgent.getInstance(application)
pushAgent.onAppStart() // 开启App统计
//注册推送服务每次调用register方法都会回调该接口
registerDevice()
val aliasInSp = PreferenceManager.getDefaultSharedPreferences(application).getString(SP_PUSH_ALIAS, "")
previousAlias = gson.fromJson(aliasInSp, AliasEntity::class.java)
if (previousAlias == null) {
getAndSetAlias()
}
// 完全自定义处理(透传)
pushAgent.setPushIntentServiceClass(GHUmengNotificationService::class.java)
}
private fun registerDevice() {
PushAgent.getInstance(application).register(object : IUmengRegisterCallback {
override fun onSuccess(dToken: String) {
//注册成功会返回device token
deviceToken = dToken
getAndSetAlias()
Utils.log("deviceToken::$dToken")
}
override fun onFailure(s: String, s1: String) {
Utils.log("deviceToken::" + "注册失败")
}
})
}
@JvmStatic
fun getAndSetAlias() {
if (deviceToken.isNullOrEmpty()) {
registerDevice()
return
}
val meta = MetaUtil.getMeta()
val jsonObject = JSONObject()
jsonObject.put("device_token", deviceToken)
jsonObject.put("imei", meta.imei)
jsonObject.put("android_id", meta.android_id)
jsonObject.put("model", meta.model)
jsonObject.put("manufacturer", meta.manufacturer)
jsonObject.put("os", meta.os)
jsonObject.put("os_version", meta.android_version)
jsonObject.put("mac", meta.mac)
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
RetrofitManager.getInstance(application).api.getAlias(body)
.subscribeOn(Schedulers.io())
.subscribe(
{ setAlias(it) },
{ it.printStackTrace() }
)
}
@JvmStatic
fun setAlias(alias: AliasEntity) {
val pushAgent = PushAgent.getInstance(application)
previousAlias = alias
PreferenceManager.getDefaultSharedPreferences(application).edit {
putString(SP_PUSH_ALIAS, gson.toJson(previousAlias))
}
pushAgent.setAlias(alias.alias, alias.aliasType) { b, s ->
Utils.log("注册别名 $b + $s")
}
}
@JvmStatic
fun deleteAlias() {
val pushAgent = PushAgent.getInstance(application)
previousAlias?.let {
pushAgent.deleteAlias(it.alias, it.aliasType) { b, s ->
Utils.log("删除别名 $b + $s")
}
}
PreferenceManager.getDefaultSharedPreferences(application).edit {
putString(SP_PUSH_ALIAS, "")
}
previousAlias = null
}
}

View File

@ -0,0 +1,61 @@
package com.gh.common
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import java.util.concurrent.Executors
/**
* 统计用户在当前 Fragment 的停留时间,在 onViewDestroy 或 onDestroy 里获取 elapsedTime 即可,单位为秒
*/
class TimeElapsedHelper(var fragment: Fragment) {
private var isWorking = false
var elapsedTime: Int = 0
init {
fragment.fragmentManager?.registerFragmentLifecycleCallbacks(
object : FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentResumed(fm: FragmentManager?, f: Fragment?) {
if (f === fragment) {
resumeCounting()
}
}
override fun onFragmentPaused(fm: FragmentManager?, f: Fragment?) {
if (f === fragment) {
pauseCounting()
}
}
override fun onFragmentViewDestroyed(fm: FragmentManager?, f: Fragment?) {
if (f === fragment) {
fragment.fragmentManager?.unregisterFragmentLifecycleCallbacks(this)
}
}
}, false)
}
private fun resumeCounting() {
isWorking = true
TimeElapsedThreadHolder.threadService.execute {
while (isWorking) {
try {
elapsedTime++
Thread.sleep(1000)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
private fun pauseCounting() {
isWorking = false
}
}
object TimeElapsedThreadHolder {
val threadService = Executors.newSingleThreadExecutor()
}

View File

@ -3,39 +3,195 @@ package com.gh.common.constant;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import com.gh.common.util.GsonUtils;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.entity.NewsEntity;
import com.gh.gamecenter.entity.SettingsEntity;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.Utils;
import java.util.List;
public class Config {
public static final String HOST = "http://api2.ghzhushou.com/v2d6/";
public static final String USER_HOST = "http://user2.ghzhushou.com/v1d2/";
public static final String COMMENT_HOST = "http://comment2.ghzhushou.com/v1d2/";
public static final String DATA_HOST = "http://data.ghzhushou.com/";
public static final String LIBAO_HOST = "http://libao2.ghzhushou.com/v1d2/";
public static final String MESSAGE_HOST = "http://message.ghzhushou.com/v1d0/"; // TODO TEST v1d1
public static final String PREFERENCE = "ghzhushou";
public static final String API_HOST = BuildConfig.API_HOST;
public static final String USER_HOST = BuildConfig.USER_HOST;
public static final String COMMENT_HOST = BuildConfig.COMMENT_HOST;
public static final String DATA_HOST = BuildConfig.DATA_HOST;
public static final String LIBAO_HOST = BuildConfig.LIBAO_HOST;
public static final String MESSAGE_HOST = BuildConfig.MESSAGE_HOST;
/**
* 需要配置的请使用{@link PreferenceManager#getDefaultSharedPreferences(Context)}
*/
// @Deprecated
// public static final String PREFERENCE = "ghzhushou";
// Third-Party confs
public static final String WECHAT_APPID = BuildConfig.WECHAT_APPID;
public static final String WECHAT_SECRET = BuildConfig.WECHAT_SECRET;
public static final String TENCENT_APPID = BuildConfig.TENCENT_APPID;
public static final String WEIBO_APPKEY = BuildConfig.WEIBO_APPKEY;
public static final String MIPUSH_APPID = BuildConfig.MIPUSH_APPID;
public static final String MIPUSH_APPKEY = BuildConfig.MIPUSH_APPKEY;
public static final String MTA_APPKEY = BuildConfig.MTA_APPKEY;
public static final String TD_APPID = BuildConfig.TD_APPID;// TalkingData
public static final String TALKINGDATA_APPID = BuildConfig.TD_APPID;// TalkingData
public static final String UMENG_APPKEY = BuildConfig.UMENG_APPKEY;
public static final String UMENG_MESSAGE_SECRET = BuildConfig.UMENG_MESSAGE_SECRET;
public static final String BUGLY_APPID = BuildConfig.BUGLY_APPID;
public static final String PATCH_VERSION_NAME = BuildConfig.PATCH_VERSION_NAME; // 补丁包版本 对应关于->版本号
// http://www.ghzs666.com/article/${articleId}.html
public static final String URL_ARTICLE = "http://www.ghzs666.com/article/"; // TODO ghzs/ghzs666 统一
public static final String PATCHES = "patches";
public static final String DEBUG_MIPUSH_APPID = BuildConfig.DEBUG_MIPUSH_APPID;
public static final String DEBUG_MIPUSH_APPKEY = BuildConfig.DEBUG_MIPUSH_APPKEY;
public static final String DEBUG_UMENG_APPKEY = BuildConfig.DEBUG_UMENG_APPKEY;
public static final String DEBUG_UMENG_MESSAGE_SECRET = BuildConfig.DEBUG_UMENG_MESSAGE_SECRET;
private static String SETTINGS_KEY = "settingsKey";
private static SettingsEntity mSettingsEntity;
public static boolean isShow() {
if (PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication())
.getBoolean("isFixDownload", false)) return true;
if (!isExistDownloadFilter()) return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if ("all".equals(entity.getGame())) {
if (entity.isPluginfy() && "normal".equals(entity.getPolicy()) && filterTime(entity.getTime())) {
return true;
}
}
}
return false;
}
public static String getExceptionMsg(Context context) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
return sp.getString("errMsg", null);
}
public static void setExceptionMsg(Context context, String errMsg) {
PreferenceManager.getDefaultSharedPreferences(context).edit().putString("errMsg", errMsg).apply();
}
public static boolean isShowDownload(String gameId) {
if (PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication())
.getBoolean("isFixDownload", false)) return true;
if (TextUtils.isEmpty(gameId) || !isExistDownloadFilter())
return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if (gameId.equals(entity.getGame())) {
if ("normal".equals(entity.getPolicy()) && filterTime(entity.getTime())) {
return true;
} else {
return false;
}
} else if ("all".equals(entity.getGame())) {
if ("normal".equals(entity.getPolicy()) && filterTime(entity.getTime())) {
return true;
}
}
}
return false;
}
public static boolean isShow(Context context) {
SharedPreferences sp = context.getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE);
return sp.getBoolean("isShow", true);
public static boolean isShowPlugin(String gameId) {
if (TextUtils.isEmpty(gameId) || !isExistDownloadFilter())
return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if (gameId.equals(entity.getGame())) {
if (entity.isPluginfy() && filterTime(entity.getTime())) {
return true;
} else {
return false;
}
} else if ("all".equals(entity.getGame())) {
if (entity.isPluginfy() && filterTime(entity.getTime())) {
return true;
}
}
}
return false;
}
public static boolean isShowPlugin() {
if (!isExistDownloadFilter())
return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if ("all".equals(entity.getGame())) {
if (entity.isPluginfy() && filterTime(entity.getTime())) {
return true;
}
}
}
return false;
}
private static boolean filterTime(SettingsEntity.Download.TimeEntity timeEntity) {
long end = timeEntity.getEnd();
long start = timeEntity.getStart();
long curTime = Utils.getTime(HaloApp.getInstance().getApplication());
if ((start == 0 || curTime >= start) && (end == 0 || curTime <= end)) {
return true;
}
return false;
}
public static void setSettings(SettingsEntity settingsEntity) {
SharedPreferences.Editor edit = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()).edit();
edit.putString(SETTINGS_KEY, GsonUtils.getInstance().toJson(settingsEntity)).apply();
mSettingsEntity = settingsEntity;
}
public static SettingsEntity getSettings() {
if (mSettingsEntity == null) {
try {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
String json = sp.getString(SETTINGS_KEY, null);
if (!TextUtils.isEmpty(json)) {
mSettingsEntity = GsonUtils.getInstance().fromJsonBean(json, SettingsEntity.class);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return mSettingsEntity;
}
private static boolean isExistDownloadFilter() {
if (getSettings() == null || getSettings().getDownload() == null || getSettings().getDownload().size() == 0) {
return false;
} else {
return true;
}
}
public static void filterPluginArticle(List<NewsEntity> list) {
if (isShowPlugin() || list == null) return;
for (int i = 0; i < list.size(); i++) {
NewsEntity newsEntity = list.get(i);
String title = newsEntity.getTitle();
if (!TextUtils.isEmpty(title) && title.contains("插件")) {
list.remove(i);
i--;
}
}
}
}

View File

@ -2,18 +2,22 @@ package com.gh.common.constant;
public class Constants {
public static final int CONTINUE_DOWNLOAD_TASK = 0x123;
public static final int PAUSE_DOWNLOAD_TASK = 0x124;
public static final int DOWNLOAD_ROLL = 0x125;
public static final int SEND_NEWS_FEEDBACK = 0x126;
public static final int SEND_COMMENT_FEEDBACK = 0x127;
public static final String KEY_DOWNLOAD_ENTRY = "key_download_entry";
public static final String KEY_DOWNLOAD_ACTION = "key_download_action";
public final static int LIST_FOOTER_ITEM = 1;
public final static int LIST_HEAD_ITEM = 1;
public static final int MAX_DOWNLOAD_THREAD_SIZE = 3;
public static final int MAX_DOWNLOADING_SIZE = 3;
public static final long SPEED_CHECK_INTERVAL = 1000;//速度监测频率
public final static int NOT_NETWORK_CODE = 504; // 没有网络的状态码(应该是这个吧!)
public static final String LOGIN_TOKEN_ID = "userToken_id"; // 用户ID 与服务器无关
public static final String USER_TOKEN_KEY = "userTokenKey";
public static final String USER_INFO_KEY = "userInfoKey";
// 最近显示的弹窗信息
public static final String SP_LAST_OPENING_ID = "last_opening_dialog_id";
public static final String SP_LAST_OPENING_TIME = "last_opening_dialog_time";
//手机号码匹配规则
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";

View File

@ -8,6 +8,7 @@ public class ItemViewType {
public static final int COLUMN_HEADER = 0; // 专题头部布局
public static final int GAME_SLIDE = 1; // 滚动图布局
public static final int GAME_NORMAL = 2; // 正常游戏布局
public static final int GAME_SUBJECT = 19;
public static final int GAME_TEST = 3; // 测试游戏布局
public static final int GAME_IMAGE = 4; // 游戏大图布局
public static final int NEWS_HEADER = 5; // 新闻头部布局
@ -21,6 +22,17 @@ public class ItemViewType {
public static final int LOADING = 14; // 加载布局
public static final int LIBAO_NORMAL = 15; // 礼包正常布局
public static final int LIBAO_SKIP_CONCERN = 16; // 跳转关注管理页面布局
public static final int KC_HINT = 16;
public static final int KC_HINT = 17;
public static final int GAME_PLUGIN = 18; // 游戏插件模块
public static final int ASK_REFRESH = 19; // 问答精选 刷新
public static final int ITEM_EMPTY = 20;
/**
* 普通列表
*/
public static final int ITEM_BODY = 100;
public static final int ITEM_FOOTER = 101;
public static final int ITEM_TOP = 102;
}

View File

@ -0,0 +1,488 @@
package com.gh.common.databind;
import android.content.Intent;
import android.databinding.BindingAdapter;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.base.OnViewClickListener;
import com.gh.common.constant.Config;
import com.gh.common.exposure.ExposureEvent;
import com.gh.common.exposure.ExposureUtils;
import com.gh.common.util.DataUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.GameUtils;
import com.gh.common.util.GameViewUtils;
import com.gh.common.util.ImageUtils;
import com.gh.common.util.KaiFuUtils;
import com.gh.common.util.NetworkUtils;
import com.gh.common.util.NewsUtils;
import com.gh.common.util.NumberUtils;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.StringUtils;
import com.gh.common.view.DownloadDialog;
import com.gh.common.view.DownloadProgressBar;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R;
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.KaiFuCalendarEntity;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.manager.PackageManager;
import com.lightgame.download.DownloadEntity;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.Utils;
import org.greenrobot.eventbus.EventBus;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
/**
* Created by khy on 12/02/18.
*/
public class BindingAdapters {
@BindingAdapter("imageIcon")
public static void loadIcon(SimpleDraweeView view, String imageUrl) {
ImageUtils.displayIcon(view, imageUrl);
}
@BindingAdapter("imageUrl")
public static void loadImage(SimpleDraweeView view, String imageUrl) {
ImageUtils.display(view, imageUrl);
}
@BindingAdapter({"addDetailKaiFuView", "addDetailKaiFuViewListener", "isReadyPatch"})
public static void addDetailKaiFuView(LinearLayout view, List<KaiFuCalendarEntity> list
, OnViewClickListener listener, Boolean isReadyPatch) {
if (list == null) return;
view.removeAllViews();
for (int i = 0; i < list.size() + 1; i++) { // 1 is Title
View inflate = LayoutInflater.from(view.getContext()).inflate(R.layout.kaifu_detail_item_row, null);
KaifuDetailItemRowBinding binding = KaifuDetailItemRowBinding.bind(inflate);
binding.setIsCloseBottom(i == list.size());
binding.setIsReadyPatch(isReadyPatch);
if (i == 0) {
binding.setIsTitle(true);
} else {
KaiFuCalendarEntity serverEntity = list.get(i - 1);
binding.setEntity(serverEntity);
binding.getRoot().setOnClickListener(v -> {
listener.onClick(v, isReadyPatch != null && isReadyPatch ? serverEntity : null);
});
// 滑动冲突处理
binding.getRoot().setOnTouchListener((v, event) -> {
if (list.size() > 5) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
EventBus.getDefault().post(new EBReuse("CalenderDown"));
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
EventBus.getDefault().post(new EBReuse("CalenderCancel"));
}
}
return false;
});
}
view.addView(inflate);
}
}
// 如果超过10000则转换为1.0W
@BindingAdapter("transSimpleCount")
public static void transSimpleCount(TextView view, int count) {
view.setText(NumberUtils.transSimpleCount(count));
}
@BindingAdapter({"addKaiFuView", "clickListener"})
public static void addKaiFuView(LinearLayout view, List<KaiFuCalendarEntity> list, OnViewClickListener listener) {
if (list == null) return;
view.removeAllViews();
view.addView(LayoutInflater.from(view.getContext()).inflate(R.layout.kaifu_add_item_title, null));
for (int i = 0; i < list.size(); i++) {
View inflate = LayoutInflater.from(view.getContext()).inflate(R.layout.kaifu_add_item, null);
KaifuAddItemBinding binding = KaifuAddItemBinding.bind(inflate);
binding.setClickListener(listener);
binding.setEntity(list.get(i));
binding.setPosition(i);
binding.setIsCloseBottom(list.size() - 1 == i);
view.addView(inflate);
binding.kaifuAddName.setOnFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
binding.kaifuAddName.setHint("");
} else {
binding.kaifuAddName.setHint("点击填写");
}
});
binding.kaifuAddRemark.setOnFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
binding.kaifuAddRemark.setHint("");
} else {
binding.kaifuAddRemark.setHint("点击填写");
}
});
}
}
@BindingAdapter({"addKaiFuTime", "addKaiFuPosition"})
public static void addKaiFuTime(EditText view, Long time, Integer position) {
if (time == 0) {
view.setHint("点击选择");
view.setText("");
} else {
String pattern;
if (position == 0) {
pattern = "yyy-MM-dd HH:mm +";
} else {
pattern = "yyy-MM-dd HH:mm";
}
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.CHINA);
view.setText(format.format(time * 1000));
}
}
@BindingAdapter({"kaiFuTextColor", "kaiFuTextPosition"})
public static void kaiFuTextColor(EditText view, Integer dataMark, Integer position) {
if (dataMark == 1 && view.getId() == R.id.kaifu_add_time
|| dataMark == 2 && view.getId() == R.id.kaifu_add_name
|| dataMark == 3 && view.getId() == R.id.kaifu_add_remark
|| dataMark == 4 && (view.getId() == R.id.kaifu_add_time || view.getId() == R.id.kaifu_add_name)) {
view.setTextColor(ContextCompat.getColor(view.getContext(), R.color.red));
view.setHintTextColor(ContextCompat.getColor(view.getContext(), R.color.red));
} else if (position == 0) {
view.setTextColor(ContextCompat.getColor(view.getContext(), R.color.hint));
view.setHintTextColor(ContextCompat.getColor(view.getContext(), R.color.hint));
} else {
view.setTextColor(ContextCompat.getColor(view.getContext(), R.color.title));
view.setHintTextColor(ContextCompat.getColor(view.getContext(), R.color.hint));
}
}
@BindingAdapter("visibleGone")
public static void showHide(View view, Boolean show) {
if (show != null && show) {
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.GONE);
}
}
@BindingAdapter("messageUnread")
public static void setMessageUnread(TextView view, int unreadCount) {
if (unreadCount < 100) {
view.setText(String.valueOf(unreadCount));
} else {
view.setText("99+");
}
}
@BindingAdapter("serverTypePadding")
public static void setServerTypePadding(TextView view, String serverType) {
int paddRight = 0;
if (TextUtils.isEmpty(serverType)) {
} else {
if ("删档内测".equals(serverType) || "不删档内测".equals(serverType)) {
if ("删档内测".equals(serverType)) {
paddRight = DisplayUtils.dip2px(view.getContext(), 50);
} else {
paddRight = DisplayUtils.dip2px(view.getContext(), 60);
}
} else {
paddRight = DisplayUtils.dip2px(view.getContext(), 30);
}
}
view.setPadding(0, 0, paddRight, 0);
}
@BindingAdapter("serverType")
public static void setServerType(TextView view, String serverType) {
view.setText(serverType);
if ("删档内测".equals(serverType) || "不删档内测".equals(serverType)) {
view.setBackgroundResource(R.drawable.textview_server_tag);
} else {
view.setBackgroundResource(R.drawable.textview_orange_up);
}
}
@BindingAdapter("articleType")
public static void setArticleType(TextView view, String articleType) {
NewsUtils.setNewsType(view, articleType, 0, 0);
}
@BindingAdapter("detailDownloadText")
public static void setDetailDownloadText(TextView view, GameEntity gameEntity) {
if (gameEntity == null || gameEntity.getApk().isEmpty()) {
view.setBackgroundResource(R.drawable.game_item_btn_pause_style);
view.setTextColor(0xFF999999);
view.setClickable(false);
}
}
@BindingAdapter("liBaoBtn")
public static void setLiBaoBtn(TextView view, String status) {
if (TextUtils.isEmpty(status)) return;
switch (status) {
case "coming":
view.setText(R.string.libao_coming);
view.setBackgroundResource(R.drawable.textview_blue_style);
break;
case "ling":
view.setText(R.string.libao_ling);
view.setBackgroundResource(R.drawable.textview_green_style);
break;
case "tao":
view.setText(R.string.libao_tao);
view.setBackgroundResource(R.drawable.textview_orange_style);
break;
case "used_up":
view.setText(R.string.libao_used_up);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "finish":
view.setText(R.string.libao_finish);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "linged":
view.setText(R.string.libao_linged);
view.setBackgroundResource(R.drawable.libao_linged_style);
view.setTextColor(ContextCompat.getColorStateList(view.getContext(), R.color.libao_linged_selector));
break;
case "taoed":
view.setText(R.string.libao_taoed);
view.setBackgroundResource(R.drawable.libao_taoed_style);
view.setTextColor(ContextCompat.getColorStateList(view.getContext(), R.color.libao_taoed_selector));
break;
case "copy":
view.setText(R.string.libao_copy);
view.setBackgroundResource(R.drawable.textview_blue_style);
break;
case "repeatLing":
view.setText(R.string.libao_repeat_ling);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "repeatLinged":
view.setText(R.string.libao_repeat_ling);
view.setBackgroundResource(R.drawable.textview_green_style);
break;
case "repeatTao":
view.setText(R.string.libao_repeat_tao);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "repeatTaoed":
view.setText(R.string.libao_repeat_tao);
view.setBackgroundResource(R.drawable.textview_orange_style);
break;
case "unshelve":
view.setBackgroundResource(R.drawable.textview_cancel_style);
view.setText(R.string.libao_unshelve);
break;
default:
view.setBackgroundResource(R.drawable.textview_cancel_style);
view.setText("异常");
}
}
@BindingAdapter({"downloadButton", "traceEvent"})
public static void setDownloadButton(DownloadProgressBar progressBar, GameEntity gameEntity, ExposureEvent traceEvent) {
// 判断是否显示按钮
if (gameEntity != null
&& Config.isShowDownload(gameEntity.getId())
&& !"光环助手".equals(gameEntity.getName())) {
progressBar.setVisibility(View.VISIBLE);
} else {
progressBar.setVisibility(View.GONE);
return;
}
// 显示下载按钮状态
if (gameEntity.getApk().isEmpty()) {
progressBar.setText("暂无下载");
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
} else {
String status = GameUtils.getDownloadBtnText(progressBar.getContext(), gameEntity);
switch (status) {
case "插件化":
progressBar.setDownloadType(DownloadProgressBar.DownloadType.PLUGIN);
break;
case "打开":
if (gameEntity.getApk().size() == 1) {
status = "启动";
}
progressBar.setDownloadType(DownloadProgressBar.DownloadType.LAUNCH_OR_OPEN);
break;
default:
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NORMAL);
break;
}
progressBar.setText(status);
}
// 显示下载过程状态
if (gameEntity.getApk().size() == 1) {
DownloadEntity downloadEntity = DownloadManager.getInstance(progressBar.getContext()).getDownloadEntityByUrl(gameEntity.getApk().get(0).getUrl());
if (downloadEntity != null) {
progressBar.setProgress((int) (downloadEntity.getPercent() * 10));
switch (downloadEntity.getStatus()) {
case downloading:
case pause:
case timeout:
case neterror:
case waiting:
progressBar.setText(R.string.downloading);
if (downloadEntity.isPluggable() && PackageManager.INSTANCE.isInstalled(downloadEntity.getPackageName())) {
progressBar.setDownloadType(DownloadProgressBar.DownloadType.DOWNLOADING_PLUGIN);
} else {
progressBar.setDownloadType(DownloadProgressBar.DownloadType.DOWNLOADING_NORMAL);
}
break;
case done:
progressBar.setText(R.string.install);
if (downloadEntity.isPluggable()
&& PackageManager.INSTANCE.isInstalled(downloadEntity.getPackageName())) {
progressBar.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_PLUGIN);
} else {
progressBar.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_NORMAL);
}
break;
case cancel:
case hijack:
case notfound:
break;
default:
break;
}
}
}
// 点击事件
progressBar.setOnClickListener(v -> {
switch (progressBar.getDownloadType()) {
case DOWNLOADING_PLUGIN:
case DOWNLOADING_NORMAL:
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(v.getContext(),
gameEntity.getApk().get(0).getUrl(), "(我的光环:我的游戏)");
v.getContext().startActivity(intent);
break;
case NONE:
Utils.toast(v.getContext(), "该游戏已关闭下载");
break;
case NORMAL:
case PLUGIN:
if (gameEntity.getApk().size() == 1) {
if (NetworkUtils.isWifiConnected(v.getContext())) {
download(progressBar, gameEntity, traceEvent);
} else {
DialogUtils.showDownloadDialog(v.getContext(), () -> {
download(progressBar, gameEntity, traceEvent);
});
}
} else {
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
"(我的光环:我的游戏)", "我的光环-我的游戏:" + gameEntity.getName(), traceEvent);
}
break;
case LAUNCH_OR_OPEN:
if (gameEntity.getApk().size() == 1) {
DataUtils.onGameLaunchEvent(v.getContext(), gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), "我的光环-我的游戏");
PackageUtils.launchApplicationByPackageName(v.getContext(), gameEntity.getApk().get(0).getPackageName());
} else {
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
"(我的光环:我的游戏)", "我的光环-我的游戏:" + gameEntity.getName(), traceEvent);
}
break;
case INSTALL_PLUGIN:
case INSTALL_NORMAL:
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());
}
}
}
});
}
// 开始下载
private static void download(DownloadProgressBar progressBar, GameEntity
gameEntity, ExposureEvent traceEvent) {
String str = progressBar.getText();
String method;
if (str.contains("更新")) {
method = "更新";
} else if (str.contains("插件化")) {
method = "插件化";
} else {
method = progressBar.getContext().getString(R.string.download);
}
ApkEntity apkEntity = gameEntity.getApk().get(0);
String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity.getSize());
if (TextUtils.isEmpty(msg)) {
DataUtils.onGameDownloadEvent(progressBar.getContext(), gameEntity.getName(), apkEntity.getPlatform(), "(我的光环:我的游戏)", "下载开始", method);
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, ExposureUtils.DownloadType.DOWNLOAD);
DownloadManager.createDownload(progressBar.getContext(),
apkEntity,
gameEntity,
method,
StringUtils.buildString("(我的光环:我的游戏)"), "我的光环-我的游戏:" + gameEntity.getName(),
downloadExposureEvent);
progressBar.setProgress(0);
progressBar.setDownloadType("插件化".equals(method) ?
DownloadProgressBar.DownloadType.DOWNLOADING_PLUGIN : DownloadProgressBar.DownloadType.DOWNLOADING_NORMAL);
} else {
Utils.toast(progressBar.getContext(), msg);
}
}
@BindingAdapter({"gameLabelList", "subjectTag"})
public static void setGameLabelList(LinearLayout layout, GameEntity gameEntity, String subjectTag) {
if (gameEntity == null) return;
if (gameEntity.getTest() != null) {
layout.removeAllViews();
View testView = LayoutInflater.from(layout.getContext()).inflate(R.layout.game_test_label, null);
TextView testType = testView.findViewById(R.id.test_type);
TextView testTime = testView.findViewById(R.id.test_time);
String type = gameEntity.getTest().getType();
KaiFuUtils.setKaiFuType(testType, type);
if (gameEntity.getTest().getStart() == 0) {
testTime.setVisibility(View.GONE);
} else {
testTime.setText(GameViewUtils.getGameTestDate(gameEntity.getTest().getStart()));
}
layout.addView(testView);
} else {
GameViewUtils.setLabelList(layout.getContext(), layout, gameEntity.getTag(), subjectTag, gameEntity.getTagStyle());
}
}
@BindingAdapter("isRefreshing")
public static void isRefreshing(SwipeRefreshLayout layout, LoadStatus status) {
if (status == LoadStatus.INIT_LOADING) {
layout.setRefreshing(true);
} else {
layout.setRefreshing(false);
}
}
}

View File

@ -0,0 +1,61 @@
package com.gh.common.exposure
import android.arch.persistence.room.TypeConverter
import com.gh.common.exposure.meta.Meta
import com.google.gson.Gson
import java.util.*
import kotlin.collections.ArrayList
class ExposureConverters {
@TypeConverter
fun convertPayload2String(any: ExposureEntity): String {
return Gson().toJson(any)
}
@TypeConverter
fun convertString2Payload(string: String): ExposureEntity {
return Gson().fromJson(string, ExposureEntity::class.java)
}
@TypeConverter
fun convertSource2String(sourceList: List<ExposureSource>): String {
return Gson().toJson(sourceList)
}
@TypeConverter
fun convertString2Source(sourceList: String): List<ExposureSource> {
return ArrayList(Arrays.asList(Gson().fromJson(sourceList, Array<ExposureSource>::class.java))) as List<ExposureSource>
}
@TypeConverter
fun convertETrace2String(sourceList: List<ExposureEvent>?): String {
return Gson().toJson(sourceList)
}
@TypeConverter
fun convertStringToETrace(sourceList: String): List<ExposureEvent> {
return ArrayList(Arrays.asList(Gson().fromJson(sourceList, Array<ExposureEvent>::class.java))) as List<ExposureEvent>
}
@TypeConverter
fun convertExposeType2String(exposureType: ExposureType): String {
return exposureType.toString()
}
@TypeConverter
fun convertStringToExposeType(exposureType: String): ExposureType {
return ExposureType.valueOf(exposureType)
}
@TypeConverter
fun convertMeta2String(any: Meta): String {
return Gson().toJson(any)
}
@TypeConverter
fun convertString2Meta(string: String): Meta {
return Gson().fromJson(string, Meta::class.java)
}
}

View File

@ -0,0 +1,23 @@
package com.gh.common.exposure
import android.arch.persistence.room.Database
import android.arch.persistence.room.Room
import android.arch.persistence.room.RoomDatabase
import android.arch.persistence.room.TypeConverters
import android.content.Context
@TypeConverters(ExposureConverters::class)
@Database(entities = [ExposureEvent::class], version = 1, exportSchema = false)
abstract class ExposureDatabase : RoomDatabase() {
companion object {
private const val DATABASE = "exposure_database"
fun buildDatabase(context: Context): ExposureDatabase {
return Room.databaseBuilder(context, ExposureDatabase::class.java, DATABASE)
.fallbackToDestructiveMigration()
.build()
}
}
abstract fun logHubEventDao(): ExposureEventDao
}

View File

@ -0,0 +1,18 @@
package com.gh.common.exposure
import android.os.Parcelable
import android.support.annotation.Keep
import com.google.gson.annotations.SerializedName
import kotlinx.android.parcel.Parcelize
@Keep
@Parcelize
data class ExposureEntity(
@SerializedName("game_id")
val gameId: String? = "",
val gameName: String? = "",
val sequence: Int? = 0,
val platform: String? = "",
val downloadType: String? = "",
val downloadCompleteType: String? = ""
) : Parcelable

View File

@ -0,0 +1,40 @@
package com.gh.common.exposure
import android.arch.persistence.room.Entity
import android.arch.persistence.room.PrimaryKey
import android.os.Parcelable
import android.support.annotation.Keep
import com.gh.common.exposure.meta.Meta
import com.gh.common.exposure.meta.MetaUtil
import com.gh.common.exposure.time.TimeUtil
import com.gh.gamecenter.entity.GameEntity
import kotlinx.android.parcel.Parcelize
import java.util.*
@Keep
@Parcelize
@Entity(tableName = "exposureEvent")
data class ExposureEvent(
val payload: ExposureEntity,
val source: List<ExposureSource>,
var eTrace: List<ExposureEvent>? = arrayListOf(),
val event: ExposureType,
val meta: Meta = MetaUtil.getMeta(),
val time: Int = TimeUtil.currentTime(),
@PrimaryKey
val id: String = UUID.randomUUID().toString()) : Parcelable {
companion object {
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>?, event: ExposureType): ExposureEvent {
return ExposureEvent(
ExposureEntity(gameId = gameEntity?.id,
gameName = gameEntity?.name,
sequence = gameEntity?.sequence,
platform = gameEntity?.platform,
downloadType = gameEntity?.downloadType,
downloadCompleteType = gameEntity?.downloadCompleteType),
source = source,
eTrace = eTrace,
event = event)
}
}
}

View File

@ -0,0 +1,19 @@
package com.gh.common.exposure
import android.arch.persistence.room.*
@Dao
interface ExposureEventDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertMany(eventList: List<ExposureEvent>)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(event: ExposureEvent)
@Query("SELECT * FROM exposureEvent")
fun getAll(): List<ExposureEvent>
@Delete
fun deleteMany(eventList: List<ExposureEvent>)
}

View File

@ -0,0 +1,70 @@
package com.gh.common.exposure
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import io.reactivex.functions.Consumer
/**
* Exposure Event Listener for RecyclerView
*
* TODO 1. Pull down refresh change in first page without scroll down action
* TODO 2. Item change not triggered by user scroll action (vm data change etc.)
*/
class ExposureListener(var fragment: Fragment, var exposable: IExposable) : RecyclerView.OnScrollListener() {
var throttleBus: ExposureThrottleBus? = null
var layoutManager: LinearLayoutManager? = null
var visibleState: ExposureThrottleBus.VisibleState? = null
init {
fragment.fragmentManager?.registerFragmentLifecycleCallbacks(
object : FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentResumed(fm: FragmentManager?, f: Fragment?) {
throttleBus = ExposureThrottleBus(Consumer { commitExposure(it) }, Consumer(Throwable::printStackTrace))
}
override fun onFragmentPaused(fm: FragmentManager?, f: Fragment?) {
visibleState?.let { commitExposure(it) }
throttleBus?.clear()
}
}, false)
}
/**
* Monitor items in display when scrolling, record those newly displayed as well as
* those newly disappeared. And finally trigger commitExposure().
*/
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
if (layoutManager == null) layoutManager = recyclerView.layoutManager as LinearLayoutManager
layoutManager?.run {
visibleState = ExposureThrottleBus.VisibleState(findFirstCompletelyVisibleItemPosition(), findLastCompletelyVisibleItemPosition())
throttleBus?.postVisibleState(visibleState!!)
}
}
/**
* Check disappearMap items together with according data in displayMap,
* log any items displayed long enough to be called a EXPOSURE
*/
private fun commitExposure(visibleState: ExposureThrottleBus.VisibleState) {
val eventList = arrayListOf<ExposureEvent>()
for (pos in visibleState.firstCompletelyVisible..visibleState.lastCompletelyVisible) {
try {
exposable.getEventByPosition(pos)?.let { eventList.add(it) }
exposable.getEventListByPosition(pos)?.let { eventList.addAll(it) }
} catch (e: Exception) {
e.printStackTrace()
}
}
ExposureManager.log(eventList)
}
}

View File

@ -0,0 +1,200 @@
package com.gh.common.exposure
import android.app.Application
import com.aliyun.sls.android.sdk.LogException
import com.aliyun.sls.android.sdk.model.LogGroup
import com.gh.common.exposure.aliyun.LGLOG
import com.gh.common.exposure.aliyun.LGLOGClient
import com.gh.common.exposure.meta.MetaUtil
import com.gh.common.exposure.time.TimeUtil
import com.gh.gamecenter.BuildConfig
import com.google.gson.Gson
import java.util.concurrent.Executors
import kotlin.concurrent.fixedRateTimer
/**
* ExposureManager tool to commit logs to aliyun loghub
* TODO handle logs that failed to be committed multiple times
*/
object ExposureManager {
private var TAG: String = ExposureManager::class.java.simpleName
private const val ACCESS_KEY_ID = "LTAIV3i0sNc4TPK1"
private const val ACCESS_KEY_SECRET = "8dKtTPeE5WYA6ZCeuIBcIVp7eB0ir4"
private const val ENDPOINT = "cn-qingdao.log.aliyuncs.com"
private const val PROJECT = "ghzs"
private const val STORE_SIZE = 100
private const val STORE_FORCE_UPLOAD_PERIOD = 300 * 1000L
private var LOG_STORE = BuildConfig.EXPOSURE_REPO
private lateinit var client: LGLOGClient
private lateinit var db: ExposureEventDao
private val storeSet = hashSetOf<ExposureEvent>()
private val storeOpThread = Executors.newSingleThreadExecutor()
private val gson = Gson()
private val exposureCache = FixedSizeLinkedHashSet<String>(20)
/**
* Must be called early to init object then real use (for example in Application)
*/
fun init(application: Application) {
client = LGLOGClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET, PROJECT)
db = ExposureDatabase.buildDatabase(application).logHubEventDao()
storeOpThread.execute {
val eventList = db.getAll()
storeSet.addAll(eventList)
}
fixedRateTimer(name = "ExposureManager-Store-Checker", initialDelay = 500, period = STORE_FORCE_UPLOAD_PERIOD) {
checkAndUploadFromDatabase(true)
}
MetaUtil.init(application)
TimeUtil.init()
}
/**
* Log an Event
*/
fun log(event: ExposureEvent, uploadImmediately: Boolean = false) {
when (uploadImmediately) {
false -> store(event)
true -> upload(event)
}
}
/**
* Log Many Events
*/
fun log(eventList: List<ExposureEvent>, uploadImmediately: Boolean = false) {
when (uploadImmediately) {
false -> store(eventList)
true -> upload(eventList)
}
}
/**
* Store an Event to storeSet, upload when storeSet size exceeds STORE_SIZE
*/
private fun store(event: ExposureEvent) {
storeOpThread.execute {
if (!exposureCache.contains(event.id)) {
storeSet.add(event)
db.insert(event)
exposureCache.add(event.id)
}
checkAndUploadFromDatabase()
}
}
/**
* Store Many Events to storeSet, upload when storeSet size exceeds STORE_SIZE
*/
private fun store(eventList: List<ExposureEvent>) {
storeOpThread.execute {
for (event in eventList) {
if (!exposureCache.contains(event.id)) {
storeSet.add(event)
db.insert(event)
exposureCache.add(event.id)
}
}
}
}
/**
* Upload an Event
*/
private fun upload(event: ExposureEvent) {
storeOpThread.execute {
client.PostLog(buildLogGroup(event), LOG_STORE)
}
}
/**
* Upload Many Events
*/
private fun upload(eventList: List<ExposureEvent>) {
storeOpThread.execute {
client.PostLog(buildLogGroup(eventList), LOG_STORE)
}
}
/**
* Upload Events From Store, and removed them
*/
private fun checkAndUploadFromDatabase(isForceUpload: Boolean = false) {
storeOpThread.execute {
if (storeSet.size < STORE_SIZE && !isForceUpload || storeSet.size == 0) return@execute
val uploaded = storeSet.toList()
try {
client.PostLog(buildLogGroup(uploaded), LOG_STORE)
} catch (exception: LogException) {
// Return to insure no logs lost because of online commit failure
return@execute
}
storeSet.removeAll(uploaded)
db.deleteMany(uploaded)
}
}
private fun buildLog(event: ExposureEvent): LGLOG {
val log = LGLOG()
log.PutContent("id", event.id)
log.PutContent("payload", gson.toJson(event.payload))
log.PutContent("event", event.event.toString())
log.PutContent("source", eliminateMultipleBrackets(gson.toJson(event.source)))
log.PutContent("meta", gson.toJson(event.meta))
log.PutContent("e-traces", if (event.eTrace != null) eliminateMultipleBrackets(gson.toJson(event.eTrace)) else "")
log.PutTime(event.time)
return log
}
private fun eliminateMultipleBrackets(jsonWithMultipleBracket: String): String {
return jsonWithMultipleBracket.replace("[[", "[").replace("]]", "]")
}
private fun buildLogGroup(event: ExposureEvent): LogGroup {
val logGroup = LogGroup("sls android", "no ip")
logGroup.PutLog(buildLog(event))
return logGroup
}
private fun buildLogGroup(eventList: List<ExposureEvent>): LogGroup {
val logGroup = LogGroup("sls android", "no ip")
eventList.forEach { event ->
logGroup.PutLog(buildLog(event))
}
return logGroup
}
internal class FixedSizeLinkedHashSet<T>(var maxSize: Int) : LinkedHashSet<T>() {
override fun add(element: T): Boolean {
if (size == maxSize) {
pop()
}
return super.add(element);
}
private fun pop() {
if (size > 0) {
remove(iterator().next())
}
}
}
}

View File

@ -0,0 +1,9 @@
package com.gh.common.exposure
import android.os.Parcelable
import android.support.annotation.Keep
import kotlinx.android.parcel.Parcelize
@Keep
@Parcelize
data class ExposureSource(var k: String, var v: String): Parcelable

View File

@ -0,0 +1,59 @@
package com.gh.common.exposure
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import java.util.concurrent.TimeUnit
class ExposureThrottleBus(var onSuccess: Consumer<VisibleState>, var onError: Consumer<Throwable>) {
companion object {
private const val THRESHOLD_TIME = 300L
}
private val mPublishSubject: PublishSubject<VisibleState> = PublishSubject.create()
private val mCompositeDisposable: CompositeDisposable = CompositeDisposable()
init {
/**
* Since onScroll() callback will be triggered multiple times for every swipe, we use
* distinctUntilChanged() to prevent committing the same visibleState event and
* throttleWithTimeout() to pass a visibleState event with a delay and drop current event if another event arrives before the timeout.
*/
val disposable = mPublishSubject
.distinctUntilChanged()
.throttleWithTimeout(THRESHOLD_TIME, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.subscribe(onSuccess, onError)
mCompositeDisposable.add(disposable)
}
fun clear() {
mCompositeDisposable.clear()
}
fun postVisibleState(visibleState: VisibleState) {
mPublishSubject.onNext(visibleState)
}
class VisibleState(val firstCompletelyVisible: Int, val lastCompletelyVisible: Int) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || javaClass != other.javaClass) return false
val that = other as VisibleState
if (firstCompletelyVisible != that.firstCompletelyVisible) return false
return lastCompletelyVisible == that.lastCompletelyVisible
}
override fun hashCode(): Int {
var result = firstCompletelyVisible
result = 31 * result + lastCompletelyVisible
return result
}
}
}

View File

@ -0,0 +1,25 @@
package com.gh.common.exposure
object ExposureTraceUtils {
fun appendTrace(event: ExposureEvent?): List<ExposureEvent> {
val traceList = arrayListOf<ExposureEvent>()
event?.let {
if (event.eTrace == null) {
traceList.add(event)
} else {
traceList.addAll(event.eTrace!!)
traceList.add(flattenTrace(event))
}
}
return traceList
}
private fun flattenTrace(event: ExposureEvent): ExposureEvent {
event.eTrace = arrayListOf()
return event
}
}

View File

@ -0,0 +1,11 @@
package com.gh.common.exposure
enum class ExposureType {
EXPOSURE,
CLICK,
DOWNLOAD,
DOWNLOAD_COMPLETE
}

View File

@ -0,0 +1,46 @@
package com.gh.common.exposure
import com.gh.gamecenter.entity.GameEntity
import com.google.gson.Gson
import java.util.*
object ExposureUtils {
val gson = Gson()
@JvmStatic
fun logADownloadExposureEvent(entity: GameEntity, platform: String?, traceEvent: ExposureEvent?, downloadType: DownloadType): ExposureEvent {
val gameEntity = entity.clone()
gameEntity.platform = platform
gameEntity.downloadType = downloadType.toString()
val exposureEvent = ExposureEvent.createEvent(gameEntity = gameEntity,
source = traceEvent?.source ?: ArrayList(),
eTrace = ExposureTraceUtils.appendTrace(traceEvent),
event = ExposureType.DOWNLOAD)
ExposureManager.log(exposureEvent, false)
return exposureEvent
}
@JvmStatic
fun logADownloadCompleteExposureEvent(entity: GameEntity, platform: String?, trace: String?, downloadType: DownloadType) {
val gameEntity = entity.clone()
gameEntity.platform = platform
gameEntity.downloadCompleteType = downloadType.toString()
val traceEvent = gson.fromJson(trace, ExposureEvent::class.java)
val exposureEvent = ExposureEvent.createEvent(gameEntity = gameEntity,
source = traceEvent?.source ?: ArrayList(),
eTrace = ExposureTraceUtils.appendTrace(traceEvent),
event = ExposureType.DOWNLOAD_COMPLETE)
ExposureManager.log(exposureEvent, false)
}
enum class DownloadType {
DOWNLOAD,
UPDATE,
PLUGIN_UPDATE,
PLUGIN_DOWNLOAD
}
}

View File

@ -0,0 +1,7 @@
package com.gh.common.exposure
interface IExposable {
fun getEventByPosition(pos: Int): ExposureEvent?
fun getEventListByPosition(pos: Int): List<ExposureEvent>?
}

View File

@ -0,0 +1,42 @@
package com.gh.common.exposure.aliyun;
import com.aliyun.sls.android.sdk.model.Log;
import com.gh.common.exposure.time.TimeUtil;
import java.util.HashMap;
import java.util.Map;
/**
* Extend to change __time__ field in mContent to use the correct time from TimeUtil
*/
public class LGLOG extends Log {
private Map<String, Object> mContent = new HashMap<String, Object>();
public LGLOG() {
mContent.put("__time__", TimeUtil.INSTANCE.currentTime());
}
@Override
public void PutTime(int time) {
mContent.put("__time__", time);
}
@Override
public void PutContent(String key, String value) {
if (key == null || key.isEmpty()) {
return;
}
if (value == null) {
mContent.put(key, "");
} else {
mContent.put(key, value);
}
}
@Override
public Map<String, Object> GetContent() {
return mContent;
}
}

View File

@ -0,0 +1,67 @@
package com.gh.common.exposure.aliyun;
import com.aliyun.sls.android.sdk.LOGClient;
import com.aliyun.sls.android.sdk.LogException;
import com.gh.common.exposure.time.TimeUtil;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
/**
* Extend to override GetHttpHeadersFrom, so we can change "Date" header attribute using
* correct time from TimeUtil.
* And accordingly, the value of "Authorization" attribute should also be re-calculate
* since the sign became different as before.
*/
public class LGLOGClient extends LOGClient {
private String mAccessKeyID;
private String mAccessKeySecret;
private String mAccessToken;
public LGLOGClient(String endPoint, String accessKeyID, String accessKeySecret, String projectName) {
super(endPoint, accessKeyID, accessKeySecret, projectName);
this.mAccessKeyID = accessKeyID;
this.mAccessKeySecret = accessKeySecret;
this.mAccessToken = "";
}
@Override
public Map<String, String> GetHttpHeadersFrom(String logStoreName, byte[] body, byte[] bodyZipped) throws LogException {
Map<String, String> headers = super.GetHttpHeadersFrom(logStoreName, body, bodyZipped);
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("GMT")); // 设置时区为GMT
String str = sdf.format(new Date(TimeUtil.INSTANCE.currentTimeMillis()));
headers.put("Date", str);
StringBuilder signStringBuf = new StringBuilder("POST" + "\n").
append(headers.get("Content-MD5") + "\n").
append(headers.get("Content-Type") + "\n").
append(headers.get("Date") + "\n");
String token = mAccessToken;
if (token != null && token != "") {
headers.put("x-acs-security-token", token);
signStringBuf.append("x-acs-security-token:" + headers.get("x-acs-security-token") + "\n");
}
signStringBuf.append("x-log-apiversion:0.6.0\n").
append("x-log-bodyrawsize:" + headers.get("x-log-bodyrawsize") + "\n").
append("x-log-compresstype:deflate\n").
append("x-log-signaturemethod:hmac-sha1\n").
append("/logstores/" + logStoreName + "/shards/lb");
String signString = signStringBuf.toString();
try {
String sign = hmac_sha1(signString, mAccessKeySecret);
headers.put("Authorization", "LOG " + mAccessKeyID + ":" + sign);
} catch (Exception e) {
throw new LogException("LogClientError", "fail to get encode signature", e, "");
}
return headers;
}
}

View File

@ -0,0 +1,24 @@
package com.gh.common.exposure.meta
import android.os.Parcelable
import android.support.annotation.Keep
import kotlinx.android.parcel.Parcelize
@Keep
@Parcelize
data class Meta(
val mac: String? = "",
val imei: String? = "",
val model: String? = "",
val manufacturer: String? = "",
val android_id: String? = "",
val android_sdk: Int? = -1,
val android_version: String? = "",
val network: String? = "",
val ip: String? = "",
val os: String? = "",
val channel: String? = "",
val appVersion: String? = "",
val userId: String? = "",
val exposureVersion: String? = ""
) : Parcelable

View File

@ -0,0 +1,170 @@
package com.gh.common.exposure.meta
import android.Manifest
import android.app.Application
import android.content.Context
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.wifi.WifiManager
import android.os.Build
import android.provider.Settings
import android.telephony.TelephonyManager
import android.text.TextUtils
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.manager.UserManager
import com.leon.channel.helper.ChannelReaderUtil
import java.io.File
object MetaUtil {
private lateinit var application: Application
private var channel = ""
private var m: Meta? = null
fun init(application: Application) {
MetaUtil.application = application
}
fun refreshMeta() {
m = Meta(getMac(), getIMEI(), getModel(), getManufacturer(), getAndroidId(), getAndroidSDK(),
getAndroidVersion(), getNetwork(), getIP(), getOS(), getChannel(), BuildConfig.VERSION_NAME, UserManager.getInstance().userId, BuildConfig.EXPOSURE_VERSION)
}
fun getMeta(): Meta {
if (m == null) {
refreshMeta()
}
return m!!
}
private fun getChannel(): String? {
if (TextUtils.isEmpty(channel)) {
channel = if (ChannelReaderUtil.getChannel(application) != null) ChannelReaderUtil.getChannel(application) else ""
}
return channel
}
/**
* Get MAC address
* TODO check > 6.0 results
*/
fun getMac(): String? {
var mac: String = ""
//Plan A
try {
mac = File("/sys/class/net/wlan0/address").inputStream().bufferedReader().use { it.readText() }
if (!TextUtils.isEmpty(mac)) return mac.trim()
} catch (e: Exception) {
// e.printStackTrace()
}
// Plan B
try {
mac = File("/sys/class/net/eth0/address").inputStream().bufferedReader().use { it.readText() }
if (!TextUtils.isEmpty(mac)) return mac.trim()
} catch (e: Exception) {
// e.printStackTrace()
}
// Plan C
val wifiManager = application.getSystemService(Context.WIFI_SERVICE) as WifiManager
try {
mac = wifiManager.connectionInfo.macAddress
} catch (e: Exception) {
// e.printStackTrace()
}
return mac.trim()
}
/**
* Get IMEI
*/
fun getIMEI(): String? {
if (application.checkCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED)
return ""
val telephonyManager = application.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
if (Build.VERSION.SDK_INT >= 26) {
return telephonyManager.imei
}
return telephonyManager.getDeviceId()
}
fun getModel(): String? {
return Build.MODEL
}
fun getManufacturer(): String? {
return Build.MANUFACTURER
}
fun getAndroidId(): String? {
var android_id: String = ""
try {
android_id = Settings.Secure.getString(application.contentResolver, Settings.Secure.ANDROID_ID)
} catch (e: Exception) {
e.printStackTrace()
}
return android_id
}
fun getAndroidSDK(): Int? {
return Build.VERSION.SDK_INT
}
fun getAndroidVersion(): String? {
return Build.VERSION.RELEASE
}
fun getNetwork(): String? {
if (application.checkCallingOrSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)
return "unknown"
val activeNetwork = (application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
?: return "unknown"
return when (activeNetwork.type) {
ConnectivityManager.TYPE_WIFI -> "Wifi"
ConnectivityManager.TYPE_WIMAX -> "WifiMax"
ConnectivityManager.TYPE_MOBILE -> {
val telephonyManager = application.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
if (telephonyManager.simState != TelephonyManager.SIM_STATE_READY) return "unknown"
when (telephonyManager.networkType) {
// Unknown
TelephonyManager.NETWORK_TYPE_UNKNOWN -> "Cellular - Unknown"
// Cellular Data2G
TelephonyManager.NETWORK_TYPE_EDGE, TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_CDMA,
TelephonyManager.NETWORK_TYPE_IDEN, TelephonyManager.NETWORK_TYPE_1xRTT -> "Cellular - 2G"
// Cellular Data3G
TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_HSDPA, TelephonyManager.NETWORK_TYPE_HSPA,
TelephonyManager.NETWORK_TYPE_HSPAP, TelephonyManager.NETWORK_TYPE_HSUPA, TelephonyManager.NETWORK_TYPE_EVDO_0,
TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_EVDO_B -> "Cellular - 3G"
// Cellular Data4G
TelephonyManager.NETWORK_TYPE_LTE -> "Cellular - 4G"
else -> "Cellular - Unknown Generation"
}
}
else -> "unknown"
}
}
fun getIP(): String {
return "unknown"
}
fun getOS(): String {
return "android"
}
}

View File

@ -0,0 +1,27 @@
package com.gh.common.exposure.time
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
import kotlin.concurrent.fixedRateTimer
class Corrector {
companion object {
const val TIME_CORRECTOR_ADJUST_PERIOD: Long = 600000
}
var delta: Long = 0
init {
fixedRateTimer("TimeUtil-Corrector-Checker", initialDelay = 0, period = TIME_CORRECTOR_ADJUST_PERIOD) {
RetrofitManager.getInstance(HaloApp.getInstance().application).api.time
.subscribeOn(Schedulers.io())
.subscribe({
val serverTime = java.lang.Long.parseLong(it.string())
delta = serverTime * 1000 - System.currentTimeMillis()
}, Throwable::printStackTrace)
}
}
}

View File

@ -0,0 +1,22 @@
package com.gh.common.exposure.time
object TimeUtil {
private lateinit var corrector: Corrector
fun currentTimeMillis(): Long {
return corrector.delta + System.currentTimeMillis()
}
fun currentTime(): Int {
return ( ( corrector.delta + System.currentTimeMillis() ) / 1000 ).toInt()
}
/**
* Must be called early then real use (for example in Application)
*/
fun init() {
corrector = Corrector()
}
}

View File

@ -0,0 +1,67 @@
package com.gh.common.im
import android.app.Activity
import android.support.v4.view.ViewCompat
import android.view.View
import android.view.ViewGroup
object ImHintHelper {
@JvmStatic
fun show(activity: Activity?) {
activity?.let {
var hintView = retrieveHintViewFromActivity(it)
if (hintView == null) {
hintView = ImHintView(it)
hintView.showDot(ImManager.shouldShowFloatingWindowDot)
val decorView = it.window.decorView as ViewGroup
it.runOnUiThread {
decorView.addView(hintView)
}
} else {
hintView.showDot(ImManager.shouldShowFloatingWindowDot)
}
}
}
@JvmStatic
fun dismiss(activity: Activity?) {
activity?.let {
clearCurrent(it)
}
}
private fun retrieveHintViewFromActivity(activity: Activity?) : ImHintView? {
(activity?.window?.decorView as? ViewGroup)?.let {
for (i in 0..it.childCount) {
val childView = if (it.getChildAt(i) is ImHintView) it.getChildAt(i) as ImHintView else null
if (childView != null && childView.windowToken != null) {
return childView
}
}
return null
}
return null
}
private fun clearCurrent(activity: Activity?) {
(activity?.window?.decorView as? ViewGroup)?.let {
for (i in 0..it.childCount) {
val childView = if (it.getChildAt(i) is ImHintView) it.getChildAt(i) as ImHintView else null
if (childView != null && childView.windowToken != null) {
ViewCompat.animate(childView).alpha(0f).withEndAction(getRemoveViewRunnable(childView))
}
}
}
}
private fun getRemoveViewRunnable(childView: View?): Runnable {
return Runnable {
childView?.let {
(childView.parent as? ViewGroup)?.removeView(childView)
}
}
}
}

View File

@ -0,0 +1,84 @@
package com.gh.common.im
import android.app.Activity
import android.content.Context
import android.os.Build
import android.support.v4.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 com.gh.gamecenter.R
import kotlinx.android.synthetic.main.view_im_hint.view.*
class ImHintView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
: RelativeLayout(context, attrs, defStyle) {
init {
inflate(context, R.layout.view_im_hint, this)
ViewCompat.setTranslationZ(this, Integer.MAX_VALUE.toFloat() - 1)
ivContainer.setOnClickListener {
if (context is Activity) {
ImManager.startChatActivity(context)
ImManager.removeNotification()
}
}
val lp = ivContainer.layoutParams as RelativeLayout.LayoutParams
lp.setMargins(0, 0, dp2px(30f), dp2px(106f) + retrieveNavigationHeight())
}
fun showDot(show: Boolean) {
if (show) {
unreadDot.visibility = View.VISIBLE
} else {
unreadDot.visibility = View.GONE
}
}
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

@ -0,0 +1,146 @@
package com.gh.common.im
import android.app.Activity
import android.app.NotificationManager
import android.content.Context
import com.gh.base.CurrentActivityHolder
import com.gh.common.util.SPUtils
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
import com.moor.imkf.ChatListener
import com.moor.imkf.IMChat
import com.moor.imkf.IMChatManager
import com.moor.imkf.IMMessage
object ImManager {
const val IM_KEY = "893be270-9c75-11e8-a344-212975ba32b9"
const val SP_FLOATING_WINDOW_KEY = "IM_FLOATING_WINDOW"
const val SP_FLOATING_WINDOW_DOT_KEY = "IM_FLOATING_WINDOW_DOT"
var shouldShowFloatingWindow = false
var shouldShowFloatingWindowDot = false
@JvmStatic
fun attachIm() {
try {
if (UserManager.getInstance().userInfoEntity != null) {
IMChatManager.getInstance().init(
HaloApp.getInstance().application,
ImReceiver.UNIQUE_BROADCAST_ACTION,
IM_KEY,
UserManager.getInstance().userInfoEntity.name + "(" + UserManager.getInstance().userId + ")",
UserManager.getInstance().userId)
shouldShowFloatingWindow = SPUtils.getBoolean(SP_FLOATING_WINDOW_KEY + UserManager.getInstance().userId)
shouldShowFloatingWindowDot = SPUtils.getBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId)
updateFloatingWindow()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
@JvmStatic
fun detachIm() {
try {
IMChatManager.getInstance().quitSDk()
shouldShowFloatingWindow = false
updateFloatingWindow()
removeNotification()
} catch (e: Exception) {
e.printStackTrace()
}
}
@JvmStatic
fun startChatActivity(activity: Activity) {
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)
chatHelper.initSdkChat(
ImReceiver.UNIQUE_BROADCAST_ACTION,
IM_KEY,
UserManager.getInstance().userInfoEntity.name + "(" + UserManager.getInstance().userId + ")",
UserManager.getInstance().userId)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
@JvmStatic
fun showFloatingWindow() {
updateShouldShowFloatingWindow(true)
updateShouldShowFloatingWindowDot(true)
updateFloatingWindow()
}
@JvmStatic
fun dismissFloatingWindow() {
updateShouldShowFloatingWindow(false)
updateShouldShowFloatingWindowDot(false)
updateFloatingWindow()
}
@JvmStatic
fun removeNotification() {
val notificationManager = HaloApp.getInstance().application?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancel(ImReceiver.NOTIFICATION_ID)
}
@JvmStatic
fun updateFloatingWindow() {
try {
CurrentActivityHolder.getCurrentActivity()?.let {
if (isActivityValid(it)) {
if (shouldShowFloatingWindow) {
ImHintHelper.show(it)
} else {
ImHintHelper.dismiss(it)
removeNotification()
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
@JvmStatic
fun sendFeedbackMessage(message: String) {
val fromToMessage = IMMessage.createTxtMessage(message)
HaloApp.getInstance().mainExecutor.execute {
IMChat.getInstance().sendMessage(fromToMessage, object : ChatListener {
override fun onProgress(p0: Int) {}
override fun onSuccess() {}
override fun onFailed() {}
})
}
}
fun updateShouldShowFloatingWindow(show: Boolean) {
SPUtils.setBoolean(SP_FLOATING_WINDOW_KEY + UserManager.getInstance().userId, show)
shouldShowFloatingWindow = show
}
fun updateShouldShowFloatingWindowDot(show: Boolean) {
SPUtils.setBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId, show)
shouldShowFloatingWindowDot = show
}
private fun isActivityValid(activity: Activity): Boolean {
return when (activity) {
is MainActivity -> true
is SuggestSelectActivity -> true
is MessageActivity -> true
else -> false
}
}
}

View File

@ -0,0 +1,76 @@
package com.gh.common.im
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.support.v4.app.NotificationCompat
import com.gh.base.CurrentActivityHolder
import com.gh.gamecenter.R
import com.m7.imkfsdk.chat.ChatActivity
import com.moor.imkf.IMChatManager
import com.moor.imkf.utils.Utils
class ImReceiver : BroadcastReceiver() {
companion object {
const val UNIQUE_BROADCAST_ACTION = "com.gh.im"
const val NOTIFICATION_ID: Int = 987321
}
var notificationManager: NotificationManager? = null
override fun onReceive(context: Context?, intent: Intent?) {
intent?.let {
if (intent.action == IMChatManager.NEW_MSG_ACTION) {
notificationManager = context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// 判断 ImActivity 是否在最顶端
if (CurrentActivityHolder.getCurrentActivity() is ChatActivity) {
ImManager.showFloatingWindow()
ImManager.updateShouldShowFloatingWindowDot(false)
} else {
val contentIntent = Intent(Utils.getApp(), ChatActivity::class.java)
contentIntent.putExtra("PeerId", "")
contentIntent.putExtra("type", "peedId")
contentIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
val resultPendingIntent = PendingIntent.getActivity(
Utils.getApp(),
0,
contentIntent,
PendingIntent.FLAG_UPDATE_CURRENT
)
// 新的通知
val builder = NotificationCompat.Builder(Utils.getApp(), "Halo_IM")
val notification = builder.setTicker("您有新的消息")
.setDefaults(Notification.DEFAULT_ALL)
.setSmallIcon(R.drawable.ic_notification)
.setWhen(System.currentTimeMillis())
.setContentIntent(resultPendingIntent)
.setContentTitle("光环助手客服回复")
.setContentText("您有新的消息")
.setAutoCancel(true)
.build()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel("Halo_IM", "Halo_IM", NotificationManager.IMPORTANCE_DEFAULT)
notificationManager?.createNotificationChannel(channel)
}
if (notification != null) {
notificationManager?.notify(NOTIFICATION_ID, notification)
ImManager.showFloatingWindow()
}
}
} else if (intent.action == IMChatManager.FINISH_ACTION) {
ImManager.dismissFloatingWindow()
}
}
}
}

View File

@ -0,0 +1,170 @@
package com.gh.common.notifier
import android.app.Activity
import android.support.v4.view.ViewCompat
import android.view.View
import android.view.ViewGroup
import com.gh.common.util.SPUtils
import com.gh.gamecenter.*
import java.lang.ref.WeakReference
@Suppress("DEPRECATION")
class Notifier private constructor() {
companion object {
private var activityWeakReference: WeakReference<Activity>? = null
private const val SP_VIEWED_NOTIFIER = "viewed_notifier"
/**
* 根据内容决定是否显示 Notifier
*/
@JvmStatic
fun shouldShowNotifier(content: String): Boolean {
val viewedNotifierCollection = SPUtils.getString(SP_VIEWED_NOTIFIER)
return !viewedNotifierCollection.contains(content)
}
/**
* 标记相应内容的 Notifier 已经显示过了
*/
@JvmStatic
fun tagNotifierAsShowed(content: String) {
val viewedNotifierCollection = SPUtils.getString(SP_VIEWED_NOTIFIER)
if (viewedNotifierCollection.length > 1000) {
SPUtils.setString(SP_VIEWED_NOTIFIER, content)
} else {
SPUtils.setString(SP_VIEWED_NOTIFIER, viewedNotifierCollection + content)
}
}
@JvmStatic
fun create(activity: Activity?): Notifier {
if (activity == null) {
throw IllegalArgumentException("Activity cannot be null!")
}
val notifier = Notifier()
// Hide current NotifierView, if one is active
clearCurrent(activity)
notifier.setActivity(activity)
notifier.notifierView = NotifierView(activity)
return notifier
}
@JvmStatic
fun isActivityValid(activity: Activity?): Boolean {
if (activity == null) return false
return when (activity) {
is MessageActivity -> false
is DownloadManagerActivity -> false
is CleanApkActivity -> false
is SplashScreenActivity -> false
else -> isNotExistInActivity(activity)
}
}
@JvmStatic
fun isNotExistInActivity(activity: Activity?): Boolean {
if (activity == null) return false
(activity.window?.decorView as? ViewGroup)?.let {
//Find all NotifierView Views in Parent layout
for (i in 0..it.childCount) {
val childView = if (it.getChildAt(i) is NotifierView) it.getChildAt(i) as NotifierView else null
if (childView != null && childView.windowToken != null) {
return false
}
}
}
return true
}
/**
* Cleans up the currently showing notifierView view, if one is present
*
* @param activity The current Activity
*/
@JvmStatic
fun clearCurrent(activity: Activity?) {
(activity?.window?.decorView as? ViewGroup)?.let {
//Find all NotifierView Views in Parent layout
for (i in 0..it.childCount) {
val childView = if (it.getChildAt(i) is NotifierView) it.getChildAt(i) as NotifierView else null
if (childView != null && childView.windowToken != null) {
ViewCompat.animate(childView).alpha(0f).withEndAction(getRemoveViewRunnable(childView))
}
}
}
}
@JvmStatic
fun hide() {
activityWeakReference?.get()?.let { clearCurrent(it) }
}
private fun getRemoveViewRunnable(childView: NotifierView?): Runnable {
return Runnable {
childView?.let {
(childView.parent as? ViewGroup)?.removeView(childView)
}
}
}
}
private var notifierView: NotifierView? = null
private val activityDecorView: ViewGroup?
get() {
var decorView: ViewGroup? = null
activityWeakReference?.get()?.let {
decorView = it.window.decorView as ViewGroup
}
return decorView
}
fun show(showVerticalTranslateAnimation: Boolean, delay: Long? = 0): NotifierView? {
activityWeakReference?.get()?.let {
it.runOnUiThread {
activityDecorView?.postDelayed({
notifierView?.showVerticalTranslateAnimation = showVerticalTranslateAnimation
activityDecorView?.addView(notifierView)
}, delay!!)
}
}
return notifierView
}
fun setIcon(url: String?): Notifier {
url?.let { notifierView?.setIcon(it) }
return this
}
fun setText(text: String?): Notifier {
notifierView?.setText(text)
return this
}
fun setDuration(time: Long): Notifier {
notifierView?.duration = time
return this
}
fun setOnClickListener(onClickListener: View.OnClickListener): Notifier {
notifierView?.findViewById<View>(R.id.cardView)?.setOnClickListener(onClickListener)
return this
}
private fun setActivity(activity: Activity) {
activityWeakReference = WeakReference(activity)
}
}

View File

@ -0,0 +1,332 @@
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.support.v4.view.ViewCompat
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.widget.FrameLayout
import com.gh.common.util.ImageUtils
import com.gh.common.util.doOnEnd
import com.gh.common.util.doOnStart
import com.gh.gamecenter.R
import kotlinx.android.synthetic.main.view_notifier.view.*
class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
: FrameLayout(context, attrs, defStyle) {
companion object {
const val SCALE_MINI = 0.2F
const val SCALE_DEFAULT = 1F
const val DEFAULT_DURATION = 500L
}
var onShowListener: OnShowNotificationListener? = null
var onHideListener: OnHideNotificationListener? = null
lateinit var expandAnimator: ValueAnimator
lateinit var shrinkAnimator: ValueAnimator
lateinit var translateUpAnimator: ObjectAnimator
lateinit var translateDownAnimator: ObjectAnimator
lateinit var translateToLeftAnimator: ObjectAnimator
lateinit var translateToRightAnimator: ObjectAnimator
lateinit var zoomInAnimator: ObjectAnimator
lateinit var zoomOutAnimator: ObjectAnimator
var showAnimatorSet: AnimatorSet
var hideAnimatorSet: AnimatorSet
var rightToLeftPath: Path
var leftToRightPath: Path
var veryRight: Float = 0F
var veryBottom: Float = 0F
var centerX: Float = 0F
var navigationHeight = 0
var textWidth: Int = 0
var cardViewWidth: Int = 0
var verticalAnimationOffset: Int = 0
var duration = DEFAULT_DURATION
var showVerticalTranslateAnimation: Boolean = true
init {
inflate(context, R.layout.view_notifier, this)
ViewCompat.setTranslationZ(this, Integer.MAX_VALUE.toFloat())
cardView.scaleX = SCALE_MINI
cardView.scaleY = SCALE_MINI
verticalAnimationOffset = dp2px(100F)
navigationHeight = retrieveNavigationHeight()
rightToLeftPath = Path()
leftToRightPath = Path()
showAnimatorSet = AnimatorSet()
hideAnimatorSet = AnimatorSet()
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
centerX = (left + right - cardViewWidth) / 2F
// TODO Provide method to change these absolute offset.
val r = right - dp2px(72F).toFloat()
val b = bottom - dp2px(145F).toFloat() - navigationHeight
// Only set
if (veryRight != r || veryBottom != b) {
veryRight = r
veryBottom = b
rightToLeftPath.moveTo(r, b)
rightToLeftPath.lineTo(centerX, b)
leftToRightPath.moveTo(centerX, b)
leftToRightPath.lineTo(r, b)
initAnimator()
}
}
private fun initAnimator() {
expandAnimator = ValueAnimator.ofFloat(0F, 1F)
expandAnimator.duration = DEFAULT_DURATION
expandAnimator.addUpdateListener { a ->
val progress = a?.animatedValue as Float
tvText.width = (textWidth * progress).toInt()
}
expandAnimator.doOnEnd {
enableSwipeToDismiss()
shrinkAfterDelay()
}
shrinkAnimator = ValueAnimator.ofFloat(1F, 0F)
shrinkAnimator.duration = DEFAULT_DURATION
shrinkAnimator.addUpdateListener { a ->
val progress = a?.animatedValue as Float
tvText.width = (textWidth * progress).toInt()
}
shrinkAnimator.doOnEnd {
val lp = FrameLayout.LayoutParams(cardView.layoutParams)
lp.gravity = Gravity.NO_GRAVITY
cardView.layoutParams = lp
disableSwipeToDismiss()
}
translateToLeftAnimator = ObjectAnimator.ofFloat(cardView, "translationX", veryRight, centerX)
translateToLeftAnimator.duration = DEFAULT_DURATION
translateToLeftAnimator.doOnEnd {
onShowListener?.onShow()
val lp = FrameLayout.LayoutParams(cardView.layoutParams)
lp.gravity = Gravity.CENTER_HORIZONTAL
cardView.layoutParams = lp
cardView.translationX = 0f
expandAnimator.start()
}
translateToRightAnimator = ObjectAnimator.ofFloat(cardView, "translationX", centerX, veryRight)
translateToRightAnimator.duration = DEFAULT_DURATION
translateUpAnimator = ObjectAnimator.ofFloat(cardView, "translationY", veryBottom + verticalAnimationOffset, veryBottom)
translateUpAnimator.duration = DEFAULT_DURATION
translateUpAnimator.doOnStart { cardView.translationX = veryRight }
translateDownAnimator = ObjectAnimator.ofFloat(cardView, "translationY", veryBottom, veryBottom + verticalAnimationOffset)
translateDownAnimator.duration = DEFAULT_DURATION
zoomInAnimator = ObjectAnimator.ofPropertyValuesHolder(cardView, PropertyValuesHolder.ofFloat("scaleX", SCALE_DEFAULT),
PropertyValuesHolder.ofFloat("scaleY", SCALE_DEFAULT))
zoomInAnimator.duration = DEFAULT_DURATION
zoomInAnimator.doOnStart { cardView.translationX = veryRight }
zoomInAnimator.doOnStart { cardView.translationY = veryBottom }
zoomOutAnimator = ObjectAnimator.ofPropertyValuesHolder(cardView, PropertyValuesHolder.ofFloat("scaleX", SCALE_MINI),
PropertyValuesHolder.ofFloat("scaleY", SCALE_MINI))
zoomOutAnimator.duration = DEFAULT_DURATION
zoomOutAnimator.doOnEnd { removeFromParent() }
if (showVerticalTranslateAnimation) {
showAnimatorSet.play(translateUpAnimator).with(zoomInAnimator).before(translateToLeftAnimator)
} else {
showAnimatorSet.play(zoomInAnimator).before(translateToLeftAnimator)
}
showAnimatorSet.start()
}
private fun enableSwipeToDismiss() {
cardView?.setOnTouchListener(SwipeDismissTouchListener(cardView, object : SwipeDismissTouchListener.DismissCallbacks {
override fun canDismiss(): Boolean {
return true
}
override fun onDismiss(view: View) {
removeFromParent()
}
override fun onTouch(view: View, touch: Boolean) {
// Ignore.
}
}))
}
private fun disableSwipeToDismiss() {
cardView?.setOnTouchListener(null)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
showAnimatorSet.cancel()
hideAnimatorSet.cancel()
removeAllListeners(expandAnimator,
shrinkAnimator,
translateUpAnimator,
translateDownAnimator,
translateToLeftAnimator,
translateToRightAnimator)
}
private fun removeAllListeners(vararg ts: Animator) {
for (a in ts) {
a.removeAllListeners()
if (a is ValueAnimator) {
a.removeAllUpdateListeners()
}
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
performClick()
return super.onTouchEvent(event)
}
private fun shrinkAfterDelay() {
postDelayed({ shrink() }, duration)
}
fun shrink() {
shrinkAnimator.doOnEnd { hide() }
shrinkAnimator.start()
}
private fun removeFromParent() {
clearAnimation()
visibility = View.GONE
postDelayed(object : Runnable {
override fun run() {
try {
if (parent == null) {
Log.e(javaClass.simpleName, "getParent() returning Null")
} else {
try {
(parent as ViewGroup).removeView(this@NotifierView)
onHideListener?.onHide()
} catch (ex: Exception) {
Log.e(javaClass.simpleName, "Cannot remove from parent layout")
}
}
} catch (ex: Exception) {
Log.e(javaClass.simpleName, Log.getStackTraceString(ex))
}
}
}, 100)
}
fun setText(text: String?) {
if (!TextUtils.isEmpty(text)) {
tvText.text = text
tvText.measure(0, 0)
textWidth = tvText.measuredWidth
tvText.width = 0
cardView.measure(0, 0)
cardViewWidth = cardView.measuredWidth
}
}
fun hide() {
if (showVerticalTranslateAnimation) {
hideAnimatorSet.play(translateDownAnimator).with(zoomOutAnimator).after(translateToRightAnimator)
} else {
hideAnimatorSet.play(zoomOutAnimator).after(translateToRightAnimator)
}
hideAnimatorSet.start()
}
fun setIcon(url: String) {
ImageUtils.display(ivIcon, url)
}
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
}
interface OnShowNotificationListener {
fun onShow()
}
interface OnHideNotificationListener {
fun onHide()
}
}

View File

@ -0,0 +1,238 @@
package com.gh.common.notifier
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Modifications Copyright (C) 2017 David Kwon
*/
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.os.Build
import android.support.annotation.RequiresApi
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.View
import android.view.ViewConfiguration
/**
* A [View.OnTouchListener] that makes any [View] dismissable when the
* user swipes (drags her finger) horizontally across the view.
*
* @param view The view to make dismissable.
* @param callbacks The callback to trigger when the user has indicated that she would like to
* dismiss this view.
*/
class SwipeDismissTouchListener(
private val mView: View,
private val mCallbacks: DismissCallbacks) : View.OnTouchListener {
// Cached ViewConfiguration and system-wide constant values
private val mSlop: Int
private val mMinFlingVelocity: Int
private val mAnimationTime: Long
private var mViewWidth = 1 // 1 and not 0 to prevent dividing by zero
// Transient properties
private var mDownX: Float = 0.toFloat()
private var mDownY: Float = 0.toFloat()
private var mSwiping: Boolean = false
private var mSwipingSlop: Int = 0
private var mVelocityTracker: VelocityTracker? = null
private var mTranslationX: Float = 0.toFloat()
init {
val vc = ViewConfiguration.get(mView.context)
mSlop = vc.scaledTouchSlop
mMinFlingVelocity = vc.scaledMinimumFlingVelocity * 16
mAnimationTime = mView.context.resources.getInteger(
android.R.integer.config_shortAnimTime).toLong()
}
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB_MR1)
override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
// offset because the view is translated during swipe
motionEvent.offsetLocation(mTranslationX, 0f)
if (mViewWidth < 2) {
mViewWidth = mView.width
}
when (motionEvent.actionMasked) {
MotionEvent.ACTION_DOWN -> {
mDownX = motionEvent.rawX
mDownY = motionEvent.rawY
if (mCallbacks.canDismiss()) {
mVelocityTracker = VelocityTracker.obtain()
mVelocityTracker!!.addMovement(motionEvent)
}
mCallbacks.onTouch(view, true)
return false
}
MotionEvent.ACTION_UP -> {
mVelocityTracker?.run {
val deltaX = motionEvent.rawX - mDownX
this.addMovement(motionEvent)
this.computeCurrentVelocity(1000)
val velocityX = this.xVelocity
val absVelocityX = Math.abs(velocityX)
val absVelocityY = Math.abs(this.yVelocity)
var dismiss = false
var dismissRight = false
if (Math.abs(deltaX) > mViewWidth / 2 && mSwiping) {
dismiss = true
dismissRight = deltaX > 0
} else if (mMinFlingVelocity <= absVelocityX && absVelocityY < absVelocityX && mSwiping) {
// dismiss only if flinging in the same direction as dragging
dismiss = velocityX < 0 == deltaX < 0
dismissRight = this.xVelocity > 0
}
if (dismiss) {
// dismiss
mView.animate()
.translationX((if (dismissRight) mViewWidth else -mViewWidth).toFloat())
.alpha(0f)
.setDuration(mAnimationTime)
.setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
performDismiss()
}
})
} else if (mSwiping) {
// cancel
mView.animate()
.translationX(0f)
.alpha(1f)
.setDuration(mAnimationTime)
.setListener(null)
mCallbacks.onTouch(view, false)
}
this.recycle()
mVelocityTracker = null
mTranslationX = 0f
mDownX = 0f
mDownY = 0f
mSwiping = false
}
}
MotionEvent.ACTION_CANCEL -> {
mVelocityTracker?.run {
mView.animate()
.translationX(0f)
.alpha(1f)
.setDuration(mAnimationTime)
.setListener(null)
this.recycle()
mVelocityTracker = null
mTranslationX = 0f
mDownX = 0f
mDownY = 0f
mSwiping = false
}
}
MotionEvent.ACTION_MOVE -> {
mVelocityTracker?.run {
this.addMovement(motionEvent)
val deltaX = motionEvent.rawX - mDownX
val deltaY = motionEvent.rawY - mDownY
if (Math.abs(deltaX) > mSlop && Math.abs(deltaY) < Math.abs(deltaX) / 2) {
mSwiping = true
mSwipingSlop = if (deltaX > 0) mSlop else -mSlop
mView.parent.requestDisallowInterceptTouchEvent(true)
// Cancel listview's touch
val cancelEvent = MotionEvent.obtain(motionEvent)
cancelEvent.action = MotionEvent.ACTION_CANCEL or (motionEvent.actionIndex shl MotionEvent.ACTION_POINTER_INDEX_SHIFT)
mView.onTouchEvent(cancelEvent)
cancelEvent.recycle()
}
if (mSwiping) {
mTranslationX = deltaX
mView.translationX = deltaX - mSwipingSlop
// TODO: use an ease-out interpolator or such
mView.alpha = Math.max(0f, Math.min(1f,
1f - 2f * Math.abs(deltaX) / mViewWidth))
return true
}
}
}
else -> {
view.performClick()
return false
}
}
return false
}
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
private fun performDismiss() {
// Animate the dismissed view to zero-height and then fire the dismiss callback.
// This triggers layout on each animation frame; in the future we may want to do something
// smarter and more performant.
val lp = mView.layoutParams
val originalHeight = mView.height
val animator = ValueAnimator.ofInt(originalHeight, 1).setDuration(mAnimationTime)
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
mCallbacks.onDismiss(mView)
// Reset view presentation
mView.alpha = 1f
mView.translationX = 0f
lp.height = originalHeight
mView.layoutParams = lp
}
})
animator.addUpdateListener { valueAnimator ->
lp.height = valueAnimator.animatedValue as Int
mView.layoutParams = lp
}
animator.start()
}
/**
* The callback interface used by [SwipeDismissTouchListener] to inform its client
* about a successful dismissal of the view for which it was created.
*/
interface DismissCallbacks {
/**
* Called to determine whether the view can be dismissed.
*
* @return boolean The view can dismiss.
*/
fun canDismiss(): Boolean
/**
* Called when the user has indicated they she would like to dismiss the view.
*
* @param view The originating [View]
*/
fun onDismiss(view: View)
/**
* Called when the user touches the view or release the view.
*
* @param view The originating [View]
* @param touch The view is being touched.
*/
fun onTouch(view: View, touch: Boolean)
}
}

View File

@ -0,0 +1,128 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gh.common.util
import android.animation.Animator
import android.support.annotation.RequiresApi
/**
* Since [Android KTX] has not release a stable build yet,
* we copy a single class to achieve the same goal.
*
* You might check the original extension class in the link below.
*
* https://github.com/android/android-ktx/blob/master/src/main/java/androidx/core/animation/Animator.kt.
*/
/**
* Add an action which will be invoked when the animation has ended.
*
* @return the [Animator.AnimatorListener] added to the Animator
* @see Animator.end
*/
fun Animator.doOnEnd(action: (animator: Animator) -> Unit) = addListener(onEnd = action)
/**
* Add an action which will be invoked when the animation has started.
*
* @return the [Animator.AnimatorListener] added to the Animator
* @see Animator.start
*/
fun Animator.doOnStart(action: (animator: Animator) -> Unit) = addListener(onStart = action)
/**
* Add an action which will be invoked when the animation has been cancelled.
*
* @return the [Animator.AnimatorListener] added to the Animator
* @see Animator.cancel
*/
fun Animator.doOnCancel(action: (animator: Animator) -> Unit) = addListener(onCancel = action)
/**
* Add an action which will be invoked when the animation has repeated.
* @return the [Animator.AnimatorListener] added to the Animator
*/
fun Animator.doOnRepeat(action: (animator: Animator) -> Unit) = addListener(onRepeat = action)
/**
* Add an action which will be invoked when the animation has resumed after a pause.
*
* @return the [Animator.AnimatorPauseListener] added to the Animator
* @see Animator.resume
*/
@RequiresApi(19)
fun Animator.doOnResume(action: (animator: Animator) -> Unit) = addPauseListener(onResume = action)
/**
* Add an action which will be invoked when the animation has been paused.
*
* @return the [Animator.AnimatorPauseListener] added to the Animator
* @see Animator.pause
*/
@RequiresApi(19)
fun Animator.doOnPause(action: (animator: Animator) -> Unit) = addPauseListener(onPause = action)
/**
* Add a listener to this Animator using the provided actions.
*/
fun Animator.addListener(
onEnd: ((animator: Animator) -> Unit)? = null,
onStart: ((animator: Animator) -> Unit)? = null,
onCancel: ((animator: Animator) -> Unit)? = null,
onRepeat: ((animator: Animator) -> Unit)? = null
): Animator.AnimatorListener {
val listener = object : Animator.AnimatorListener {
override fun onAnimationRepeat(animator: Animator) {
onRepeat?.invoke(animator)
}
override fun onAnimationEnd(animator: Animator) {
onEnd?.invoke(animator)
}
override fun onAnimationCancel(animator: Animator) {
onCancel?.invoke(animator)
}
override fun onAnimationStart(animator: Animator) {
onStart?.invoke(animator)
}
}
addListener(listener)
return listener
}
/**
* Add a pause and resume listener to this Animator using the provided actions.
*/
@RequiresApi(19)
fun Animator.addPauseListener(
onResume: ((animator: Animator) -> Unit)? = null,
onPause: ((animator: Animator) -> Unit)? = null
): Animator.AnimatorPauseListener {
val listener = object : Animator.AnimatorPauseListener {
override fun onAnimationPause(animator: Animator) {
onPause?.invoke(animator)
}
override fun onAnimationResume(animator: Animator) {
onResume?.invoke(animator)
}
}
addPauseListener(listener)
return listener
}

View File

@ -22,7 +22,7 @@ public class ApkActiveUtils {
ApkEntity apkEntity = apkList.get(i);
String packageName = apkEntity.getPackageName();
String id = gameEntity.getId();
if (!apkEntity.isActive() && !PackageManager.isCanPluggable(id, packageName)) {
if (!apkEntity.isActive() && !PackageManager.INSTANCE.isCanPluggable(id, packageName)) {
apkList.remove(i);
i--;
}

View File

@ -1,143 +0,0 @@
package com.gh.common.util;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
/**
* 应用程序Activity管理类用于Activity和Intent相关的管理
*
* @author CsHeng
* @version 1.0
*/
public class AppManager {
private static AppManager mInstance;
private Stack<Activity> mActivityStack;
private AppManager() {
mActivityStack = new Stack<>();
}
/**
* 单一实例
*/
public static AppManager getInstance() {
if (mInstance == null) {
mInstance = new AppManager();
}
return mInstance;
}
public boolean isEmpty() {
return mActivityStack.isEmpty();
}
/**
* 添加Activity到堆栈
*/
public void addActivity(Activity activity) {
mActivityStack.add(activity);
}
/**
* 获取当前Activity堆栈中最后一个压入的
*/
public Activity currentActivity() {
return mActivityStack.lastElement();
}
/**
* 结束当前Activity堆栈中最后一个压入的
*/
public void finishActivity() {
final Activity activity = mActivityStack.lastElement();
finishActivity(activity);
}
/**
* 结束指定的Activity
*/
public void finishActivity(Activity activity) {
if (activity != null) {
mActivityStack.remove(activity);
activity.finish();
}
}
/**
* 结束指定类名的Activity
*/
public void finishActivity(Class<?> cls) {
for (Activity activity : mActivityStack) {
if (activity.getClass().equals(cls)) {
finishActivity(activity);
}
}
}
public boolean isOnStack(Activity activity) {
return mActivityStack.contains(activity);
}
public Intent[] getStartIntents(Intent... intent) {
List<Intent> intentList = getCurrentIntents();
if (intentList != null) {
Collections.addAll(intentList, intent);
return intentList.toArray(new Intent[intentList.size()]);
}
return intent;
}
public List<Intent> getCurrentIntents() {
List<Intent> intentList = new ArrayList<>();
for (Activity activity : mActivityStack) {
intentList.add(activity.getIntent());
}
return intentList;
}
/**
* 退出应用程序
*/
public void appExit(Context context) {
try {
finishAllActivity();
/* Need Permission */
// ActivityManager activityMgr= (ActivityManager)
// context.getSystemService(Context.ACTIVITY_SERVICE);
// activityMgr.restartPackage(context.getPackageName());
// activityMgr.killBackgroundProcesses(context.getPackageName());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 结束所有Activity
*/
public void finishAllActivity() {
for (Activity activity : mActivityStack) {
activity.finish();
}
mActivityStack.clear();
try {
android.os.Process.killProcess(android.os.Process.myPid());
} catch (Exception e) {
}
}
public void destroy() {
if (mActivityStack != null) {
mActivityStack.clear();
}
mInstance = null;
}
}

View File

@ -0,0 +1,90 @@
package com.gh.common.util;
import android.content.Context;
import com.lightgame.utils.Utils;
import org.json.JSONObject;
import retrofit2.HttpException;
/**
* Created by khy on 28/12/17.
*/
public class AskErrorResponseUtils {
public static void errorResponseControl(Context context, HttpException e) {
if (e == null) return;
int code = e.code();
try {
if (code == 403) {
JSONObject object = new JSONObject(e.response().errorBody().string());
int errorCode = object.getInt("code");
switch (errorCode) {
case 403001:
Utils.toast(context, "标签名称太长了");
break;
case 403002:
Utils.toast(context, "已经被邀请了");
break;
case 403003:
Utils.toast(context, "每天最多只能邀请10次");
break;
case 403004:
Utils.toast(context, "客户端提供的ID无效空/无效ID");
break;
case 403005:
Utils.toast(context, "已经回答过了(限制频率)");
break;
case 403006:
Utils.toast(context, "图片数量达到限制点");
break;
case 403007:
Utils.toast(context, "不合法的用户");
break;
case 403008:
Utils.toast(context, "已投票");
break;
case 403009:
Utils.toast(context, "已经收藏过了");
break;
case 403010:
Utils.toast(context, "无效的标签栏");
break;
case 403011:
Utils.toast(context, "标题内容过长");
break;
case 403012:
Utils.toast(context, "描述内容过长");
break;
case 403013:
Utils.toast(context, "无效的标签");
break;
case 403014:
Utils.toast(context, "标签数量太多了");
break;
case 403015:
Utils.toast(context, "已经关注过了");
break;
default:
Utils.toast(context, "网络错误");
break;
}
} else if (code == 401) {
JSONObject object = new JSONObject(e.response().errorBody().string());
int errorCode = object.getInt("code");
if (errorCode == 404001) {
Utils.toast(context, "请求的资源不存在");
}
} else {
Utils.toast(context, "网络错误");
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
}

View File

@ -0,0 +1,49 @@
package com.gh.common.util;
import android.text.TextUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by khy on 27/12/17.
*/
public class AskUtils {
// public static String voteCountFormat(int voteCount) {
// String vote;
// if (voteCount >= 10000) {
// DecimalFormat df = new DecimalFormat("#.0万");
// vote = df.format(voteCount / 10000f);
// } else {
// vote = String.valueOf(voteCount);
// }
// return vote;
// }
public static String stripHtml(String htmlStr) {
if (TextUtils.isEmpty(htmlStr)) return "";
String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
String regEx_html = "<[^>]+>"; //定义HTML标签的正则表达式
Pattern p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
Matcher m_script = p_script.matcher(htmlStr);
htmlStr = m_script.replaceAll(""); //过滤script标签
Pattern p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
Matcher m_style = p_style.matcher(htmlStr);
htmlStr = m_style.replaceAll(""); //过滤style标签
Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
Matcher m_html = p_html.matcher(htmlStr);
htmlStr = m_html.replaceAll(""); //过滤html标签
return htmlStr.trim(); //返回文本字符串
}
}

View File

@ -9,6 +9,7 @@ import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@ -27,13 +28,16 @@ public class BitmapUtils {
*/
public static boolean savePicture(String newPath, String filePath) {
BitmapFactory.Options options = new BitmapFactory.Options();
// options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
options.inSampleSize = 2;
options.inJustDecodeBounds = false;
File file = new File(newPath);
int quality = 80;
do {
try {
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, bos);
bos.flush();
@ -51,6 +55,62 @@ public class BitmapUtils {
return true;
}
/**
* 保存图片
*
* @param newPath
* @param filePath
* @return
*/
public static boolean savePicture(String newPath, String filePath, int compressSize) {
if (compressSize > new File(filePath).length()) {
return false;
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
options.inSampleSize = 2;
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, bos);
float zoom = (float) Math.sqrt(compressSize / (float) bos.toByteArray().length);
Matrix matrix = new Matrix();
matrix.setScale(zoom, zoom);
Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bos.reset();
bitmap.recycle();
result.compress(Bitmap.CompressFormat.JPEG, 85, bos);
while (bos.toByteArray().length > compressSize) {
matrix.setScale(0.9f, 0.9f);
result = Bitmap.createBitmap(result, 0, 0, result.getWidth(), result.getHeight(), matrix, true);
bos.reset();
result.compress(Bitmap.CompressFormat.JPEG, 85, bos);
}
File file = new File(newPath);
try {
BufferedOutputStream fbos = new BufferedOutputStream(new FileOutputStream(file));
result.compress(Bitmap.CompressFormat.JPEG, 85, fbos);
fbos.flush();
fbos.close();
result.recycle();
} catch (Exception e) {
file.delete();
e.printStackTrace();
return false;
}
return true;
}
/**
* 根据文件路径返回bitmap
*

View File

@ -0,0 +1,36 @@
package com.gh.common.util;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import com.gh.gamecenter.LoginActivity;
import com.gh.gamecenter.manager.UserManager;
import com.lightgame.utils.Utils;
/**
* Created by khy on 28/06/17.
*/
public class CheckLoginUtils {
public static void checkLogin(final Context context, OnLoginListener listener) {
if (TextUtils.isEmpty(UserManager.getInstance().getToken())) {
Utils.toast(context, "需要登录");
LogUtils.login(context, "dialog", null);
LogUtils.login(context, "activity", null);
Intent intent = LoginActivity.getIntent(context);
context.startActivity(intent);
} else {
listener.onLogin();
}
}
public static boolean isLogin() {
return !TextUtils.isEmpty(UserManager.getInstance().getToken());
}
public interface OnLoginListener {
void onLogin();
}
}

View File

@ -10,7 +10,11 @@ public class ClassUtils {
name = "GameDetailActivity";
}
try {
return Class.forName("com.gh.gamecenter." + name);
if (!name.contains("com.gh")) {
return Class.forName("com.gh.gamecenter." + name);
} else {
return Class.forName(name);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

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